]>
jfr.im git - irc/rqf/shadowircd.git/blob - bandb/rsdb_snprintf.c
2 * libString, Copyright (C) 1999 Patrick Alken
3 * This library comes with absolutely NO WARRANTY
5 * Should you choose to use and/or modify this source code, please
6 * do so under the terms of the GNU General Public License under which
7 * this library is distributed.
14 * This table is arranged in chronological order from 0-999,
15 * however the numbers are written backwards, so the number 100
16 * is expressed in this table as "001".
17 * It's purpose is to ensure fast conversions from integers to
18 * ASCII strings. When an integer variable is encountered, a
19 * simple hash algorithm is used to determine where to look
20 * in this array for the corresponding string.
21 * This outperforms continually dividing by 10 and using the
22 * digit obtained as a character, because we can now divide by
23 * 1000 and use the remainder directly, thus cutting down on
24 * the number of costly divisions needed. For an integer's worst
25 * case, 2 divisions are needed because it can only go up to
26 * 32767, so after 2 divisions by 1000, and some algebra, we will
27 * be left with 327 which we can get from this table. This is much
28 * better than the 5 divisions by 10 that we would need if we did
29 * it the conventional way. Of course, if we made this table go
30 * from 0-9999, only 1 division would be needed.
31 * Longs and unsigned ints of course, are another matter :-).
33 * Patrick Alken <wnder@underworld.net>
37 * Set this to the number of indices (numbers) in our table
39 #define TABLE_MAX 1000
41 static const char *IntTable
[] = {
42 "000", "100", "200", "300", "400",
43 "500", "600", "700", "800", "900",
44 "010", "110", "210", "310", "410",
45 "510", "610", "710", "810", "910",
46 "020", "120", "220", "320", "420",
47 "520", "620", "720", "820", "920",
48 "030", "130", "230", "330", "430",
49 "530", "630", "730", "830", "930",
50 "040", "140", "240", "340", "440",
51 "540", "640", "740", "840", "940",
52 "050", "150", "250", "350", "450",
53 "550", "650", "750", "850", "950",
54 "060", "160", "260", "360", "460",
55 "560", "660", "760", "860", "960",
56 "070", "170", "270", "370", "470",
57 "570", "670", "770", "870", "970",
58 "080", "180", "280", "380", "480",
59 "580", "680", "780", "880", "980",
60 "090", "190", "290", "390", "490",
61 "590", "690", "790", "890", "990",
62 "001", "101", "201", "301", "401",
63 "501", "601", "701", "801", "901",
64 "011", "111", "211", "311", "411",
65 "511", "611", "711", "811", "911",
66 "021", "121", "221", "321", "421",
67 "521", "621", "721", "821", "921",
68 "031", "131", "231", "331", "431",
69 "531", "631", "731", "831", "931",
70 "041", "141", "241", "341", "441",
71 "541", "641", "741", "841", "941",
72 "051", "151", "251", "351", "451",
73 "551", "651", "751", "851", "951",
74 "061", "161", "261", "361", "461",
75 "561", "661", "761", "861", "961",
76 "071", "171", "271", "371", "471",
77 "571", "671", "771", "871", "971",
78 "081", "181", "281", "381", "481",
79 "581", "681", "781", "881", "981",
80 "091", "191", "291", "391", "491",
81 "591", "691", "791", "891", "991",
82 "002", "102", "202", "302", "402",
83 "502", "602", "702", "802", "902",
84 "012", "112", "212", "312", "412",
85 "512", "612", "712", "812", "912",
86 "022", "122", "222", "322", "422",
87 "522", "622", "722", "822", "922",
88 "032", "132", "232", "332", "432",
89 "532", "632", "732", "832", "932",
90 "042", "142", "242", "342", "442",
91 "542", "642", "742", "842", "942",
92 "052", "152", "252", "352", "452",
93 "552", "652", "752", "852", "952",
94 "062", "162", "262", "362", "462",
95 "562", "662", "762", "862", "962",
96 "072", "172", "272", "372", "472",
97 "572", "672", "772", "872", "972",
98 "082", "182", "282", "382", "482",
99 "582", "682", "782", "882", "982",
100 "092", "192", "292", "392", "492",
101 "592", "692", "792", "892", "992",
102 "003", "103", "203", "303", "403",
103 "503", "603", "703", "803", "903",
104 "013", "113", "213", "313", "413",
105 "513", "613", "713", "813", "913",
106 "023", "123", "223", "323", "423",
107 "523", "623", "723", "823", "923",
108 "033", "133", "233", "333", "433",
109 "533", "633", "733", "833", "933",
110 "043", "143", "243", "343", "443",
111 "543", "643", "743", "843", "943",
112 "053", "153", "253", "353", "453",
113 "553", "653", "753", "853", "953",
114 "063", "163", "263", "363", "463",
115 "563", "663", "763", "863", "963",
116 "073", "173", "273", "373", "473",
117 "573", "673", "773", "873", "973",
118 "083", "183", "283", "383", "483",
119 "583", "683", "783", "883", "983",
120 "093", "193", "293", "393", "493",
121 "593", "693", "793", "893", "993",
122 "004", "104", "204", "304", "404",
123 "504", "604", "704", "804", "904",
124 "014", "114", "214", "314", "414",
125 "514", "614", "714", "814", "914",
126 "024", "124", "224", "324", "424",
127 "524", "624", "724", "824", "924",
128 "034", "134", "234", "334", "434",
129 "534", "634", "734", "834", "934",
130 "044", "144", "244", "344", "444",
131 "544", "644", "744", "844", "944",
132 "054", "154", "254", "354", "454",
133 "554", "654", "754", "854", "954",
134 "064", "164", "264", "364", "464",
135 "564", "664", "764", "864", "964",
136 "074", "174", "274", "374", "474",
137 "574", "674", "774", "874", "974",
138 "084", "184", "284", "384", "484",
139 "584", "684", "784", "884", "984",
140 "094", "194", "294", "394", "494",
141 "594", "694", "794", "894", "994",
142 "005", "105", "205", "305", "405",
143 "505", "605", "705", "805", "905",
144 "015", "115", "215", "315", "415",
145 "515", "615", "715", "815", "915",
146 "025", "125", "225", "325", "425",
147 "525", "625", "725", "825", "925",
148 "035", "135", "235", "335", "435",
149 "535", "635", "735", "835", "935",
150 "045", "145", "245", "345", "445",
151 "545", "645", "745", "845", "945",
152 "055", "155", "255", "355", "455",
153 "555", "655", "755", "855", "955",
154 "065", "165", "265", "365", "465",
155 "565", "665", "765", "865", "965",
156 "075", "175", "275", "375", "475",
157 "575", "675", "775", "875", "975",
158 "085", "185", "285", "385", "485",
159 "585", "685", "785", "885", "985",
160 "095", "195", "295", "395", "495",
161 "595", "695", "795", "895", "995",
162 "006", "106", "206", "306", "406",
163 "506", "606", "706", "806", "906",
164 "016", "116", "216", "316", "416",
165 "516", "616", "716", "816", "916",
166 "026", "126", "226", "326", "426",
167 "526", "626", "726", "826", "926",
168 "036", "136", "236", "336", "436",
169 "536", "636", "736", "836", "936",
170 "046", "146", "246", "346", "446",
171 "546", "646", "746", "846", "946",
172 "056", "156", "256", "356", "456",
173 "556", "656", "756", "856", "956",
174 "066", "166", "266", "366", "466",
175 "566", "666", "766", "866", "966",
176 "076", "176", "276", "376", "476",
177 "576", "676", "776", "876", "976",
178 "086", "186", "286", "386", "486",
179 "586", "686", "786", "886", "986",
180 "096", "196", "296", "396", "496",
181 "596", "696", "796", "896", "996",
182 "007", "107", "207", "307", "407",
183 "507", "607", "707", "807", "907",
184 "017", "117", "217", "317", "417",
185 "517", "617", "717", "817", "917",
186 "027", "127", "227", "327", "427",
187 "527", "627", "727", "827", "927",
188 "037", "137", "237", "337", "437",
189 "537", "637", "737", "837", "937",
190 "047", "147", "247", "347", "447",
191 "547", "647", "747", "847", "947",
192 "057", "157", "257", "357", "457",
193 "557", "657", "757", "857", "957",
194 "067", "167", "267", "367", "467",
195 "567", "667", "767", "867", "967",
196 "077", "177", "277", "377", "477",
197 "577", "677", "777", "877", "977",
198 "087", "187", "287", "387", "487",
199 "587", "687", "787", "887", "987",
200 "097", "197", "297", "397", "497",
201 "597", "697", "797", "897", "997",
202 "008", "108", "208", "308", "408",
203 "508", "608", "708", "808", "908",
204 "018", "118", "218", "318", "418",
205 "518", "618", "718", "818", "918",
206 "028", "128", "228", "328", "428",
207 "528", "628", "728", "828", "928",
208 "038", "138", "238", "338", "438",
209 "538", "638", "738", "838", "938",
210 "048", "148", "248", "348", "448",
211 "548", "648", "748", "848", "948",
212 "058", "158", "258", "358", "458",
213 "558", "658", "758", "858", "958",
214 "068", "168", "268", "368", "468",
215 "568", "668", "768", "868", "968",
216 "078", "178", "278", "378", "478",
217 "578", "678", "778", "878", "978",
218 "088", "188", "288", "388", "488",
219 "588", "688", "788", "888", "988",
220 "098", "198", "298", "398", "498",
221 "598", "698", "798", "898", "998",
222 "009", "109", "209", "309", "409",
223 "509", "609", "709", "809", "909",
224 "019", "119", "219", "319", "419",
225 "519", "619", "719", "819", "919",
226 "029", "129", "229", "329", "429",
227 "529", "629", "729", "829", "929",
228 "039", "139", "239", "339", "439",
229 "539", "639", "739", "839", "939",
230 "049", "149", "249", "349", "449",
231 "549", "649", "749", "849", "949",
232 "059", "159", "259", "359", "459",
233 "559", "659", "759", "859", "959",
234 "069", "169", "269", "369", "469",
235 "569", "669", "769", "869", "969",
236 "079", "179", "279", "379", "479",
237 "579", "679", "779", "879", "979",
238 "089", "189", "289", "389", "489",
239 "589", "689", "789", "889", "989",
240 "099", "199", "299", "399", "499",
241 "599", "699", "799", "899", "999"
245 * Since we calculate the right-most digits for %d %u etc first,
246 * we need a temporary buffer to store them in until we get
247 * to the left-most digits
250 #define TEMPBUF_MAX 20
252 static char TempBuffer
[TEMPBUF_MAX
];
256 Backend to Snprintf() - performs the construction of 'dest'
257 using the string 'format' and the given arguments. Also makes sure
258 not more than 'bytes' characters are copied to 'dest'
260 We always allow room for a terminating \0 character, so at most,
261 bytes - 1 characters will be written to dest.
263 Return: Number of characters written, NOT including the terminating
264 \0 character which is *always* placed at the end of the string
266 NOTE: This function handles the following flags only:
268 In addition, this function performs *NO* precision, padding,
269 or width formatting. If it receives an unknown % character,
270 it will call vsprintf() to complete the remainder of the
275 rs_vsnprintf(char *dest
, const size_t bytes
, const char *format
, va_list args
)
278 int written
= 0; /* bytes written so far */
279 int maxbytes
= bytes
- 1;
281 while((ch
= *format
++) && (written
< maxbytes
))
291 * Put the most common cases first - %s %d etc
296 const char *str
= va_arg(args
, const char *);
298 while((*dest
= *str
))
303 if(++written
>= maxbytes
)
312 int num
= va_arg(args
, int);
315 char *digitptr
= TempBuffer
;
318 * We have to special-case "0" unfortunately
330 if(++written
>= maxbytes
)
338 quotient
= num
/ TABLE_MAX
;
341 * We'll start with the right-most digits of 'num'.
342 * Dividing by TABLE_MAX cuts off all but the X
343 * right-most digits, where X is such that:
347 * For example, if num = 1200, and TABLE_MAX = 1000,
348 * quotient will be 1. Multiplying this by 1000 and
349 * subtracting from 1200 gives: 1200 - (1 * 1000) = 200.
350 * We then go right to slot 200 in our array and behold!
351 * The string "002" (200 backwards) is conveniently
352 * waiting for us. Then repeat the process with the
355 * The reason we need to have the integers written
356 * backwards, is because we don't know how many digits
357 * there are. If we want to express the number 12130
358 * for example, our first pass would leave us with 130,
359 * whose slot in the array yields "031", which we
360 * plug into our TempBuffer[]. The next pass gives us
361 * 12, whose slot yields "21" which we append to
362 * TempBuffer[], leaving us with "03121". This is the
363 * exact number we want, only backwards, so it is
364 * a simple matter to reverse the string. If we used
365 * straightfoward numbers, we would have a TempBuffer
366 * looking like this: "13012" which would be a nightmare
370 str
= IntTable
[num
- (quotient
* TABLE_MAX
)];
372 while((*digitptr
= *str
))
378 while((num
= quotient
) != 0);
381 * If the last quotient was a 1 or 2 digit number, there
382 * will be one or more leading zeroes in TempBuffer[] -
385 while(*(digitptr
- 1) == '0')
388 while(digitptr
!= TempBuffer
)
390 *dest
++ = *--digitptr
;
391 if(++written
>= maxbytes
)
396 } /* if (ch == 'd') */
400 *dest
++ = va_arg(args
, int);
405 } /* if (ch == 'c') */
409 unsigned int num
= va_arg(args
, unsigned int);
410 unsigned int quotient
;
412 char *digitptr
= TempBuffer
;
423 quotient
= num
/ TABLE_MAX
;
426 * Very similar to case 'd'
429 str
= IntTable
[num
- (quotient
* TABLE_MAX
)];
431 while((*digitptr
= *str
))
437 while((num
= quotient
) != 0);
439 while(*(digitptr
- 1) == '0')
442 while(digitptr
!= TempBuffer
)
444 *dest
++ = *--digitptr
;
445 if(++written
>= maxbytes
)
450 } /* if (ch == 'u') */
454 const char *arg
= va_arg(args
, const char *);
459 const char *str
= rsdb_quote(arg
);
461 while((*dest
= *str
))
466 if(++written
>= maxbytes
)
477 unsigned long num
= va_arg(args
, unsigned long);
478 unsigned long quotient
;
480 char *digitptr
= TempBuffer
;
493 quotient
= num
/ TABLE_MAX
;
496 * Very similar to case 'u'
499 str
= IntTable
[num
- (quotient
* TABLE_MAX
)];
501 while((*digitptr
= *str
))
507 while((num
= quotient
) != 0);
509 while(*(digitptr
- 1) == '0')
512 while(digitptr
!= TempBuffer
)
514 *dest
++ = *--digitptr
;
515 if(++written
>= maxbytes
)
522 /* if (*format == 'u') */ if(*format
== 'd')
524 long num
= va_arg(args
, long);
527 char *digitptr
= TempBuffer
;
541 if(++written
>= maxbytes
)
549 quotient
= num
/ TABLE_MAX
;
551 str
= IntTable
[num
- (quotient
* TABLE_MAX
)];
553 while((*digitptr
= *str
))
559 while((num
= quotient
) != 0);
561 while(*(digitptr
- 1) == '0')
564 while(digitptr
!= TempBuffer
)
566 *dest
++ = *--digitptr
;
567 if(++written
>= maxbytes
)
573 else /* if (*format == 'd') */
580 } /* if (ch == 'l') */
586 } /* if (ch != '%') */
587 } /* if (ch == '%') */
591 } /* while ((ch = *format++) && (written < maxbytes)) */
594 * Terminate the destination buffer with a \0
603 Optimized version of snprintf().
605 Inputs: dest - destination string
606 bytes - number of bytes to copy
607 format - formatted string
608 args - args to 'format'
610 Return: number of characters copied, NOT including the terminating
611 NULL which is always placed at the end of the string
615 rs_snprintf(char *dest
, const size_t bytes
, const char *format
, ...)
620 va_start(args
, format
);
622 count
= rs_vsnprintf(dest
, bytes
, format
, args
);