Browse Source

Rework printf functions.

tags/0.6.6
Vsevolod Stakhov 10 years ago
parent
commit
4ed70df2fb
2 changed files with 187 additions and 177 deletions
  1. 170
    171
      src/printf.c
  2. 17
    6
      src/printf.h

+ 170
- 171
src/printf.c View File

@@ -169,65 +169,115 @@ rspamd_sprintf_num (gchar *buf, gchar *last, guint64 ui64, gchar zero,
return ((gchar *)memcpy (buf, p, len)) + len;
}

gint
struct rspamd_printf_char_buf {
char *begin;
char *pos;
glong remain;
};

static glong
rspamd_printf_append_char (const gchar *buf, glong buflen, gpointer ud)
{
struct rspamd_printf_char_buf *dst = (struct rspamd_printf_char_buf *)ud;
glong wr;

if (dst->remain <= 0) {
return dst->remain;
}

wr = MIN (dst->remain, buflen);
memcpy (dst->pos, buf, wr);
dst->remain -= wr;
dst->pos += wr;

return wr;
}

static glong
rspamd_printf_append_file (const gchar *buf, glong buflen, gpointer ud)
{
FILE *dst = (FILE *)ud;

return fwrite (buf, 1, buflen, dst);
}

static glong
rspamd_printf_append_gstring (const gchar *buf, glong buflen, gpointer ud)
{
GString *dst = (GString *)ud;

g_string_append_len (dst, buf, buflen);

return buflen;
}

glong
rspamd_fprintf (FILE *f, const gchar *fmt, ...)
{
va_list args;
gchar buf[BUFSIZ];
gint r;
glong r;

va_start (args, fmt);
rspamd_vsnprintf (buf, sizeof (buf), fmt, args);
r = rspamd_vprintf_common (rspamd_printf_append_file, f, fmt, args);
va_end (args);

r = fprintf (f, "%s", buf);

return r;
return r;
}

gint
glong
rspamd_log_fprintf (FILE *f, const gchar *fmt, ...)
{
va_list args;
gchar buf[BUFSIZ];
gint r;
glong r;

va_start (args, fmt);
rspamd_vsnprintf (buf, sizeof (buf), fmt, args);
r = rspamd_vprintf_common (rspamd_printf_append_file, f, fmt, args);
va_end (args);

r = fprintf (f, "%s\n", buf);
fflush (f);
fflush (f);

return r;
return r;
}

gint
rspamd_sprintf (gchar *buf, const gchar *fmt, ...)

glong
rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...)
{
gchar *p;
va_list args;
gchar *r;
va_list args;

va_start (args, fmt);
p = rspamd_vsnprintf (buf, /* STUB */ 65536, fmt, args);
r = rspamd_vsnprintf (buf, max, fmt, args);
va_end (args);

return p - buf;
return (r - buf);
}

gchar *
rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
{
struct rspamd_printf_char_buf dst;

dst.begin = buf;
dst.pos = dst.begin;
dst.remain = max - 1;
(void)rspamd_vprintf_common (rspamd_printf_append_char, &dst, fmt, args);
*dst.pos = '\0';

gint
rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...)
return dst.pos;
}

glong
rspamd_printf_gstring (GString *s, const gchar *fmt, ...)
{
gchar *p;
va_list args;
va_list args;
glong r;

va_start (args, fmt);
p = rspamd_vsnprintf (buf, max - 1, fmt, args);
r = rspamd_vprintf_common (rspamd_printf_append_gstring, s, fmt, args);
va_end (args);
*p = '\0';

return p - buf;
return r;
}

gchar *
@@ -284,13 +334,25 @@ rspamd_escape_string (gchar *dst, const gchar *src, glong len)
return buf;
}

gchar *
rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
#define RSPAMD_PRINTF_APPEND(buf, len) \
do { \
wr = func ((buf), (len), apd); \
if (wr <= 0) { \
goto oob; \
} \
written += wr; \
fmt ++; \
buf_start = fmt; \
} while(0)

glong
rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar *fmt, va_list args)
{
gchar *p, zero, *last;
gchar zero, numbuf[G_ASCII_DTOSTR_BUF_SIZE], *p, *last, c;
const gchar *buf_start = fmt;
gint d;
long double f, scale;
size_t len, slen;
glong written = 0, wr, slen;
gint64 i64;
guint64 ui64;
guint width, sign, hex, humanize, bytes, frac_width, i;
@@ -298,13 +360,7 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
GString *gs;
gboolean bv;

if (max <= 0) {
return buf;
}

last = buf + max;

while (*fmt && buf < last) {
while (*fmt) {

/*
* "buf < last" means that we could copy at least one character:
@@ -313,6 +369,15 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)

if (*fmt == '%') {

/* Append what we have in buf */
if (fmt > buf_start) {
wr = func (buf_start, fmt - buf_start, apd);
if (wr <= 0) {
goto oob;
}
written += wr;
}

i64 = 0;
ui64 = 0;

@@ -323,7 +388,7 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
bytes = 0;
humanize = 0;
frac_width = 0;
slen = (size_t) -1;
slen = -1;

while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + *fmt++ - '0';
@@ -376,10 +441,10 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
case '*':
d = (gint)va_arg (args, gint);
if (G_UNLIKELY (d < 0)) {
msg_err ("crititcal error: size is less than 0");
g_assert (0);
msg_err ("critical error: size is less than 0");
return 0;
}
slen = (size_t)d;
slen = (glong)d;
fmt++;
continue;

@@ -395,61 +460,28 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)

case 'V':
v = va_arg (args, f_str_t *);

len = v->len;
len = (buf + len < last) ? len : (size_t) (last - buf);

buf = ((gchar *)memcpy (buf, v->begin, len)) + len;
fmt++;
RSPAMD_PRINTF_APPEND (v->begin, v->len);

continue;

case 'v':
gs = va_arg (args, GString *);
len = gs->len;
len = (buf + len < last) ? len : (size_t) (last - buf);

buf = ((gchar *)memcpy (buf, gs->str, len)) + len;
fmt++;
break;

case 's':
p = va_arg(args, gchar *);
if (p == NULL) {
p = "(NULL)";
}

if (slen == (size_t) -1) {
while (*p && buf < last) {
*buf++ = *p++;
}

} else {
len = (buf + slen < last) ? slen : (size_t) (last - buf);

buf = ((gchar *)memcpy (buf, p, len)) + len;
}

fmt++;
RSPAMD_PRINTF_APPEND (gs->str, gs->len);

continue;

case 'S':
p = va_arg(args, gchar *);
case 's':
p = va_arg (args, gchar *);
if (p == NULL) {
p = "(NULL)";
}

if (slen == (size_t) -1) {
buf = rspamd_escape_string (buf, p, last - buf);

} else {
len = (buf + slen < last) ? slen : (size_t) (last - buf);

buf = rspamd_escape_string (buf, p, len);
if (slen == -1) {
/* NULL terminated string */
slen = strlen (p);
}

fmt++;
RSPAMD_PRINTF_APPEND (p, slen);

continue;

@@ -510,57 +542,28 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)


case 'f':
f = (double) va_arg (args, double);
if (f < 0) {
*buf++ = '-';
f = -f;
case 'F':
if (*fmt == 'f') {
f = (long double) va_arg (args, double);
}

ui64 = (gint64) f;

buf = rspamd_sprintf_num (buf, last, ui64, zero, 0, width);

if (frac_width) {

if (buf < last) {
*buf++ = '.';
}

scale = 1.0;

for (i = 0; i < frac_width; i++) {
scale *= 10.0;
}

/*
* (gint64) cast is required for msvc6:
* it can not convert guint64 to double
*/
ui64 = (guint64) ((f - (gint64) ui64) * scale);

buf = rspamd_sprintf_num (buf, last, ui64, '0', 0, frac_width);
else {
f = (long double) va_arg (args, long double);
}

fmt++;

continue;

case 'F':
f = (long double) va_arg (args, long double);

p = numbuf;
last = p + sizeof (numbuf);
if (f < 0) {
*buf++ = '-';
*p++ = '-';
f = -f;
}

ui64 = (gint64) f;

buf = rspamd_sprintf_num (buf, last, ui64, zero, 0, width);
p = rspamd_sprintf_num (p, last, ui64, zero, 0, width);

if (frac_width) {

if (buf < last) {
*buf++ = '.';
if (p < last) {
*p++ = '.';
}

scale = 1.0;
@@ -575,50 +578,32 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
*/
ui64 = (guint64) ((f - (gint64) ui64) * scale);

buf = rspamd_sprintf_num (buf, last, ui64, '0', 0, frac_width);
p = rspamd_sprintf_num (p, last, ui64, '0', 0, frac_width);
}

fmt++;
slen = p - numbuf;
RSPAMD_PRINTF_APPEND (numbuf, slen);

continue;

case 'g':
f = (long double) va_arg (args, double);

if (f < 0) {
*buf++ = '-';
f = -f;
}
g_ascii_formatd (buf, last - buf, "%g", (double)f);
buf += strlen (buf);
fmt++;

continue;

case 'b':
bv = (gboolean) va_arg (args, double);
if (bv) {
len = MIN (last - buf, 4);
memcpy (buf, "true", len);
case 'G':
if (*fmt == 'g') {
f = (long double) va_arg (args, double);
}
else {
len = MIN (last - buf, 5);
memcpy (buf, "false", len);
f = (long double) va_arg (args, long double);
}
fmt++;

continue;
g_ascii_formatd (numbuf, sizeof (numbuf), "%g", (double)f);
slen = strlen (numbuf);
RSPAMD_PRINTF_APPEND (numbuf, slen);

case 'G':
f = (long double) va_arg (args, long double);
continue;

if (f < 0) {
*buf++ = '-';
f = -f;
}
g_ascii_formatd (buf, last - buf, "%g", (double)f);
buf += strlen (buf);
fmt++;
case 'b':
bv = (gboolean) va_arg (args, double);
RSPAMD_PRINTF_APPEND (bv ? "true" : "false", bv ? 4 : 5);

continue;

@@ -631,39 +616,43 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
break;

case 'c':
d = va_arg (args, gint);
*buf++ = (gchar) (d & 0xff);
fmt++;
c = va_arg (args, gint);
c &= 0xff;
RSPAMD_PRINTF_APPEND (&c, 1);

continue;

case 'Z':
*buf++ = '\0';
fmt++;
c = '\0';
RSPAMD_PRINTF_APPEND (&c, 1);

continue;

case 'N':
*buf++ = LF;
fmt++;
c = LF;
RSPAMD_PRINTF_APPEND (&c, 1);

continue;

case '%':
*buf++ = '%';
fmt++;
c = '%';
RSPAMD_PRINTF_APPEND (&c, 1);

continue;

default:
*buf++ = *fmt++;
c = *fmt;
RSPAMD_PRINTF_APPEND (&c, 1);

continue;
}

/* Print number */
p = numbuf;
last = p + sizeof (numbuf);
if (sign) {
if (i64 < 0) {
*buf++ = '-';
*p++ = '-';
ui64 = (guint64) -i64;

} else {
@@ -672,19 +661,29 @@ rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args)
}

if (!humanize) {
buf = rspamd_sprintf_num (buf, last, ui64, zero, hex, width);
p = rspamd_sprintf_num (p, last, ui64, zero, hex, width);
}
else {
buf = rspamd_humanize_number (buf, last, ui64, bytes);
p = rspamd_humanize_number (p, last, ui64, bytes);
}
slen = p - numbuf;
RSPAMD_PRINTF_APPEND (numbuf, slen);

} else {
fmt++;
}
}

} else {
*buf++ = *fmt++;
/* Finish buffer */
if (fmt > buf_start) {
wr = func (buf_start, fmt - buf_start, apd);
if (wr <= 0) {
goto oob;
}
written += wr;
}

return buf;
oob:
return written;
}


+ 17
- 6
src/printf.h View File

@@ -47,7 +47,6 @@
* %V f_str_t *
* %v GString *
* %s null-terminated string
* %S ascii null-terminated string
* %*s length and string
* %Z '\0'
* %N '\n'
@@ -55,13 +54,25 @@
* %% %
*
*/
gint rspamd_sprintf (gchar *buf, const gchar *fmt, ...);
gint rspamd_fprintf (FILE *f, const gchar *fmt, ...);
gint rspamd_log_fprintf (FILE *f, const gchar *fmt, ...);
gint rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...);

/**
* Callback used for common printf operations
* @param buf buffer to append
* @param buflen lenght of the buffer
* @param ud opaque pointer
* @return number of characters written
*/
typedef glong (*rspamd_printf_append_func)(const gchar *buf, glong buflen, gpointer ud);

glong rspamd_fprintf (FILE *f, const gchar *fmt, ...);
glong rspamd_log_fprintf (FILE *f, const gchar *fmt, ...);
glong rspamd_snprintf (gchar *buf, glong max, const gchar *fmt, ...);
gchar *rspamd_vsnprintf (gchar *buf, glong max, const gchar *fmt, va_list args);
glong rspamd_printf_gstring (GString *s, const gchar *fmt, ...);

/*
glong rspamd_vprintf_common (rspamd_printf_append_func func, gpointer apd, const gchar *fmt, va_list args);

/**
* Escape rspamd string to write it to log file or other 7 bit prefferable places
*
* @param dst destination string

Loading…
Cancel
Save