Navigation Menu

Skip to content

Commit

Permalink
remove ksprintf_fast(); it is not that fast...
Browse files Browse the repository at this point in the history
  • Loading branch information
Heng Li committed Sep 23, 2011
1 parent 7f8ec00 commit f4f8449
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 259 deletions.
258 changes: 0 additions & 258 deletions kstring.c
Expand Up @@ -3,7 +3,6 @@
#include <ctype.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "kstring.h"

int ksprintf(kstring_t *s, const char *fmt, ...)
Expand Down Expand Up @@ -167,256 +166,6 @@ char *kstrnstr(const char *str, const char *pat, int n, int **_prep)
return (char*)kmemmem(str, n, pat, strlen(pat), _prep);
}

/****************
* fast sprintf *
****************/

typedef struct {
int32_t n_ell:5, n_Ell:5, left_aln:2, w:20;
int32_t f;
} printf_conv_t;

static inline void enlarge(kstring_t *s, int l)
{
if (s->l + l + 1 >= s->m) {
s->m = s->l + l + 2;
kroundup32(s->m);
s->s = (char*)realloc(s->s, s->m);
}
}

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, ...)
{

#define write_integer0(_c, _s, _type, _z, _base, _conv) do { \
char buf[24]; \
int l = 0, k; \
_type x; \
if (_c != 0) { \
for (x = _c < 0? -_c : _c; x; x /= _base) buf[l++] = _conv[x%_base]; \
if (_c < 0) buf[l++] = '-'; \
} else buf[l++] = '0'; \
if (_z.f > 0 || _z.w) { \
int f, w; \
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++] = ' '; \
if (f > l) \
for (k = l; k < f; ++k) _s->s[_s->l++] = '0'; \
for (k = l - 1; k >= 0; --k) _s->s[_s->l++] = buf[k]; \
if (w > f && _z.left_aln) \
for (k = f; k < w; ++k) _s->s[_s->l++] = ' '; \
} else { \
enlarge(_s, l); \
for (k = l - 1; k >= 0; --k) _s->s[_s->l++] = buf[k]; \
} \
} while (0)

#define write_integer(_ap, _s, _type, _z, _base, _conv) do { \
_type c = va_arg(_ap, _type); \
write_integer0(c, _s, _type, _z, _base, _conv); \
} 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.f = -1;
memset(&ztmp, 0, sizeof(printf_conv_t));
va_start(ap, fmt);
while (*p) {
if (state == 1) {
int finished = 0;
if (*p == '%') {
enlarge(s, 1);
s->s[s->l++] = '%';
finished = 1;
} else if (*p == 'd' || *p == 'i') { // %d or %i
if (z.n_ell == 0) write_integer(ap, s, int, z, 10, "0123456789");
else if (z.n_ell == 1) write_integer(ap, s, long, z, 10, "0123456789");
else write_integer(ap, s, long long, z, 10, "0123456789");
finished = 1;
} else if (*p == 'g' || *p == 'G') { // double-precision
double x = va_arg(ap, double);
uint64_t *y = (uint64_t*)&x;
int l00 = s->l;
if ((*y >> 52 & 0x7ff) == 0x7ff) { // nan, inf or -inf
const char *t, *r = 0;
if (*y & 0x000fffffffffffffull) r = "nan";
else if (*y>>63) r = "-inf";
else r = "inf";
enlarge(s, strlen(r));
for (t = r; *t; ++t) s->s[s->l++] = *t;
} else if (x == 0.) { // zero
s->s[s->l++] = '0';
} else { // other cases
double f, base, p10;
int type = *p, e, tmp;
uint64_t y;
if (z.f < 0) z.f = 6; // default precision
if (z.f > 20) z.f = 20; // maximum precision. 1<<63 ~ 1e20
f = frexp10(x, &e); // 10-based frexp()
type = (e < -4 || e >= z.f)? 'e' : 'f'; // see the printf() manual page
for (p10 = 1., base = 10., tmp = z.f - 1; tmp; base *= base, tmp >>= 1) // compute pow(10, z.f-1)
if (tmp & 1) p10 *= base;
if (f < 0) {
f = -f;
s->s[s->l++] = '-';
}
y = (uint64_t)round(f * p10); // perhaps (uint64_t)(f*p10+0.4999999999) is more portable?
enlarge(s, z.w > z.f + 7? z.w : z.f + 7);
if (type == 'e') { // scientific number
int j, l0 = s->l;
ztmp.f = -1; write_integer0(y, s, int64_t, ztmp, 10, "0123456789");
if (s->l - l0 > z.f) ++e; // in case x=9.9999999e100
while (s->s[s->l - 1] == '0') --s->l; // trim trailing zeros
for (j = s->l; j > l0 + 1; --j) s->s[j] = s->s[j - 1]; // shift for the dot
s->s[j] = '.'; ++s->l; // add the dot
s->s[s->l++] = isupper(*p)? 'E' : 'e';
if (e >= 0) s->s[s->l++] = '+';
ztmp.f = 2; write_integer0(e, s, int, ztmp, 10, "0123456789"); // write the exp
} else { // type == 'f'
int j;
if (e >= 0) { // NB: here e < z.f by the definition of type
int l0 = s->l;
ztmp.f = -1; write_integer0(y, s, int64_t, ztmp, 10, "0123456789");
if (s->l - l0 > z.f) ++e;
for (j = s->l; j > l0 + e + 1; --j) s->s[j] = s->s[j - 1]; // shift for the dot
s->s[j] = '.'; ++s->l; // add the dot
for (j = s->l - 1; s->s[j] == '0'; --j); // trim trailing zeros
s->l = (s->s[j] == '.')? j : j + 1; // trim dot if necessary
} else {
s->s[s->l++] = '0';
s->s[s->l++] = '.';
for (j = 0; j < -e - 1; ++j) s->s[s->l++] = '0'; // fill enough zeros
ztmp.f = -1; write_integer0(y, s, int64_t, ztmp, 10, "0123456789");
while (s->s[s->l - 1] == '0') --s->l;
}
}
}
if (z.w > s->l - l00) { // add spaces
int j, skip = z.w - (s->l - l00);
if (!z.left_aln) {
memmove(s->s + l00 + skip, s->s + l00, s->l - l00);
for (j = 0; j < skip; ++j) s->s[l00 + j] = ' ';
s->l += skip;
} else for (j = 0; j < skip; ++j) s->s[s->l++] = ' ';
}
finished = 1;
} else if (*p >= '0' && *p <= '9') { // w
char *r;
z.w = strtol(p, &r, 10);
p = r - 1;
} else if (*p == '.') { // f
char *r;
z.f = strtol(p + 1, &r, 10);
p = r - 1;
} else if (*p == 'l') { // %l
++z.n_ell;
} else if (*p == 's') { // %s
char *r = va_arg(ap, char*);
int j, l = strlen(r);
if (z.w > l) {
enlarge(s, z.w);
if (!z.left_aln)
for (j = 0; j < z.w - l; ++j) s->s[s->l++] = ' ';
memcpy(s->s + s->l, r, l);
s->l += l;
if (z.left_aln)
for (j = 0; j < z.w - l; ++j) s->s[s->l++] = ' ';
} else {
enlarge(s, z.w);
memcpy(s->s + s->l, r, l);
s->l += l;
}
finished = 1;
} else if (*p == 'c') { // %c
if (z.w > 1) {
int j;
enlarge(s, z.w);
if (!z.left_aln)
for (j = 0; j < z.w - 1; ++j) s->s[s->l++] = ' ';
s->s[s->l++] = va_arg(ap, int);
if (z.left_aln)
for (j = 0; j < z.w - 1; ++j) s->s[s->l++] = ' ';
} else {
enlarge(s, 1);
s->s[s->l++] = va_arg(ap, int);
}
finished = 1;
} else if (*p == 'u') { // %u
if (z.n_ell == 0) write_integer(ap, s, unsigned, z, 10, "0123456789");
else if (z.n_ell == 1) write_integer(ap, s, unsigned long, z, 10, "0123456789");
else write_integer(ap, s, unsigned long long, z, 10, "0123456789");
finished = 1;
} else if (*p == 'x') { // %x
if (z.n_ell == 0) write_integer(ap, s, unsigned, z, 16, "0123456789abcdef");
else if (z.n_ell == 1) write_integer(ap, s, unsigned long, z, 16, "0123456789abcdef");
else write_integer(ap, s, unsigned long long, z, 16, "0123456789abcdef");
finished = 1;
} else if (*p == 'X') { // %X
if (z.n_ell == 0) write_integer(ap, s, unsigned, z, 16, "0123456789ABCDEF");
else if (z.n_ell == 1) write_integer(ap, s, unsigned long, z, 16, "0123456789ABCDEF");
else write_integer(ap, s, unsigned long long, z, 16, "0123456789ABCDEF");
finished = 1;
} else if (*p == 'o') { // %o
if (z.n_ell == 0) write_integer(ap, s, unsigned, z, 8, "01234567");
else if (z.n_ell == 1) write_integer(ap, s, unsigned long, z, 8, "01234567");
else write_integer(ap, s, unsigned long long, z, 8, "01234567");
finished = 1;
} else if (*p == 'L') { // %L
++z.n_Ell;
} else if (*p == '-') { // %-
z.left_aln = 1;
}
++p;
if (finished) state = 0;
} else {
q = p;
while (*p && *p != '%') ++p;
if (p > q) {
enlarge(s, p - q);
memcpy(s->s + s->l, q, p - q);
s->l += p - q;
}
if (*p == '%') {
state = 1;
++p;
memset(&z, 0, sizeof(printf_conv_t)); z.f = -1;
}
}
}
va_end(ap);
s->s[s->l] = 0;
return 0;
}

/***********************
* The main() function *
***********************/
Expand All @@ -430,13 +179,6 @@ int main()
ks_tokaux_t aux;
char *p;
s = (kstring_t*)calloc(1, sizeof(kstring_t));
{ // test ksprintf_fast()
long xx = -10;
int e;
ksprintf_fast(s, " pooiu %% *|%10s| %ld %-5c%-5.4X |%-10.5g|", "+++", xx, '*', 110, -0.0222256); printf("'%s'\n", s->s); s->l = 0;
frexp10(-1.2e10, &e);
printf("%.3g, %.1f\n", 2461., 1e30);
}
// test ksprintf()
ksprintf(s, " abcdefg: %d ", 100);
printf("'%s'\n", s->s);
Expand Down
1 change: 0 additions & 1 deletion kstring.h
Expand Up @@ -53,7 +53,6 @@ extern "C" {
#endif

int ksprintf(kstring_t *s, const char *fmt, ...);
int ksprintf_fast(kstring_t *s, const char *fmt, ...);
int ksplit_core(char *s, int delimiter, int *_max, int **_offsets);
char *kstrstr(const char *str, const char *pat, int **_prep);
char *kstrnstr(const char *str, const char *pat, int n, int **_prep);
Expand Down

0 comments on commit f4f8449

Please sign in to comment.