snprintf.c (5993B)
1 /* $Id: //depot/blt/lib/snprintf.c#2 $ 2 ** 3 ** Copyright 1998 Brian J. Swetland 4 ** All rights reserved. 5 ** 6 ** Redistribution and use in source and binary forms, with or without 7 ** modification, are permitted provided that the following conditions 8 ** are met: 9 ** 1. Redistributions of source code must retain the above copyright 10 ** notice, this list of conditions, and the following disclaimer. 11 ** 2. Redistributions in binary form must reproduce the above copyright 12 ** notice, this list of conditions, and the following disclaimer in the 13 ** documentation and/or other materials provided with the distribution. 14 ** 3. The name of the author may not be used to endorse or promote products 15 ** derived from this software without specific prior written permission. 16 ** 17 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* Copyright 1997, Brian J. Swetland <swetland@neog.com> 30 ** Free for non-commercial use. Share and enjoy 31 ** 32 ** Minimal snprintf() function. 33 ** %s - string %d - signed int %x - 32bit hex number (0 padded) 34 ** %c - character %u - unsigned int %X - 8bit hex number (0 padded) 35 */ 36 37 #include <stdarg.h> 38 39 static char hexmap[] = { 40 '0', '1', '2', '3', '4', '5', '6', '7', 41 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 42 }; 43 44 void va_snprintf(char *b, int l, char *fmt, va_list pvar) 45 { 46 int n,i; 47 unsigned u; 48 unsigned long long ull; 49 char *t,d[10], mod_l, mod_ll; 50 51 if(!fmt || !b || (l < 1)) return; 52 53 mod_l = mod_ll = 0; 54 while(l && *fmt) { 55 if(*fmt == '%'){ 56 if(!(--l)) break; 57 again: 58 fmt++; 59 60 switch(*fmt){ 61 case 'l': /* long modifier */ 62 if (!mod_l) 63 mod_l = 1; 64 else if (!mod_ll) 65 { 66 mod_l = 0; 67 mod_ll = 1; 68 } 69 goto again; 70 71 case 's': /* string */ 72 t = va_arg(pvar,char *); 73 while(l && *t) *b++ = *t++, l--; 74 break; 75 76 case 'c': /* single character */ 77 *b++ = va_arg(pvar,char); 78 l--; 79 break; 80 81 case 'S': /* uint32 as a short ... */ 82 if(l < 4) { l = 0; break; } 83 u = va_arg(pvar,unsigned int); 84 for(i=3;i>=0;i--){ 85 b[i] = hexmap[u & 0x0F]; 86 u >>= 4; 87 } 88 b+=4; 89 l-=4; 90 break; 91 92 case 'x': 93 case 'p': 94 if (!mod_ll) { /* 8 digit, unsigned 32-bit hex integer */ 95 if(l < 8) { l = 0; break; } 96 u = va_arg(pvar,unsigned int); 97 for(i=7;i>=0;i--){ 98 b[i] = hexmap[u & 0x0F]; 99 u >>= 4; 100 } 101 b+=8; 102 l-=8; 103 } 104 else if (mod_ll) { /* 16 digit, unsigned 64-bit hex integer */ 105 if (l < 16) { l = 0; break; } 106 ull = va_arg (pvar, unsigned long long); 107 for (i = 15; i >= 0; i--) { 108 b[i] = hexmap[ull & 0x0f]; 109 ull >>= 4; 110 } 111 b += 16; 112 l -= 16; 113 } 114 mod_l = mod_ll = 0; 115 break; 116 117 case 'd': /* signed integer */ 118 n = va_arg(pvar,int); 119 if(n < 0) { 120 u = -n; 121 *b++ = '-'; 122 if(!(--l)) break; 123 } else { 124 u = n; 125 } 126 goto u2; 127 128 case 'u': /* unsigned integer */ 129 u = va_arg(pvar,unsigned int); 130 u2: 131 i = 9; 132 do { 133 d[i] = (u % 10) + '0'; 134 u /= 10; 135 i--; 136 } while(u && i >= 0); 137 while(++i < 10){ 138 *b++ = d[i]; 139 if(!(--l)) break; 140 } 141 break; 142 143 case 'U': 144 u = va_arg(pvar,unsigned int); 145 i = 9; 146 d[8] = d[7] = d[6] = ' '; 147 do { 148 d[i] = (u % 10) + '0'; 149 u /= 10; 150 i--; 151 } while(u && i >= 0); 152 i = 5; 153 while(++i < 10){ 154 *b++ = d[i]; 155 if(!(--l)) break; 156 } 157 break; 158 159 case 'X': /* 2 digit, unsigned 8bit hex int */ 160 if(l < 2) { l = 0; break; } 161 n = va_arg(pvar,int); 162 *b++ = hexmap[(n & 0xF0) >> 4]; 163 *b++ = hexmap[n & 0x0F]; 164 l-=2; 165 break; 166 default: 167 *b++ = *fmt; 168 } 169 } else { 170 *b++ = *fmt; 171 l--; 172 } 173 fmt++; 174 } 175 *b = 0; 176 } 177 178 void snprintf(char *str, int len, char *fmt, ...) 179 { 180 va_list pvar; 181 va_start(pvar,fmt); 182 va_snprintf(str,len,fmt,pvar); 183 va_end(pvar); 184 } 185 186