📄 fmt.c
字号:
static char rcsid[] = "$Id: fmt.c 6 2007-01-22 00:45:22Z drhanson $";#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <limits.h>#include <float.h>#include <ctype.h>#include <math.h>#include "assert.h"#include "except.h"#include "fmt.h"#include "mem.h"#define T Fmt_Tstruct buf { char *buf; char *bp; int size;};#define pad(n,c) do { int nn = (n); \ while (nn-- > 0) \ put((c), cl); } while (0)static void cvt_s(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { char *str = va_arg(*app, char *); assert(str); Fmt_puts(str, strlen(str), put, cl, flags, width, precision);}static void cvt_d(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { int val = va_arg(*app, int); unsigned m; char buf[43]; char *p = buf + sizeof buf; if (val == INT_MIN) m = INT_MAX + 1U; else if (val < 0) m = -val; else m = val; do *--p = m%10 + '0'; while ((m /= 10) > 0); if (val < 0) *--p = '-'; Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags, width, precision);}static void cvt_u(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { unsigned m = va_arg(*app, unsigned); char buf[43]; char *p = buf + sizeof buf; do *--p = m%10 + '0'; while ((m /= 10) > 0); Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags, width, precision);}static void cvt_o(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { unsigned m = va_arg(*app, unsigned); char buf[43]; char *p = buf + sizeof buf; do *--p = (m&0x7) + '0'; while ((m>>= 3) != 0); Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags, width, precision);}static void cvt_x(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { unsigned m = va_arg(*app, unsigned); char buf[43]; char *p = buf + sizeof buf; do *--p = "0123456789abcdef"[m&0xf]; while ((m>>= 4) != 0); Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags, width, precision);}static void cvt_p(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { unsigned long m = (unsigned long)va_arg(*app, void*); char buf[43]; char *p = buf + sizeof buf; precision = INT_MIN; do *--p = "0123456789abcdef"[m&0xf]; while ((m>>= 4) != 0); Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags, width, precision);}static void cvt_c(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { if (width == INT_MIN) width = 0; if (width < 0) { flags['-'] = 1; width = -width; } if (!flags['-']) pad(width - 1, ' '); put((unsigned char)va_arg(*app, int), cl); if ( flags['-']) pad(width - 1, ' ');}static void cvt_f(int code, va_list *app, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { char buf[DBL_MAX_10_EXP+1+1+99+1]; if (precision < 0) precision = 6; if (code == 'g' && precision == 0) precision = 1; { static char fmt[] = "%.dd?"; assert(precision <= 99); fmt[4] = code; fmt[3] = precision%10 + '0'; fmt[2] = (precision/10)%10 + '0'; sprintf(buf, fmt, va_arg(*app, double)); } Fmt_putd(buf, strlen(buf), put, cl, flags, width, precision);}const Except_T Fmt_Overflow = { "Formatting Overflow" };static T cvt[256] = { /* 0- 7 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 8- 15 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 16- 23 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 24- 31 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 32- 39 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 40- 47 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 48- 55 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 56- 63 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 64- 71 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 72- 79 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 80- 87 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 88- 95 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 96-103 */ 0, 0, 0, cvt_c, cvt_d, cvt_f, cvt_f, cvt_f, /* 104-111 */ 0, 0, 0, 0, 0, 0, 0, cvt_o, /* 112-119 */ cvt_p, 0, 0, cvt_s, 0, cvt_u, 0, 0, /* 120-127 */ cvt_x, 0, 0, 0, 0, 0, 0, 0};char *Fmt_flags = "-+ 0";static int outc(int c, void *cl) { FILE *f = cl; return putc(c, f);}static int insert(int c, void *cl) { struct buf *p = cl; if (p->bp >= p->buf + p->size) RAISE(Fmt_Overflow); *p->bp++ = c; return c;}static int append(int c, void *cl) { struct buf *p = cl; if (p->bp >= p->buf + p->size) { RESIZE(p->buf, 2*p->size); p->bp = p->buf + p->size; p->size *= 2; } *p->bp++ = c; return c;}void Fmt_puts(const char *str, int len, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { assert(str); assert(len >= 0); assert(flags); if (width == INT_MIN) width = 0; if (width < 0) { flags['-'] = 1; width = -width; } if (precision >= 0) flags['0'] = 0; if (precision >= 0 && precision < len) len = precision; if (!flags['-']) pad(width - len, ' '); { int i; for (i = 0; i < len; i++) put((unsigned char)*str++, cl); } if ( flags['-']) pad(width - len, ' ');}void Fmt_fmt(int put(int c, void *), void *cl, const char *fmt, ...) { va_list ap; va_start(ap, fmt); Fmt_vfmt(put, cl, fmt, ap); va_end(ap);}void Fmt_print(const char *fmt, ...) { va_list ap; va_start(ap, fmt); Fmt_vfmt(outc, stdout, fmt, ap); va_end(ap);}void Fmt_fprint(FILE *stream, const char *fmt, ...) { va_list ap; va_start(ap, fmt); Fmt_vfmt(outc, stream, fmt, ap); va_end(ap);}int Fmt_sfmt(char *buf, int size, const char *fmt, ...) { va_list ap; int len; va_start(ap, fmt); len = Fmt_vsfmt(buf, size, fmt, ap); va_end(ap); return len;}int Fmt_vsfmt(char *buf, int size, const char *fmt, va_list ap) { struct buf cl; assert(buf); assert(size > 0); assert(fmt); cl.buf = cl.bp = buf; cl.size = size; Fmt_vfmt(insert, &cl, fmt, ap); insert(0, &cl); return cl.bp - cl.buf - 1;}char *Fmt_string(const char *fmt, ...) { char *str; va_list ap; assert(fmt); va_start(ap, fmt); str = Fmt_vstring(fmt, ap); va_end(ap); return str;}char *Fmt_vstring(const char *fmt, va_list ap) { struct buf cl; assert(fmt); cl.size = 256; cl.buf = cl.bp = ALLOC(cl.size); Fmt_vfmt(append, &cl, fmt, ap); append(0, &cl); return RESIZE(cl.buf, cl.bp - cl.buf);}void Fmt_vfmt(int put(int c, void *cl), void *cl, const char *fmt, va_list ap) { assert(put); assert(fmt); while (*fmt) if (*fmt != '%' || *++fmt == '%') put((unsigned char)*fmt++, cl); else { unsigned char c, flags[256]; int width = INT_MIN, precision = INT_MIN; memset(flags, '\0', sizeof flags); if (Fmt_flags) { unsigned char c = *fmt; for ( ; c && strchr(Fmt_flags, c); c = *++fmt) { assert(flags[c] < 255); flags[c]++; } } if (*fmt == '*' || isdigit(*fmt)) { int n; if (*fmt == '*') { n = va_arg(ap, int); assert(n != INT_MIN); fmt++; } else for (n = 0; isdigit(*fmt); fmt++) { int d = *fmt - '0'; assert(n <= (INT_MAX - d)/10); n = 10*n + d; } width = n; } if (*fmt == '.' && (*++fmt == '*' || isdigit(*fmt))) { int n; if (*fmt == '*') { n = va_arg(ap, int); assert(n != INT_MIN); fmt++; } else for (n = 0; isdigit(*fmt); fmt++) { int d = *fmt - '0'; assert(n <= (INT_MAX - d)/10); n = 10*n + d; } precision = n; } c = *fmt++; assert(cvt[c]); (*cvt[c])(c, &ap, put, cl, flags, width, precision); }}T Fmt_register(int code, T newcvt) { T old; assert(0 < code && code < (int)(sizeof (cvt)/sizeof (cvt[0]))); old = cvt[code]; cvt[code] = newcvt; return old;}void Fmt_putd(const char *str, int len, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision) { int sign; assert(str); assert(len >= 0); assert(flags); if (width == INT_MIN) width = 0; if (width < 0) { flags['-'] = 1; width = -width; } if (precision >= 0) flags['0'] = 0; if (len > 0 && (*str == '-' || *str == '+')) { sign = *str++; len--; } else if (flags['+']) sign = '+'; else if (flags[' ']) sign = ' '; else sign = 0; { int n; if (precision < 0) precision = 1; if (len < precision) n = precision; else if (precision == 0 && len == 1 && str[0] == '0') n = 0; else n = len; if (sign) n++; if (flags['-']) { if (sign) put(sign, cl); } else if (flags['0']) { if (sign) put(sign, cl); pad(width - n, '0'); } else { pad(width - n, ' '); if (sign) put(sign, cl); } pad(precision - len, '0'); { int i; for (i = 0; i < len; i++) put((unsigned char)*str++, cl); } if (flags['-']) pad(width - n, ' '); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -