alternative form
parent
b2c3820ed0
commit
25187319ab
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.20)
|
||||
include(cmake/color.cmake)
|
||||
set(BLT_VERSION 5.1.3)
|
||||
set(BLT_VERSION 5.1.4)
|
||||
|
||||
set(BLT_TARGET BLT)
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ namespace blt::logging
|
|||
COLON,
|
||||
DOT,
|
||||
MINUS,
|
||||
PLUS
|
||||
PLUS,
|
||||
POUND
|
||||
};
|
||||
|
||||
enum class fmt_sign_t : u8
|
||||
|
@ -66,6 +67,7 @@ namespace blt::logging
|
|||
fmt_sign_t sign = fmt_sign_t::MINUS;
|
||||
bool leading_zeros = false;
|
||||
bool uppercase = false;
|
||||
bool alternate_form = false;
|
||||
};
|
||||
|
||||
struct fmt_token_t
|
||||
|
@ -121,10 +123,15 @@ namespace blt::logging
|
|||
private:
|
||||
void parse_fmt_field();
|
||||
void parse_arg_id();
|
||||
void parse_fmt_spec_stage_1();
|
||||
void parse_fmt_spec_stage_2();
|
||||
void parse_fmt_spec_stage_3();
|
||||
|
||||
void parse_fmt_spec();
|
||||
void parse_fmt_spec_sign();
|
||||
void parse_fmt_spec_form();
|
||||
void parse_fmt_spec_width();
|
||||
void parse_fmt_spec_precision();
|
||||
|
||||
void parse_sign();
|
||||
void parse_form();
|
||||
void parse_width();
|
||||
void parse_precision();
|
||||
void parse_type();
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace blt::logging
|
|||
case fmt_sign_t::SPACE:
|
||||
if constexpr (std::is_arithmetic_v<T>)
|
||||
{
|
||||
if (t >= 0)
|
||||
if (type.type != fmt_type_t::BINARY && t >= 0)
|
||||
stream << ' ';
|
||||
}
|
||||
break;
|
||||
|
@ -90,6 +90,7 @@ namespace blt::logging
|
|||
{
|
||||
char buffer[sizeof(T)];
|
||||
std::memcpy(buffer, &t, sizeof(T));
|
||||
if (type.alternate_form)
|
||||
stream << '0' << (type.uppercase ? 'B' : 'b');
|
||||
for (size_t i = 0; i < sizeof(T); ++i)
|
||||
{
|
||||
|
@ -127,7 +128,7 @@ namespace blt::logging
|
|||
}
|
||||
break;
|
||||
default:
|
||||
handle_type(stream, type.type);
|
||||
handle_type(stream, type);
|
||||
stream << t;
|
||||
}
|
||||
};
|
||||
|
@ -135,7 +136,7 @@ namespace blt::logging
|
|||
|
||||
void setup_stream(const fmt_spec_t& spec);
|
||||
void process_strings();
|
||||
static void handle_type(std::ostream& stream, fmt_type_t type);
|
||||
static void handle_type(std::ostream& stream, const fmt_spec_t& spec);
|
||||
|
||||
static void exponential(std::ostream& stream);
|
||||
static void fixed(std::ostream& stream);
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace blt::logging
|
|||
return fmt_token_type::COLON;
|
||||
case ' ':
|
||||
return fmt_token_type::SPACE;
|
||||
case '#':
|
||||
return fmt_token_type::POUND;
|
||||
default:
|
||||
return fmt_token_type::STRING;
|
||||
}
|
||||
|
@ -62,6 +64,7 @@ namespace blt::logging
|
|||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::DOT:
|
||||
case fmt_token_type::COLON:
|
||||
case fmt_token_type::POUND:
|
||||
return fmt_token_t{base_type, std::string_view{m_fmt.data() + m_pos++, 1}};
|
||||
default:
|
||||
{
|
||||
|
@ -100,39 +103,39 @@ namespace blt::logging
|
|||
if (!has_next())
|
||||
throw std::runtime_error("Expected token when parsing format field");
|
||||
const auto [type, value] = peek();
|
||||
if (type == fmt_token_type::COLON)
|
||||
{
|
||||
consume();
|
||||
parse_fmt_spec_stage_1();
|
||||
}
|
||||
else if (type == fmt_token_type::NUMBER)
|
||||
switch (type)
|
||||
{
|
||||
case fmt_token_type::NUMBER:
|
||||
parse_arg_id();
|
||||
if (has_next())
|
||||
{
|
||||
if (peek().type == fmt_token_type::COLON)
|
||||
{
|
||||
consume();
|
||||
parse_fmt_spec_stage_1();
|
||||
}
|
||||
parse_fmt_spec();
|
||||
else
|
||||
throw std::runtime_error("Expected ':' when parsing format field after arg id!");
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
case fmt_token_type::COLON:
|
||||
parse_fmt_spec();
|
||||
break;
|
||||
case fmt_token_type::STRING:
|
||||
case fmt_token_type::SPACE:
|
||||
case fmt_token_type::DOT:
|
||||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::PLUS:
|
||||
case fmt_token_type::POUND:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Expected unknown token '" << static_cast<u8>(type) << "' value '" << value << "' when parsing format field";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
if (has_next())
|
||||
parse_type();
|
||||
}
|
||||
|
||||
void fmt_parser_t::parse_arg_id()
|
||||
{
|
||||
if (!has_next())
|
||||
throw std::runtime_error("Missing token when parsing arg id");
|
||||
const auto [type, value] = next();
|
||||
if (type != fmt_token_type::NUMBER)
|
||||
{
|
||||
|
@ -143,11 +146,10 @@ namespace blt::logging
|
|||
m_spec.arg_id = std::stoll(std::string(value));
|
||||
}
|
||||
|
||||
// handle start of fmt, with sign
|
||||
void fmt_parser_t::parse_fmt_spec_stage_1()
|
||||
void fmt_parser_t::parse_fmt_spec()
|
||||
{
|
||||
if (!has_next())
|
||||
return;
|
||||
// consume :
|
||||
consume();
|
||||
auto [type, value] = peek();
|
||||
switch (type)
|
||||
{
|
||||
|
@ -155,29 +157,89 @@ namespace blt::logging
|
|||
case fmt_token_type::COLON:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(Stage 1) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
ss << "(Stage (Begin)) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
case fmt_token_type::NUMBER:
|
||||
parse_width();
|
||||
parse_fmt_spec_stage_3();
|
||||
parse_fmt_spec_width();
|
||||
break;
|
||||
case fmt_token_type::DOT:
|
||||
consume();
|
||||
parse_precision();
|
||||
parse_fmt_spec_precision();
|
||||
break;
|
||||
case fmt_token_type::SPACE:
|
||||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::PLUS:
|
||||
parse_fmt_spec_sign();
|
||||
break;
|
||||
case fmt_token_type::POUND:
|
||||
parse_fmt_spec_form();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// handle start of fmt, with sign
|
||||
void fmt_parser_t::parse_fmt_spec_sign()
|
||||
{
|
||||
parse_sign();
|
||||
parse_fmt_spec_stage_2();
|
||||
if (!has_next())
|
||||
return;
|
||||
auto [type, value] = peek();
|
||||
switch (type)
|
||||
{
|
||||
case fmt_token_type::SPACE:
|
||||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::PLUS:
|
||||
case fmt_token_type::STRING:
|
||||
case fmt_token_type::COLON:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(Stage (Sign)) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
case fmt_token_type::NUMBER:
|
||||
parse_fmt_spec_width();
|
||||
break;
|
||||
case fmt_token_type::DOT:
|
||||
parse_fmt_spec_precision();
|
||||
break;
|
||||
case fmt_token_type::POUND:
|
||||
parse_fmt_spec_form();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fmt_parser_t::parse_fmt_spec_form()
|
||||
{
|
||||
parse_form();
|
||||
if (!has_next())
|
||||
return;
|
||||
auto [type, value] = peek();
|
||||
switch (type)
|
||||
{
|
||||
case fmt_token_type::STRING:
|
||||
case fmt_token_type::SPACE:
|
||||
case fmt_token_type::COLON:
|
||||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::PLUS:
|
||||
case fmt_token_type::POUND:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(Stage (Form)) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
case fmt_token_type::NUMBER:
|
||||
parse_fmt_spec_width();
|
||||
break;
|
||||
case fmt_token_type::DOT:
|
||||
parse_fmt_spec_precision();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// handle width parsing
|
||||
void fmt_parser_t::parse_fmt_spec_stage_2()
|
||||
void fmt_parser_t::parse_fmt_spec_width()
|
||||
{
|
||||
parse_width();
|
||||
if (!has_next())
|
||||
return;
|
||||
auto [type, value] = peek();
|
||||
|
@ -188,45 +250,24 @@ namespace blt::logging
|
|||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::PLUS:
|
||||
case fmt_token_type::SPACE:
|
||||
case fmt_token_type::POUND:
|
||||
case fmt_token_type::NUMBER:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(Stage 2) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
ss << "(Stage (Width)) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
case fmt_token_type::NUMBER:
|
||||
parse_width();
|
||||
parse_fmt_spec_stage_3();
|
||||
break;
|
||||
case fmt_token_type::DOT:
|
||||
consume();
|
||||
parse_precision();
|
||||
parse_fmt_spec_precision();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fmt_parser_t::parse_fmt_spec_stage_3()
|
||||
void fmt_parser_t::parse_fmt_spec_precision()
|
||||
{
|
||||
if (!has_next())
|
||||
return;
|
||||
auto [type, value] = peek();
|
||||
switch (type)
|
||||
{
|
||||
case fmt_token_type::STRING:
|
||||
case fmt_token_type::COLON:
|
||||
case fmt_token_type::MINUS:
|
||||
case fmt_token_type::PLUS:
|
||||
case fmt_token_type::SPACE:
|
||||
case fmt_token_type::NUMBER:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "(Stage 3) Invalid token type " << static_cast<u8>(type) << " value " << value;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
case fmt_token_type::DOT:
|
||||
// consume .
|
||||
consume();
|
||||
parse_precision();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fmt_parser_t::parse_sign()
|
||||
|
@ -258,6 +299,12 @@ namespace blt::logging
|
|||
}
|
||||
}
|
||||
|
||||
void fmt_parser_t::parse_form()
|
||||
{
|
||||
consume();
|
||||
m_spec.alternate_form = true;
|
||||
}
|
||||
|
||||
void fmt_parser_t::parse_width()
|
||||
{
|
||||
auto [_, value] = next();
|
||||
|
@ -276,8 +323,6 @@ namespace blt::logging
|
|||
|
||||
void fmt_parser_t::parse_type()
|
||||
{
|
||||
if (!has_next())
|
||||
throw std::runtime_error("Missing token when parsing type");
|
||||
auto [_, value] = next();
|
||||
if (value.size() != 1)
|
||||
{
|
||||
|
|
|
@ -73,20 +73,26 @@ namespace blt::logging
|
|||
m_stream << *str_it;
|
||||
}
|
||||
|
||||
void logger_t::handle_type(std::ostream& stream, const fmt_type_t type)
|
||||
void logger_t::handle_type(std::ostream& stream, const fmt_spec_t& spec)
|
||||
{
|
||||
switch (type)
|
||||
switch (spec.type)
|
||||
{
|
||||
case fmt_type_t::DECIMAL:
|
||||
stream << std::dec;
|
||||
break;
|
||||
case fmt_type_t::OCTAL:
|
||||
if (spec.alternate_form)
|
||||
stream << "0";
|
||||
stream << std::oct;
|
||||
break;
|
||||
case fmt_type_t::HEX:
|
||||
if (spec.alternate_form)
|
||||
stream << (spec.uppercase ? "0X" : "0x");
|
||||
stream << std::hex;
|
||||
break;
|
||||
case fmt_type_t::HEX_FLOAT:
|
||||
if (spec.alternate_form)
|
||||
stream << (spec.uppercase ? "0X" : "0x");
|
||||
stream << std::hexfloat;
|
||||
break;
|
||||
case fmt_type_t::EXPONENT:
|
||||
|
|
|
@ -36,5 +36,7 @@ int main()
|
|||
blt::logging::println("This is a println with a with {:10}", 4120);
|
||||
blt::logging::println("This is a println with a with leading zeros {:010}", 4120);
|
||||
blt::logging::println("This is a println with a precision {:.10f}", 42.232342349);
|
||||
blt::logging::println("This is a println with hex {:.10x}", 4250);
|
||||
blt::logging::println("This is a println with hex with leading {:#.10x}", 4250);
|
||||
// blt::logging::println("This is println {}\twith a std::endl in the middle of it");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue