Merge branch 'dev'
This commit is contained in:
commit
bb83fa922c
@ -93,9 +93,9 @@ if(NOT WIN32 OR MINGW)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
check_support(HAS_DL_FIND_OBJECT has_dl_find_object.cpp "" "" "")
|
||||
check_support(HAS_DL_FIND_OBJECT has_dl_find_object.cpp "" "dl" "")
|
||||
if(NOT HAS_DL_FIND_OBJECT)
|
||||
check_support(HAS_DLADDR1 has_dladdr1.cpp "" "" "")
|
||||
check_support(HAS_DLADDR1 has_dladdr1.cpp "" "dl" "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
|
||||
int main() {
|
||||
Dl_info info;
|
||||
|
||||
@ -1,33 +1,24 @@
|
||||
#ifndef MICROFMT_HPP
|
||||
#define MICROFMT_HPP
|
||||
|
||||
// Copyright (c) 2024 Jeremy Rifkin; MIT License
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
#include <string_view>
|
||||
#include <string_view>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
// {[[align][width]:[fill][base]]}
|
||||
// width: number or {}
|
||||
// https://github.com/jeremy-rifkin/microfmt
|
||||
// Format: {[align][width][:[fill][base]]} # width: number or {}
|
||||
|
||||
namespace microfmt {
|
||||
namespace detail {
|
||||
#define STR2(x) #x
|
||||
#define STR(x) STR2(x)
|
||||
#define MICROFMT_ASSERT(expr) if(!(expr)) { \
|
||||
throw std::runtime_error("Microfmt check failed" __FILE__ ":" STR(__LINE__) ": " #expr); \
|
||||
}
|
||||
|
||||
inline std::uint64_t clz(std::uint64_t value) {
|
||||
#ifdef _MSC_VER
|
||||
unsigned long out = 0;
|
||||
@ -60,7 +51,6 @@ namespace microfmt {
|
||||
|
||||
template<typename It> void do_write(std::string& out, It begin, It end, const format_options& options) {
|
||||
auto size = end - begin;
|
||||
MICROFMT_ASSERT(size >= 0);
|
||||
if(static_cast<std::size_t>(size) >= options.width) {
|
||||
out.append(begin, end);
|
||||
} else {
|
||||
@ -100,13 +90,11 @@ namespace microfmt {
|
||||
|
||||
inline std::string to_string(std::uint64_t value, const format_options& options) {
|
||||
switch(options.base) {
|
||||
case 'd': return std::to_string(value);
|
||||
case 'H': return to_string<4, 0xf>(value, "0123456789ABCDEF");
|
||||
case 'h': return to_string<4, 0xf>(value);
|
||||
case 'o': return to_string<3, 0x7>(value);
|
||||
case 'b': return to_string<1, 0x1>(value);
|
||||
default:
|
||||
MICROFMT_ASSERT(false);
|
||||
default: return std::to_string(value); // failure: decimal
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +142,7 @@ namespace microfmt {
|
||||
switch(value) {
|
||||
case value_type::int64_value: return static_cast<int>(int64_value);
|
||||
case value_type::uint64_value: return static_cast<int>(uint64_value);
|
||||
default: MICROFMT_ASSERT(false);
|
||||
default: return 0; // failure: just 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,108 +181,84 @@ namespace microfmt {
|
||||
case value_type::c_string_value:
|
||||
do_write(out, c_string_value, c_string_value + std::strlen(c_string_value), options);
|
||||
break;
|
||||
default:
|
||||
MICROFMT_ASSERT(false);
|
||||
}
|
||||
} // failure: nop
|
||||
}
|
||||
};
|
||||
|
||||
inline int parse_int(const char* begin, const char* end) {
|
||||
int x = 0;
|
||||
for(auto it = begin; it != end; it++) {
|
||||
MICROFMT_ASSERT(isdigit(*it));
|
||||
x *= 10;
|
||||
x += *it - '0';
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
std::string format(const char* fmt_begin, const char* fmt_end, std::array<format_value, N> args) {
|
||||
template<std::size_t N, typename It>
|
||||
std::string format(It fmt_begin, It fmt_end, std::array<format_value, N> args) {
|
||||
std::string str;
|
||||
std::size_t arg_i = 0;
|
||||
auto it = fmt_begin;
|
||||
auto peek = [&] (std::size_t dist) -> char { // 0 on failure
|
||||
if(it != fmt_end) {
|
||||
return *(it + dist);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return fmt_end - it > signed(dist) ? *(it + dist) : 0;
|
||||
};
|
||||
auto read_number = [&] () -> int { // -1 on failure
|
||||
auto scan = it;
|
||||
int num = 0;
|
||||
while(scan != fmt_end && isdigit(*scan)) {
|
||||
num *= 10;
|
||||
num += *scan - '0';
|
||||
scan++;
|
||||
}
|
||||
if(scan != it) {
|
||||
int val = parse_int(it, scan);
|
||||
it = scan;
|
||||
return val;
|
||||
return num;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
while(it != fmt_end) {
|
||||
if(*it == '{') {
|
||||
if(peek(1) == '{') {
|
||||
// try to handle escape
|
||||
str += '{';
|
||||
for(; it != fmt_end; it++) {
|
||||
if((*it == '{' || *it == '}') && peek(1) == *it) { // parse {{ and }} escapes
|
||||
it++;
|
||||
} else if(*it == '{' && it + 1 != fmt_end) {
|
||||
auto saved_it = it;
|
||||
auto handle_formatter = [&] () {
|
||||
it++;
|
||||
} else {
|
||||
// parse format string
|
||||
it++;
|
||||
MICROFMT_ASSERT(it != fmt_end);
|
||||
format_options options;
|
||||
// try to parse alignment
|
||||
if(*it == '<' || *it == '>') {
|
||||
options.align = *it == '<' ? alignment::left : alignment::right;
|
||||
it++;
|
||||
options.align = *it++ == '<' ? alignment::left : alignment::right;
|
||||
}
|
||||
// try to parse width
|
||||
auto width = read_number();
|
||||
auto width = read_number(); // handles fmt_end check
|
||||
if(width != -1) {
|
||||
options.width = width;
|
||||
} else if(*it == '{') { // try to parse variable width
|
||||
MICROFMT_ASSERT(peek(1) == '}');
|
||||
} else if(it != fmt_end && *it == '{') { // try to parse variable width
|
||||
if(peek(1) != '}') {
|
||||
return false;
|
||||
}
|
||||
it += 2;
|
||||
MICROFMT_ASSERT(arg_i < args.size());
|
||||
options.width = args[arg_i++].unwrap_int();
|
||||
options.width = arg_i < args.size() ? args[arg_i++].unwrap_int() : 0;
|
||||
}
|
||||
// try to parse fill/base
|
||||
if(*it == ':') {
|
||||
if(it != fmt_end && *it == ':') {
|
||||
it++;
|
||||
// try to parse fill
|
||||
if(*it != '}' && peek(1) != '}') {
|
||||
// two chars before the }, treat as fill+base
|
||||
if(fmt_end - it > 1 && *it != '}' && peek(1) != '}') { // two chars before the }, fill+base
|
||||
options.fill = *it++;
|
||||
options.base = *it++;
|
||||
} else if(*it != '}') {
|
||||
// one char before the }, treat as base if possible
|
||||
} else if(it != fmt_end && *it != '}') { // one char before the }, just base
|
||||
if(*it == 'd' || *it == 'h' || *it == 'H' || *it == 'o' || *it == 'b') {
|
||||
options.base = *it++;
|
||||
} else {
|
||||
options.fill = *it++;
|
||||
}
|
||||
} else {
|
||||
MICROFMT_ASSERT(false);
|
||||
}
|
||||
}
|
||||
MICROFMT_ASSERT(*it == '}');
|
||||
MICROFMT_ASSERT(arg_i < args.size());
|
||||
args[arg_i++].write(str, options);
|
||||
if(it == fmt_end || *it != '}') {
|
||||
return false;
|
||||
}
|
||||
if(arg_i < args.size()) {
|
||||
args[arg_i++].write(str, options);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if(handle_formatter()) {
|
||||
continue; // If reached here, successfully parsed and wrote a formatter. Don't write *it.
|
||||
}
|
||||
} else if(*it == '}') {
|
||||
// parse }} escape
|
||||
if(peek(1) == '}') {
|
||||
str += '}';
|
||||
it++;
|
||||
} else {
|
||||
MICROFMT_ASSERT(false);
|
||||
}
|
||||
} else {
|
||||
str += *it;
|
||||
it = saved_it; // go back
|
||||
}
|
||||
it++;
|
||||
str += *it;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@ -306,8 +270,9 @@ namespace microfmt {
|
||||
return detail::format<sizeof...(args)>(fmt.begin(), fmt.end(), {detail::format_value(args)...});
|
||||
}
|
||||
|
||||
// working around an old msvc bug https://godbolt.org/z/88T8hrzzq mre: https://godbolt.org/z/drd8echbP
|
||||
inline std::string format(std::string_view fmt) {
|
||||
return std::string(fmt);
|
||||
return detail::format<1>(fmt.begin(), fmt.end(), {detail::format_value(1)});
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -316,7 +281,6 @@ namespace microfmt {
|
||||
return detail::format<sizeof...(args)>(fmt, fmt + std::strlen(fmt), {detail::format_value(args)...});
|
||||
}
|
||||
|
||||
// working around an old msvc bug https://godbolt.org/z/88T8hrzzq mre: https://godbolt.org/z/drd8echbP
|
||||
inline std::string format(const char* fmt) {
|
||||
return detail::format<1>(fmt, fmt + std::strlen(fmt), {detail::format_value(1)});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user