mirror of https://github.com/attractivechaos/klib
implemented %f/e/g in ksprintf_fast(); unfinished
This commit is contained in:
parent
ed80857e9a
commit
247e867757
118
kstring.c
118
kstring.c
|
@ -172,7 +172,7 @@ char *kstrnstr(const char *str, const char *pat, int n, int **_prep)
|
|||
****************/
|
||||
|
||||
typedef struct {
|
||||
int base, width, fill, left_aln, n_ell, n_Ell;
|
||||
int base, w, f, left_aln, n_ell, n_Ell;
|
||||
} printf_conv_t;
|
||||
|
||||
static inline void enlarge(kstring_t *s, int l)
|
||||
|
@ -184,6 +184,30 @@ static inline void enlarge(kstring_t *s, int l)
|
|||
}
|
||||
}
|
||||
|
||||
double frexp10(double x, int *e)
|
||||
{
|
||||
const double M_LOG_10_2 = M_LN2 / M_LN10;
|
||||
double z;
|
||||
int tmp;
|
||||
if (x == 0.) {
|
||||
*e = 0;
|
||||
return 0.;
|
||||
}
|
||||
frexp(x, e);
|
||||
if (*e >= 0) {
|
||||
*e = (int)(*e * M_LOG_10_2);
|
||||
for (z = .1, tmp = *e; tmp; z *= z, tmp >>= 1)
|
||||
if (tmp & 1) x *= z;
|
||||
} else {
|
||||
*e = (int)((*e - 1) * M_LOG_10_2);
|
||||
for (z = 10., tmp = -*e; tmp; z *= z, tmp >>= 1)
|
||||
if (tmp & 1) x *= z;
|
||||
}
|
||||
if (x >= 10. || x <= -10.) ++(*e), x *= .1;
|
||||
else if (x > -1. && x < 1.) --(*e), x *= 10.;
|
||||
return x;
|
||||
}
|
||||
|
||||
int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
||||
{
|
||||
|
||||
|
@ -195,8 +219,8 @@ int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
|||
for (x = _c < 0? -_c : _c; x > 0; x /= _z.base) buf[l++] = _conv[x%_z.base]; \
|
||||
if (_c < 0) buf[l++] = '-'; \
|
||||
} else buf[l++] = '0'; \
|
||||
f = l > _z.fill? l : _z.fill; \
|
||||
w = f > _z.width? f : _z.width; \
|
||||
f = l > _z.f? l : _z.f; \
|
||||
w = f > _z.w? f : _z.w; \
|
||||
enlarge(_s, w); \
|
||||
if (w > f && !_z.left_aln) \
|
||||
for (k = f; k < w; ++k) _s->s[_s->l++] = ' '; \
|
||||
|
@ -212,12 +236,31 @@ int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
|||
write_integer0(c, _s, _type, _z, _conv); \
|
||||
} while (0)
|
||||
|
||||
#define write_fraction(_s, _f, _z, _trim0) do { \
|
||||
int j, last; \
|
||||
for (j = 0; j < _z.f - 1; ++j) { \
|
||||
_f = (_f - (int)_f) * 10.; \
|
||||
_s->s[_s->l++] = (int)_f + '0'; \
|
||||
} \
|
||||
_f = (_f - (int)_f) * 10.; \
|
||||
last = (int)(_f + .499999999999999999); \
|
||||
if (last >= 10) { \
|
||||
_s->s[_s->l++] = '0'; \
|
||||
for (j = _s->l - 2; _s->s[j] == '9'; --j) _s->s[j] = '0'; \
|
||||
if (_s->s[j] != '.') ++_s->s[j]; \
|
||||
} else _s->s[_s->l++] = last + '0'; \
|
||||
if (_trim0) { \
|
||||
while (_s->s[_s->l - 1] == '0') --_s->l; \
|
||||
if (_s->s[_s->l - 1] == '.') --_s->l; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
va_list ap;
|
||||
const char *p = fmt, *q;
|
||||
int state = 0;
|
||||
printf_conv_t z, ztmp;
|
||||
memset(&z, 0, sizeof(printf_conv_t)); z.fill = -1;
|
||||
ztmp = z;
|
||||
memset(&z, 0, sizeof(printf_conv_t)); z.f = -1;
|
||||
ztmp = z; ztmp.base = 10;
|
||||
va_start(ap, fmt);
|
||||
while (*p) {
|
||||
if (state == 1) {
|
||||
|
@ -226,13 +269,13 @@ int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
|||
enlarge(s, 1);
|
||||
s->s[s->l++] = '%';
|
||||
finished = 1;
|
||||
} else if (*p >= '0' && *p <= '9') { // width
|
||||
} else if (*p >= '0' && *p <= '9') { // w
|
||||
char *r;
|
||||
z.width = strtol(p, &r, 10);
|
||||
z.w = strtol(p, &r, 10);
|
||||
p = r - 1;
|
||||
} else if (*p == '.') { // fill
|
||||
} else if (*p == '.') { // f
|
||||
char *r;
|
||||
z.fill = strtol(p + 1, &r, 10);
|
||||
z.f = strtol(p + 1, &r, 10);
|
||||
p = r - 1;
|
||||
} else if (*p == 'l') { // %l
|
||||
++z.n_ell;
|
||||
|
@ -266,7 +309,7 @@ int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
|||
else if (z.n_ell == 1) write_integer(ap, s, unsigned long, z, conv);
|
||||
else write_integer(ap, s, unsigned long long, z, conv);
|
||||
finished = 1;
|
||||
} else if (*p == 'f' || *p == 'e') {
|
||||
} else if (*p == 'f' || *p == 'e' || *p == 'g') {
|
||||
const char *t, *r = 0;
|
||||
double x = va_arg(ap, double);
|
||||
uint64_t *y = (uint64_t*)&x;
|
||||
|
@ -278,7 +321,52 @@ int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
|||
l = strlen(r);
|
||||
enlarge(s, l);
|
||||
for (t = r; *t; ++t) s->s[s->l++] = *t;
|
||||
} else if (*p == 'f') {
|
||||
} else {
|
||||
double f;
|
||||
int type = *p, e, w, trim0 = (*p == 'g')? 1 : 0;
|
||||
if (z.f < 0) z.f = 6;
|
||||
f = frexp10(x, &e);
|
||||
if (*p == 'g') type = (e < -4 || e >= z.f)? 'e' : 'f'; // see the printf() manual page
|
||||
if (type == 'e') {
|
||||
int j, w = 8 + z.f > z.w? 8 + z.f : z.w;
|
||||
enlarge(s, w);
|
||||
if (f < 0) s->s[s->l++] = '-', f = -f;
|
||||
s->s[s->l++] = (int)f + '0';
|
||||
if (z.f > 0) {
|
||||
s->s[s->l++] = '.';
|
||||
write_fraction(s, f, z, trim0);
|
||||
}
|
||||
s->s[s->l++] = 'e';
|
||||
if (e >= 0) s->s[s->l++] = '+';
|
||||
ztmp.f = 2;
|
||||
write_integer0(e, s, int, ztmp, "0123456789");
|
||||
} else {
|
||||
int j, w = abs(e) + 2 + z.f > z.w? abs(e) + 2 + z.f : z.w;
|
||||
enlarge(s, w);
|
||||
if (f < 0) s->s[s->l++] = '-', f = -f;
|
||||
if (e >= 0) {
|
||||
for (j = 0; j < e; ++j) {
|
||||
s->s[s->l++] = (int)f + '0';
|
||||
f = (f - (int)f) * 10.;
|
||||
}
|
||||
if (z.f != 0) {
|
||||
s->s[s->l++] = (int)f + '0';
|
||||
s->s[s->l++] = '.';
|
||||
write_fraction(s, f, z, trim0);
|
||||
} else s->s[s->l++] = (int)(f + .49999999999999999) + '0';
|
||||
} else {
|
||||
s->s[s->l++] = '0';
|
||||
if (z.f != 0) {
|
||||
s->s[s->l++] = '.';
|
||||
for (j = 1; j < -e && j <= z.f; ++j) s->s[s->l++] = '0';
|
||||
if (j - 1 < z.f) {
|
||||
f *= .1;
|
||||
z.f -= j - 1;
|
||||
write_fraction(s, f, z, trim0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finished = 1;
|
||||
}
|
||||
|
@ -295,7 +383,7 @@ int ksprintf_fast(kstring_t *s, const char *fmt, ...)
|
|||
if (*p == '%') {
|
||||
state = 1;
|
||||
++p;
|
||||
memset(&z, 0, sizeof(printf_conv_t)); z.fill = -1;
|
||||
memset(&z, 0, sizeof(printf_conv_t)); z.f = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,8 +407,10 @@ int main()
|
|||
s = (kstring_t*)calloc(1, sizeof(kstring_t));
|
||||
{ // test ksprintf_fast()
|
||||
long xx = -10;
|
||||
ksprintf_fast(s, " pooiu %% %s %ld %c%-5.4X %f", "+++", xx, '*', 110, 2.45); printf("'%s'\n", s->s); s->l = 0;
|
||||
printf("%4.3x, %.1f\n", 100, 1e30);
|
||||
int e;
|
||||
ksprintf_fast(s, " pooiu %% %s %ld %c%-5.4X %g", "+++", xx, '*', 110, 0.246); printf("'%s'\n", s->s); s->l = 0;
|
||||
frexp10(-1.2e10, &e);
|
||||
printf("%g, %.1f\n", 1e100, 1e30);
|
||||
}
|
||||
// test ksprintf()
|
||||
ksprintf(s, " abcdefg: %d ", 100);
|
||||
|
|
Loading…
Reference in New Issue