1 /* fmt/sllnum.c - Format a signed long long integer.
2  * Copyright (C) 2004,2005  Bruce Guenter <bruce@untroubled.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  */
18 #include "fmt.h"
19 
rec(char * buffer,long long num,int sign,unsigned width,char pad,unsigned base,const char * digits)20 static unsigned rec(char* buffer, long long num, int sign,
21 		    unsigned width, char pad,
22 		    unsigned base, const char* digits)
23 {
24   char* s = buffer;
25   if (width) --width;
26   if (num >= (long long)base)
27     s += rec(s, num/base, sign, width, pad, base, digits);
28   else
29     s += fmt_sign_pad(s, sign, width, pad);
30   *s++ = digits[num % base];
31   return s - buffer;
32 }
33 
34 /** Format a signed long long integer of arbitrary base with optional
35     padding. */
fmt_sllnumw(char * buffer,long long num,unsigned width,char pad,unsigned base,const char * digits)36 unsigned fmt_sllnumw(char* buffer, long long num, unsigned width, char pad,
37 		     unsigned base, const char* digits)
38 {
39   char* s = buffer;
40   int sign;
41 
42   sign = 0;
43   if (num < 0) {
44     sign = 1;
45     num = -num;
46     if (width) -- width;
47   }
48   if (buffer == 0) {
49     unsigned len;
50     for (len = 1; num >= base; ++len)
51       num /= base;
52     return ((width > len) ? width : len) + sign;
53   }
54   if (num < (long long)base) {
55     s += fmt_sign_pad(s, sign, width-1, pad);
56     *s++ = digits[num];
57   }
58   else
59     s += rec(s, num, sign, width, pad, base, digits);
60   return s - buffer;
61 }
62 
63 #ifdef SELFTEST_MAIN
test(long long num,unsigned width,char pad)64 void test(long long num, unsigned width, char pad)
65 {
66   char buf[FMT_ULONG_LEN];
67   obuf_putu(&outbuf, fmt_slldecw(0, num, width, pad));
68   obuf_putc(&outbuf, ':');
69   buf[fmt_sdecw(buf, num, width, pad)] = 0;
70   obuf_puts(&outbuf, buf);
71   NL();
72 }
73 
74 MAIN
75 {
76   test(  0, 0,   0);
77   test( 10, 0,   0);
78   test(-10, 0,   0);
79   test( 10, 1, '0');
80   test(-10, 1, '0');
81   test( 10, 5, ' ');
82   test( 10, 5, '0');
83   test(-10, 5, ' ');
84   test(-10, 5, '0');
85 }
86 #endif
87 #ifdef SELFTEST_EXP
88 1:0
89 2:10
90 3:-10
91 2:10
92 3:-10
93 5:   10
94 5:00010
95 5:  -10
96 5:-0010
97 #endif
98