21 #include <string_view>
24 #ifndef STRFORMAT_NO_LOCALE
40 return ::malloc(size);
51 constexpr
static size_t alignment =
alignof(std::max_align_t);
60 return ::malloc(size);
93 if (size == 0) size = 1;
96 auto Alloc = [&]()->
void * {
112 size_t bufsize =
sizeof(
Header) + size;
115 }
else if (h->
next) {
148 static const double tbl[] = {
149 1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06,
150 1e+07, 1e+08, 1e+09, 1e+10, 1e+11, 1e+12, 1e+13,
153 if (exp >= 0 && exp <
static_cast<int>(
sizeof tbl /
sizeof *tbl))
155 if (exp <= 0 && exp > -
static_cast<int>(
sizeof tbl /
sizeof *tbl))
156 return 1.0 / tbl[-exp];
158 return std::pow(10.0, exp);
176 static double my_strtod(
const char *nptr,
char **endptr)
178 const char *s = nptr;
180 bool saw_digit =
false;
183 bool exp_sign =
false;
187 while (std::isspace((
unsigned char)*s)) ++s;
190 if (*s ==
'+' || *s ==
'-') {
191 if (*s ==
'-') sign =
true;
196 while (std::isdigit((
unsigned char)*s)) {
198 value = value * 10.0 + (*s -
'0');
205 while (std::isdigit((
unsigned char)*s)) {
207 value = value * 10.0 + (*s -
'0');
215 if (endptr) *endptr =
const_cast<char *
>(nptr);
220 if (*s ==
'e' || *s ==
'E') {
222 const char *exp_start = s;
223 if (*s ==
'+' || *s ==
'-') {
224 if (*s ==
'-') exp_sign =
true;
227 if (std::isdigit((
unsigned char)*s)) {
228 while (std::isdigit((
unsigned char)*s)) {
229 exp_val = exp_val * 10 + (*s -
'0');
242 int total_exp = exp_val - frac_digits;
243 if (total_exp != 0) {
253 if (!std::isfinite(value)) {
255 value = sign ? -HUGE_VAL : HUGE_VAL;
256 }
else if (value == 0.0 && saw_digit && total_exp != 0) {
261 if (endptr) *endptr =
const_cast<char *
>(s);
273 while (isspace((
unsigned char)*
p)) {
278 }
else if (*
p ==
'-') {
283 if (
p[1] ==
'x' ||
p[1] ==
'X') {
289 int c = (
unsigned char)
p[i];
290 if (c < '0' || c >
'7')
break;
300 #pragma warning(push)
301 #pragma warning(disable: 4146)
304 template <
typename T>
static inline T
parse_number(
char const *ptr, std::function<T(
char const *p,
int radix)> conv)
317 #ifdef STRFORMAT_NO_LOCALE
320 struct lconv *
lc =
nullptr;
324 template <
typename T>
static inline T
num(
char const *value,
Option_ const &opt);
328 return parse_number<char>(value, [](
char const *p,
int radix){
329 return (
char)strtol(p,
nullptr, radix);
335 return parse_number<int32_t>(value, [](
char const *p,
int radix){
336 return strtol(p,
nullptr, radix);
342 return parse_number<uint32_t>(value, [](
char const *p,
int radix){
343 return strtoul(p,
nullptr, radix);
349 return parse_number<int64_t>(value, [](
char const *p,
int radix){
350 return strtoll(p,
nullptr, radix);
356 return parse_number<uint64_t>(value, [](
char const *p,
int radix){
357 return strtoull(p,
nullptr, radix);
360 #ifndef STRFORMAT_NO_FP
363 return parse_number<double>(value, [&opt](
char const *p,
int radix){
367 return strtod(p, nullptr);
370 return misc::my_strtod(p, nullptr);
373 return (
double)strtoll(p,
nullptr, radix);
378 template <
typename T>
static inline T
num(std::string
const &value,
Option_ const &opt)
380 return num<T>(value.data(), opt);
417 memcpy(
p->data, data, size);
456 Part *next =
p->next;
460 list->
head =
nullptr;
461 list->
last =
nullptr;
468 memset(
p->data,
c, n);
475 return "0123456789abcdef";
479 return "0123456789ABCDEF";
482 #ifndef STRFORMAT_NO_FP
485 if (std::isnan(val))
return alloc_part(
"#NAN");
486 if (std::isinf(val))
return alloc_part(
"#INF");
489 if (sign) val = -val;
491 int bufsize = precision + 400;
492 char *buf = (
char *)alloca(bufsize);
495 auto result = std::to_chars(ptr, buf + bufsize, val, std::chars_format::fixed, precision);
496 char *end = result.ptr;
499 char *dot = std::find(ptr, end,
'.');
501 while (end > dot + 1 && end[-1] ==
'0') end--;
502 if (end[-1] ==
'.') end--;
518 char *end = (
char *)alloca(n) + n - 1;
525 bool sign = (val < 0);
533 int c = v % 10 +
'0';
539 }
else if (force_sign) {
549 char *end = (
char *)alloca(n) + n - 1;
557 int c = val % 10 +
'0';
568 char *end = (
char *)alloca(n) + n - 1;
575 if (val == INT64_MIN) {
579 bool sign = (val < 0);
580 if (sign) val = -val;
583 int c = val % 10 +
'0';
589 }
else if (force_sign) {
599 char *end = (
char *)alloca(n) + n - 1;
607 int c = val % 10 +
'0';
618 char *end = (
char *)alloca(n) + n - 1;
628 char c = digits[val & 7];
639 char *end = (
char *)alloca(n) + n - 1;
649 char c = digits[val & 7];
660 char *end = (
char *)alloca(n) + n - 1;
670 char c = digits[val & 15];
681 char *end = (
char *)alloca(n) + n - 1;
691 char c = digits[val & 15];
701 int n =
sizeof(uintptr_t) * 2 + 1;
702 char *end = (
char *)alloca(n) + n - 1;
708 uintptr_t v = (uintptr_t)val;
709 for (
int i = 0; i < (int)
sizeof(uintptr_t) * 2; i++) {
710 char c = digits[v & 15];
753 if (*
q.
next ==
'%') {
754 if (
q.
next[1] ==
'%') {
759 }
else if (complete) {
772 #ifndef STRFORMAT_NO_FP
787 case 'c':
return format_c((
char)value);
788 case 'd':
return format((int32_t)value, 0);
789 case 'u':
return format(value, 0);
791 #ifndef STRFORMAT_NO_FP
792 case 'f':
return format((
double)value, 0);
802 case 'c':
return format_c((
char)value);
803 case 'd':
return format((int64_t)value, 0);
804 case 'u':
return format(value, 0);
806 #ifndef STRFORMAT_NO_FP
807 case 'f':
return format((
double)value, 0);
817 case 'c':
return format_c((
char)value);
818 case 'd':
return format((int32_t)value, 0);
819 case 'u':
return format(value, 0);
821 #ifndef STRFORMAT_NO_FP
822 case 'f':
return format((
double)value, 0);
832 case 'c':
return format_c((
char)value);
833 case 'd':
return format((int64_t)value, 0);
834 case 'u':
return format(value, 0);
836 #ifndef STRFORMAT_NO_FP
837 case 'f':
return format((
double)value, 0);
845 return format((int32_t)
c, hint);
847 #ifndef STRFORMAT_NO_FP
852 case 'c':
return format_c((
char)value);
853 case 'd':
return format((int64_t)value, 0);
854 case 'u':
return format((uint64_t)value, 0);
855 case 'o':
return format_o64((uint64_t)value, 0);
856 case 'x':
return format_x64((uint64_t)value, 0);
857 case 's':
return format_f(value,
true);
867 case 'c':
return format_c((
char)value);
868 case 'u':
return format((uint32_t)value, 0);
869 case 'o':
return format_o32((uint32_t)value, 0);
870 case 'x':
return format_x32((uint32_t)value, 0);
871 #ifndef STRFORMAT_NO_FP
872 case 'f':
return format((
double)value, 0);
882 case 'c':
return format_c((
char)value);
883 case 'd':
return format((int32_t)value, 0);
884 case 'o':
return format_o32((uint32_t)value, 0);
885 case 'x':
return format_x32((uint32_t)value, 0);
886 #ifndef STRFORMAT_NO_FP
887 case 'f':
return format((
double)value, 0);
897 case 'c':
return format_c((
char)value);
898 case 'u':
return format((uint64_t)value, 0);
899 case 'o':
return format_o64((uint64_t)value, 0);
900 case 'x':
return format_x64((uint64_t)value, 0);
901 #ifndef STRFORMAT_NO_FP
902 case 'f':
return format((
double)value, 0);
912 case 'c':
return format_c((
char)value);
913 case 'd':
return format((int64_t)value, 0);
916 #ifndef STRFORMAT_NO_FP
917 case 'f':
return format((
double)value, 0);
938 case 'u':
case 'o':
case 'x':
944 #ifndef STRFORMAT_NO_FP
950 return alloc_part(value, value + strlen(value));
957 return format(value.data(), hint);
961 std::string_view sv(value.data(), value.size());
981 void format(std::function<
Part *(
int)>
const &callback,
int width,
int precision)
984 if (*
q.
next ==
'%') {
991 int c = (
unsigned char)*
q.
next;
994 }
else if (
c ==
'+') {
996 }
else if (
c ==
'-') {
1004 auto GetNumber = [&](
int alternate_value){
1006 if (*
q.
next ==
'*') {
1010 int c = (
unsigned char)*
q.
next;
1011 if (!isdigit(
c))
break;
1022 value = alternate_value;
1027 q.
width = GetNumber(width);
1029 if (*
q.
next ==
'.') {
1035 while (*
q.
next ==
'l') {
1042 int c = (
unsigned char)*
q.
next;
1052 int padlen =
q.
width -
p->size;
1055 char c =
p->data[0];
1057 if (
c ==
'+' ||
c ==
'-') {
1085 #ifndef STRFORMAT_NO_LOCALE
1097 #ifndef STRFORMAT_NO_LOCALE
1133 #ifndef STRFORMAT_NO_LOCALE
1135 return *
q.
opt.
lc->decimal_point;
1144 q.
text = text.empty() ? std::string_view(
"") : text;
1148 #ifndef STRFORMAT_NO_LOCALE
1157 format([&](
int hint){
return format(value, hint); }, width, precision);
1160 #ifndef STRFORMAT_NO_FP
1163 return arg(value, width, precision);
1168 return arg(value, width, precision);
1172 return arg(value, width, precision);
1176 return arg(value, width, precision);
1180 return arg(value, width, precision);
1184 return arg(value, width, precision);
1188 format([&](
int hint){
return format_o32(value, hint); }, width, precision);
1193 format([&](
int hint){
return format_o64(value, hint); }, width, precision);
1198 format([&](
int hint){
return format_x32(value, hint); }, width, precision);
1203 format([&](
int hint){
return format_x64(value, hint); }, width, precision);
1208 return arg(value, width, precision);
1212 return arg(value, width, precision);
1216 format([&](
int hint){ (void)hint;
return format_p(value); }, width, precision);
1222 return arg(value, width, precision);
1224 void render(std::function<
void (
char const *ptr,
int len)>
const &to)
1228 to(
p->data,
p->size);
1233 render([&](
char const *ptr,
int len){
1234 fwrite(ptr, 1, len, fp);
1239 render([&](
char const *ptr,
int len){
1240 ::write(fd, ptr, len);
1254 render([&](
char const *ptr,
int len){
1255 vec->insert(
vec->end(), ptr, ptr + len);
1261 render([&](
char const *ptr,
int len){
1262 str->append(ptr, len);
1267 std::vector<char> ret;
1274 result.reserve(
length());
1275 render([&](
char const *ptr,
int len){
1276 result.append(ptr, len);
1280 operator std::string ()