📄 snprintf.c
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/common/lib/snprintf.c,v 1.3 2003/01/16 18:18:57 josh Exp $ *//* * Copyright (C) 1999-2005 Wind River Systems, Inc. * All rights reserved. Provided under license only. * Distribution or other use of this software is only * permitted pursuant to the terms of a license agreement * from Wind River Systems (and is otherwise prohibited). * Refer to that license agreement for terms of use. *//**************************************************************************** * Copyright 1999 Integrated Systems, Inc. * All rights reserved. ****************************************************************************//* * Portable implementation of snprintf() and vsnprintf(). This is * derived from publicly-available code, modified to fit Epilogue * coding conventions and strip out the floating point support (which * we don't need). * * Original author's copyright notice: * * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions *//* * $Log: snprintf.c,v $ * Revision 1.3 2003/01/16 18:18:57 josh * directory structure shifting * * Revision 1.2 2001/11/06 22:15:53 tneale * Fixed for newest file layout * * Revision 1.1.1.1 2001/11/05 17:48:39 tneale * Tornado shuffle * * Revision 1.5 2001/01/19 22:21:31 paul * Update copyright. * * Revision 1.4 2000/03/17 00:16:56 meister * Update copyright message * * Revision 1.3 1999/05/21 16:43:51 sra * Minor tweaks to debugging code. * * Revision 1.2 1999/05/20 22:15:12 wes * Call etc_vsnprintf from etc_snprintf * * Revision 1.1 1999/05/20 20:28:17 sra * Add etc_snprintf() and etc_vsnprintf(). * *//* [clearcase]modification history-------------------01b,20apr05,job update copyright notices01a,11dec03,job fix copyright statements*/#include <stdarg.h>#include <wrn/wm/common/config.h>#include <wrn/wm/common/snprintf.h>#include <wrn/wm/common/glue.h>#include <ctype.h>static void dopr (char *buffer, size_t maxlen, const char *format, va_list args);static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max);static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags);static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );/* * dopr(): poor man's version of doprintf *//* format read states */#define DP_S_DEFAULT 0#define DP_S_FLAGS 1#define DP_S_MIN 2#define DP_S_DOT 3#define DP_S_MAX 4#define DP_S_MOD 5#define DP_S_CONV 6#define DP_S_DONE 7/* format flags - Bits */#define DP_F_MINUS (1 << 0)#define DP_F_PLUS (1 << 1)#define DP_F_SPACE (1 << 2)#define DP_F_NUM (1 << 3)#define DP_F_ZERO (1 << 4)#define DP_F_UP (1 << 5)#define DP_F_UNSIGNED (1 << 6)/* Conversion Flags */#define DP_C_SHORT 1#define DP_C_LONG 2#define char_to_int(p) (p - '0')#define MAX(p,q) ((p >= q) ? p : q)static void dopr (char *buffer, size_t maxlen, const char *format, va_list args){ char ch; long value; char *strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if ((ch == '\0') || (currlen >= maxlen)) state = DP_S_DONE; switch(state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else dopr_outch (buffer, &currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (isdigit((int) ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else { state = DP_S_DOT; } break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else { state = DP_S_MOD; } break; case DP_S_MAX: if (isdigit((int) ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); ch = *format++; } else if (ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else { state = DP_S_MOD; } break; case DP_S_MOD: /* Currently, we don't support Long Long, bummer */ switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) value = va_arg (args, short int); else if (cflags == DP_C_LONG) value = va_arg (args, long int); else value = va_arg (args, int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned short int); else if (cflags == DP_C_LONG) value = va_arg (args, unsigned long int); else value = va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned short int); else if (cflags == DP_C_LONG) value = va_arg (args, unsigned long int); else value = va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned short int); else if (cflags == DP_C_LONG) value = va_arg (args, unsigned long int); else value = va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); break; case 'c': dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); if (max < 0) max = maxlen; /* ie, no max */ fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); break; case 'p': strvalue = va_arg (args, void *); fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); break; case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; case '%': dopr_outch (buffer, &currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (currlen < maxlen - 1) buffer[currlen] = '\0'; else buffer[maxlen - 1] = '\0';}static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max){ int padlen; /* amount to pad */ int cnt = 0; if (value == 0) value = "<NULL>"; padlen = min - STRLEN(value); if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } while ((padlen < 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; ++cnt; }}/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */static void fmtint (char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags){ int signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ char *chars = ((flags & DP_F_UP) ? "0123456789ABCDEF" : "0123456789abcdef"); if (max < 0) max = 0; uvalue = value; if (!(flags & DP_F_UNSIGNED)) { if (value < 0) { signvalue = '-'; uvalue = -value; } else if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ signvalue = '+'; } else if (flags & DP_F_SPACE) { signvalue = ' '; } } do { convert[place++] = chars[uvalue % (unsigned) base]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ /* Spaces */ while (spadlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) dopr_outch (buffer, currlen, maxlen, convert[--place]); /* Left Justified spaces */ while (spadlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++spadlen; }}static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c){ if (*currlen < maxlen) buffer[(*currlen)++] = c;}int etc_vsnprintf (char *str, size_t count, const char *fmt, va_list args){ str[0] = 0; dopr(str, count, fmt, args); return(STRLEN(str));}int etc_snprintf (char *str, size_t count, const char *fmt, ...){ va_list ap; va_start(ap, fmt); etc_vsnprintf(str, count, fmt, ap); va_end(ap); return(STRLEN(str));}#ifndef INSTALL_ETC_SNPRINTF_TEST#define INSTALL_ETC_SNPRINTF_TEST defined(ETC_SNPRINTF_TEST_OUTPUT)#endif#if INSTALL_ETC_SNPRINTF_TESTint main (int argc, char *argv[]){ char buf1[1024]; char buf2[1024]; char *int_fmt[] = { "%-1.5d", "%1.5d", "%123.9d", "%5.5d", "%10.5d", "% 10.5d", "%+22.33d", "%01.3d", "%4d", 0 }; long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; int x, y; int fail = 0; int num = 0; ETC_SNPRINTF_TEST_OUTPUT("Testing etc_snprintf() against sprintf()..."); for (x = 0; int_fmt[x] != 0; x++) { for (y = 0; int_nums[y] != 0 ; y++) { etc_snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); sprintf (buf2, int_fmt[x], int_nums[y]); if (STRCMP (buf1, buf2)) { ETC_SNPRINTF_TEST_OUTPUT("\netc_snprintf() doesn't match format: "); ETC_SNPRINTF_TEST_OUTPUT(int_fmt[x]); ETC_SNPRINTF_TEST_OUTPUT("\n\tetc_snprintf() = "); ETC_SNPRINTF_TEST_OUTPUT(buf1); ETC_SNPRINTF_TEST_OUTPUT("\n\tsprintf() = "); ETC_SNPRINTF_TEST_OUTPUT(buf2); ETC_SNPRINTF_TEST_OUTPUT("\n"); fail++; } else { ETC_SNPRINTF_TEST_OUTPUT("."); } num++; } } ETC_SNPRINTF_TEST_OUTPUT("\n"); return fail;}#endif /* INSTALL_ETC_SNPRINTF_TEST */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -