/src/server/strings/int2str.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2000 TXT DataKonsult Ab & Monty Program Ab |
2 | | Copyright (c) 2009-2011, Monty Program Ab |
3 | | |
4 | | Redistribution and use in source and binary forms, with or without |
5 | | modification, are permitted provided that the following conditions are |
6 | | met: |
7 | | |
8 | | 1. Redistributions of source code must retain the above copyright |
9 | | notice, this list of conditions and the following disclaimer. |
10 | | |
11 | | 2. Redistributions in binary form must the following disclaimer in |
12 | | the documentation and/or other materials provided with the |
13 | | distribution. |
14 | | |
15 | | THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY |
16 | | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
18 | | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR |
19 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
20 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
21 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
22 | | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
24 | | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
25 | | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | | SUCH DAMAGE. |
27 | | */ |
28 | | |
29 | | #include "strings_def.h" |
30 | | |
31 | | /* |
32 | | _dig_vec arrays are public because they are used in several outer places. |
33 | | */ |
34 | | const char _dig_vec_base62[] = |
35 | | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
36 | | const char _dig_vec_upper[] = |
37 | | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
38 | | const char _dig_vec_lower[] = |
39 | | "0123456789abcdefghijklmnopqrstuvwxyz"; |
40 | | |
41 | | |
42 | | /* |
43 | | Convert integer to its string representation in given scale of notation. |
44 | | |
45 | | SYNOPSIS |
46 | | int2str() |
47 | | val - value to convert |
48 | | dst - points to buffer where string representation should be stored |
49 | | radix - radix of scale of notation |
50 | | upcase - set to 1 if we should use upper-case digits |
51 | | |
52 | | DESCRIPTION |
53 | | Converts the (long) integer value to its character form and moves it to |
54 | | the destination buffer followed by a terminating NUL. |
55 | | If radix is -2..-62, val is taken to be SIGNED, if radix is 2..62, val is |
56 | | taken to be UNSIGNED. That is, val is signed if and only if radix is. |
57 | | All other radixes treated as bad and nothing will be changed in this case. |
58 | | |
59 | | For conversion to decimal representation (radix is -10 or 10) one can use |
60 | | optimized int10_to_str() function. |
61 | | |
62 | | RETURN VALUE |
63 | | Pointer to ending NUL character or NullS if radix is bad. |
64 | | */ |
65 | | |
66 | | char * |
67 | | int2str(register long int val, register char *dst, register int radix, |
68 | | int upcase) |
69 | 0 | { |
70 | 0 | char buffer[65]; |
71 | 0 | register char *p; |
72 | 0 | long int new_val; |
73 | 0 | const char *dig_vec; |
74 | 0 | ulong uval= (ulong) val; |
75 | |
|
76 | 0 | if (radix < -36 || radix > 36) |
77 | 0 | dig_vec= _dig_vec_base62; |
78 | 0 | else |
79 | 0 | dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower; |
80 | |
|
81 | 0 | if (radix < 0) |
82 | 0 | { |
83 | 0 | if (radix < -62 || radix > -2) |
84 | 0 | return NullS; |
85 | 0 | if (val < 0) |
86 | 0 | { |
87 | 0 | *dst++ = '-'; |
88 | | /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ |
89 | 0 | uval = (ulong)0 - uval; |
90 | 0 | } |
91 | 0 | radix = -radix; |
92 | 0 | } |
93 | 0 | else if (radix > 62 || radix < 2) |
94 | 0 | return NullS; |
95 | | |
96 | | /* |
97 | | The slightly contorted code which follows is due to the fact that |
98 | | few machines directly support unsigned long / and %. Certainly |
99 | | the VAX C compiler generates a subroutine call. In the interests |
100 | | of efficiency (hollow laugh) I let this happen for the first digit |
101 | | only; after that "val" will be in range so that signed integer |
102 | | division will do. Sorry 'bout that. CHECK THE CODE PRODUCED BY |
103 | | YOUR C COMPILER. The first % and / should be unsigned, the second |
104 | | % and / signed, but C compilers tend to be extraordinarily |
105 | | sensitive to minor details of style. This works on a VAX, that's |
106 | | all I claim for it. |
107 | | */ |
108 | 0 | p = &buffer[sizeof(buffer)-1]; |
109 | 0 | *p = '\0'; |
110 | 0 | new_val= uval / (ulong) radix; |
111 | 0 | *--p = dig_vec[(uchar) (uval- (ulong) new_val*(ulong) radix)]; |
112 | 0 | val = new_val; |
113 | 0 | #ifdef HAVE_LDIV |
114 | 0 | while (val != 0) |
115 | 0 | { |
116 | 0 | ldiv_t res; |
117 | 0 | res=ldiv(val,radix); |
118 | 0 | *--p = dig_vec[res.rem]; |
119 | 0 | val= res.quot; |
120 | 0 | } |
121 | | #else |
122 | | while (val != 0) |
123 | | { |
124 | | new_val=val/radix; |
125 | | *--p = dig_vec[(uchar) (val-new_val*radix)]; |
126 | | val= new_val; |
127 | | } |
128 | | #endif |
129 | 0 | while ((*dst++ = *p++) != 0) ; |
130 | 0 | return dst-1; |
131 | 0 | } |
132 | | |
133 | | |
134 | | /* |
135 | | Converts integer to its string representation in decimal notation. |
136 | | |
137 | | SYNOPSIS |
138 | | int10_to_str() |
139 | | val - value to convert |
140 | | dst - points to buffer where string representation should be stored |
141 | | radix - flag that shows whenever val should be taken as signed or not |
142 | | |
143 | | DESCRIPTION |
144 | | This is version of int2str() function which is optimized for normal case |
145 | | of radix 10/-10. It takes only sign of radix parameter into account and |
146 | | not its absolute value. |
147 | | |
148 | | RETURN VALUE |
149 | | Pointer to ending NUL character. |
150 | | */ |
151 | | |
152 | | char *int10_to_str(long int val,char *dst,int radix) |
153 | 0 | { |
154 | 0 | char buffer[65]; |
155 | 0 | register char *p; |
156 | 0 | long int new_val; |
157 | 0 | unsigned long int uval = (unsigned long int) val; |
158 | |
|
159 | 0 | if (radix < 0) /* -10 */ |
160 | 0 | { |
161 | 0 | if (val < 0) |
162 | 0 | { |
163 | 0 | *dst++ = '-'; |
164 | | /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ |
165 | 0 | uval = (unsigned long int)0 - uval; |
166 | 0 | } |
167 | 0 | } |
168 | |
|
169 | 0 | p = &buffer[sizeof(buffer)-1]; |
170 | 0 | *p = '\0'; |
171 | 0 | new_val= (long) (uval / 10); |
172 | 0 | *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); |
173 | 0 | val = new_val; |
174 | |
|
175 | 0 | while (val != 0) |
176 | 0 | { |
177 | 0 | new_val=val/10; |
178 | 0 | *--p = '0' + (char) (val-new_val*10); |
179 | 0 | val= new_val; |
180 | 0 | } |
181 | 0 | while ((*dst++ = *p++) != 0) ; |
182 | 0 | return dst-1; |
183 | 0 | } |