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