20 #include <string_view>
22 #ifndef STRFORMAT_NO_LOCALE
49 static const double tbl[] = {
50 1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06,
51 1e+07, 1e+08, 1e+09, 1e+10, 1e+11, 1e+12, 1e+13,
54 if (exp >= 0 && exp <
static_cast<int>(
sizeof tbl /
sizeof *tbl))
56 if (exp <= 0 && exp > -
static_cast<int>(
sizeof tbl /
sizeof *tbl))
57 return 1.0 / tbl[-exp];
59 return std::pow(10.0, exp);
77 static double my_strtod(
const char *nptr,
char **endptr)
81 bool saw_digit =
false;
84 bool exp_sign =
false;
88 while (std::isspace((
unsigned char)*s)) ++s;
91 if (*s ==
'+' || *s ==
'-') {
92 if (*s ==
'-') sign =
true;
97 while (std::isdigit((
unsigned char)*s)) {
99 value = value * 10.0 + (*s -
'0');
106 while (std::isdigit((
unsigned char)*s)) {
108 value = value * 10.0 + (*s -
'0');
116 if (endptr) *endptr =
const_cast<char *
>(nptr);
121 if (*s ==
'e' || *s ==
'E') {
123 const char *exp_start = s;
124 if (*s ==
'+' || *s ==
'-') {
125 if (*s ==
'-') exp_sign =
true;
128 if (std::isdigit((
unsigned char)*s)) {
129 while (std::isdigit((
unsigned char)*s)) {
130 exp_val = exp_val * 10 + (*s -
'0');
143 int total_exp = exp_val - frac_digits;
144 if (total_exp != 0) {
154 if (!std::isfinite(value)) {
156 value = sign ? -HUGE_VAL : HUGE_VAL;
157 }
else if (value == 0.0 && saw_digit && total_exp != 0) {
162 if (endptr) *endptr =
const_cast<char *
>(s);
174 while (isspace((
unsigned char)*
p)) {
179 }
else if (*
p ==
'-') {
184 if (
p[1] ==
'x' ||
p[1] ==
'X') {
190 int c = (
unsigned char)
p[i];
191 if (c < '0' || c >
'7')
break;
200 template <
typename T>
static inline T
parse_number(
char const *ptr, std::function<T(
char const *p,
int radix)> conv)
209 #ifdef STRFORMAT_NO_LOCALE
212 struct lconv *
lc =
nullptr;
216 template <
typename T>
static inline T
num(
char const *value,
Option_ const &opt);
219 return parse_number<char>(value, [](
char const *p,
int radix){
220 return (
char)strtol(p,
nullptr, radix);
225 return parse_number<int32_t>(value, [](
char const *p,
int radix){
226 return strtol(p,
nullptr, radix);
231 return parse_number<uint32_t>(value, [](
char const *p,
int radix){
232 return strtoul(p,
nullptr, radix);
237 return parse_number<int64_t>(value, [](
char const *p,
int radix){
238 return strtoll(p,
nullptr, radix);
243 return parse_number<uint64_t>(value, [](
char const *p,
int radix){
244 return strtoull(p,
nullptr, radix);
247 #ifndef STRFORMAT_NO_FP
250 return parse_number<double>(value, [&opt](
char const *p,
int radix){
254 return strtod(p, nullptr);
257 return misc::my_strtod(p, nullptr);
260 return (
double)strtoll(p,
nullptr, radix);
265 template <
typename T>
static inline T
num(std::string
const &value,
Option_ const &opt)
267 return num<T>(value.data(), opt);
290 memcpy(
p->data, data, size);
329 Part *next =
p->next;
333 list->
head =
nullptr;
334 list->
last =
nullptr;
341 memset(
p->data,
c, n);
348 return "0123456789abcdef";
352 return "0123456789ABCDEF";
355 #ifndef STRFORMAT_NO_FP
358 if (std::isnan(val))
return alloc_part(
"#NAN");
359 if (std::isinf(val))
return alloc_part(
"#INF");
370 double intval = floor(val);
375 ptr = end = (
char *)alloca(precision + 10) + 5;
382 ptr = end = (
char *)alloca(intlen + precision + 10) + intlen + 5;
390 while (v > 0 && v < 1) {
399 for (
int i = 0; i < precision - e; i++) {
408 int r = std::min(e, precision);
416 while (i < precision) {
421 *end++ = (char)m +
'0';
429 intval += floor(val + 0.5);
443 for (
int i = 0; i < intlen; i++) {
446 *--ptr = (char)((t -
u) * 10 + 0.49) +
'0';
457 if (trim_zeros && dot) {
477 char *end = (
char *)alloca(n) + n - 1;
484 bool sign = (val < 0);
492 int c = v % 10 +
'0';
498 }
else if (force_sign) {
508 char *end = (
char *)alloca(n) + n - 1;
516 int c = val % 10 +
'0';
527 char *end = (
char *)alloca(n) + n - 1;
534 if (val == (int64_t)1 << 63) {
538 bool sign = (val < 0);
539 if (sign) val = -val;
542 int c = val % 10 +
'0';
548 }
else if (force_sign) {
558 char *end = (
char *)alloca(n) + n - 1;
566 int c = val % 10 +
'0';
577 char *end = (
char *)alloca(n) + n - 1;
587 char c = digits[val & 7];
598 char *end = (
char *)alloca(n) + n - 1;
608 char c = digits[val & 7];
619 char *end = (
char *)alloca(n) + n - 1;
629 char c = digits[val & 15];
640 char *end = (
char *)alloca(n) + n - 1;
650 char c = digits[val & 15];
660 int n =
sizeof(uintptr_t) * 2 + 1;
661 char *end = (
char *)alloca(n) + n - 1;
667 uintptr_t v = (uintptr_t)val;
668 for (
int i = 0; i < (int)
sizeof(uintptr_t) * 2; i++) {
669 char c = digits[v & 15];
712 if (*
q.
next ==
'%') {
713 if (
q.
next[1] ==
'%') {
718 }
else if (complete) {
731 #ifndef STRFORMAT_NO_FP
746 case 'c':
return format_c((
char)value);
747 case 'd':
return format((int32_t)value, 0);
748 case 'u':
return format(value, 0);
750 #ifndef STRFORMAT_NO_FP
751 case 'f':
return format((
double)value, 0);
761 case 'c':
return format_c((
char)value);
762 case 'd':
return format((int64_t)value, 0);
763 case 'u':
return format(value, 0);
765 #ifndef STRFORMAT_NO_FP
766 case 'f':
return format((
double)value, 0);
776 case 'c':
return format_c((
char)value);
777 case 'd':
return format((int32_t)value, 0);
778 case 'u':
return format(value, 0);
780 #ifndef STRFORMAT_NO_FP
781 case 'f':
return format((
double)value, 0);
791 case 'c':
return format_c((
char)value);
792 case 'd':
return format((int64_t)value, 0);
793 case 'u':
return format(value, 0);
795 #ifndef STRFORMAT_NO_FP
796 case 'f':
return format((
double)value, 0);
804 return format((int32_t)
c, hint);
806 #ifndef STRFORMAT_NO_FP
811 case 'c':
return format_c((
char)value);
812 case 'd':
return format((int64_t)value, 0);
813 case 'u':
return format((uint64_t)value, 0);
814 case 'o':
return format_o64((uint64_t)value, 0);
815 case 'x':
return format_x64((uint64_t)value, 0);
816 case 's':
return format_f(value,
true);
826 case 'c':
return format_c((
char)value);
827 case 'u':
return format((uint32_t)value, 0);
828 case 'o':
return format_o32((uint32_t)value, 0);
829 case 'x':
return format_x32((uint32_t)value, 0);
830 #ifndef STRFORMAT_NO_FP
831 case 'f':
return format((
double)value, 0);
841 case 'c':
return format_c((
char)value);
842 case 'd':
return format((int32_t)value, 0);
843 case 'o':
return format_o32((uint32_t)value, 0);
844 case 'x':
return format_x32((uint32_t)value, 0);
845 #ifndef STRFORMAT_NO_FP
846 case 'f':
return format((
double)value, 0);
856 case 'c':
return format_c((
char)value);
857 case 'u':
return format((uint64_t)value, 0);
858 case 'o':
return format_o64((uint64_t)value, 0);
859 case 'x':
return format_x64((uint64_t)value, 0);
860 #ifndef STRFORMAT_NO_FP
861 case 'f':
return format((
double)value, 0);
871 case 'c':
return format_c((
char)value);
872 case 'd':
return format((int64_t)value, 0);
875 #ifndef STRFORMAT_NO_FP
876 case 'f':
return format((
double)value, 0);
897 case 'u':
case 'o':
case 'x':
903 #ifndef STRFORMAT_NO_FP
909 return alloc_part(value, value + strlen(value));
916 return format(value.data(), hint);
920 std::string_view sv(value.data(), value.size());
940 void format(std::function<
Part *(
int)>
const &callback,
int width,
int precision)
943 if (*
q.
next ==
'%') {
950 int c = (
unsigned char)*
q.
next;
953 }
else if (
c ==
'+') {
955 }
else if (
c ==
'-') {
963 auto GetNumber = [&](
int alternate_value){
965 if (*
q.
next ==
'*') {
969 int c = (
unsigned char)*
q.
next;
970 if (!isdigit(
c))
break;
981 value = alternate_value;
986 q.
width = GetNumber(width);
988 if (*
q.
next ==
'.') {
994 while (*
q.
next ==
'l') {
1001 int c = (
unsigned char)*
q.
next;
1011 int padlen =
q.
width -
p->size;
1014 char c =
p->data[0];
1016 if (
c ==
'+' ||
c ==
'-') {
1044 #ifndef STRFORMAT_NO_LOCALE
1056 #ifndef STRFORMAT_NO_LOCALE
1092 #ifndef STRFORMAT_NO_LOCALE
1094 return *
q.
opt.
lc->decimal_point;
1107 #ifndef STRFORMAT_NO_LOCALE
1127 format([&](
int hint){
return format(value, hint); }, width, precision);
1130 #ifndef STRFORMAT_NO_FP
1133 return arg(value, width, precision);
1138 return arg(value, width, precision);
1142 return arg(value, width, precision);
1146 return arg(value, width, precision);
1150 return arg(value, width, precision);
1154 return arg(value, width, precision);
1158 format([&](
int hint){
return format_o32(value, hint); }, width, precision);
1163 format([&](
int hint){
return format_o64(value, hint); }, width, precision);
1168 format([&](
int hint){
return format_x32(value, hint); }, width, precision);
1173 format([&](
int hint){
return format_x64(value, hint); }, width, precision);
1178 return arg(value, width, precision);
1182 return arg(value, width, precision);
1186 format([&](
int hint){ (void)hint;
return format_p(value); }, width, precision);
1192 return arg(value, width, precision);
1194 void render(std::function<
void (
char const *ptr,
int len)>
const &to)
1198 to(
p->data,
p->size);
1204 render([&](
char const *ptr,
int len){
1205 vec->insert(
vec->end(), ptr, ptr + len);
1210 render([&](
char const *ptr,
int len){
1211 fwrite(ptr, 1, len, fp);
1216 render([&](
char const *ptr,
int len){
1217 ::write(fd, ptr, len);
1232 std::vector<char> tmp;
1234 p = (
char *)alloca(n);
1240 render([&](
char const *ptr,
int len){
1241 memcpy(
d, ptr, len);
1244 return std::string(
p, n);
1246 operator std::string ()