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