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_upper[] = |
35 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; |
36 | const char _dig_vec_lower[] = |
37 | "0123456789abcdefghijklmnopqrstuvwxyz" ; |
38 | |
39 | |
40 | /* |
41 | Convert integer to its string representation in given scale of notation. |
42 | |
43 | SYNOPSIS |
44 | int2str() |
45 | val - value to convert |
46 | dst - points to buffer where string representation should be stored |
47 | radix - radix of scale of notation |
48 | upcase - set to 1 if we should use upper-case digits |
49 | |
50 | DESCRIPTION |
51 | Converts the (long) integer value to its character form and moves it to |
52 | the destination buffer followed by a terminating NUL. |
53 | If radix is -2..-36, val is taken to be SIGNED, if radix is 2..36, val is |
54 | taken to be UNSIGNED. That is, val is signed if and only if radix is. |
55 | All other radixes treated as bad and nothing will be changed in this case. |
56 | |
57 | For conversion to decimal representation (radix is -10 or 10) one can use |
58 | optimized int10_to_str() function. |
59 | |
60 | RETURN VALUE |
61 | Pointer to ending NUL character or NullS if radix is bad. |
62 | */ |
63 | |
64 | char * |
65 | int2str(register long int val, register char *dst, register int radix, |
66 | int upcase) |
67 | { |
68 | char buffer[65]; |
69 | register char *p; |
70 | long int new_val; |
71 | const char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower; |
72 | ulong uval= (ulong) val; |
73 | |
74 | if (radix < 0) |
75 | { |
76 | if (radix < -36 || radix > -2) |
77 | return NullS; |
78 | if (val < 0) |
79 | { |
80 | *dst++ = '-'; |
81 | /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ |
82 | uval = (ulong)0 - uval; |
83 | } |
84 | radix = -radix; |
85 | } |
86 | else if (radix > 36 || radix < 2) |
87 | return NullS; |
88 | |
89 | /* |
90 | The slightly contorted code which follows is due to the fact that |
91 | few machines directly support unsigned long / and %. Certainly |
92 | the VAX C compiler generates a subroutine call. In the interests |
93 | of efficiency (hollow laugh) I let this happen for the first digit |
94 | only; after that "val" will be in range so that signed integer |
95 | division will do. Sorry 'bout that. CHECK THE CODE PRODUCED BY |
96 | YOUR C COMPILER. The first % and / should be unsigned, the second |
97 | % and / signed, but C compilers tend to be extraordinarily |
98 | sensitive to minor details of style. This works on a VAX, that's |
99 | all I claim for it. |
100 | */ |
101 | p = &buffer[sizeof(buffer)-1]; |
102 | *p = '\0'; |
103 | new_val= uval / (ulong) radix; |
104 | *--p = dig_vec[(uchar) (uval- (ulong) new_val*(ulong) radix)]; |
105 | val = new_val; |
106 | #ifdef HAVE_LDIV |
107 | while (val != 0) |
108 | { |
109 | ldiv_t res; |
110 | res=ldiv(val,radix); |
111 | *--p = dig_vec[res.rem]; |
112 | val= res.quot; |
113 | } |
114 | #else |
115 | while (val != 0) |
116 | { |
117 | new_val=val/radix; |
118 | *--p = dig_vec[(uchar) (val-new_val*radix)]; |
119 | val= new_val; |
120 | } |
121 | #endif |
122 | while ((*dst++ = *p++) != 0) ; |
123 | return dst-1; |
124 | } |
125 | |
126 | |
127 | /* |
128 | Converts integer to its string representation in decimal notation. |
129 | |
130 | SYNOPSIS |
131 | int10_to_str() |
132 | val - value to convert |
133 | dst - points to buffer where string representation should be stored |
134 | radix - flag that shows whenever val should be taken as signed or not |
135 | |
136 | DESCRIPTION |
137 | This is version of int2str() function which is optimized for normal case |
138 | of radix 10/-10. It takes only sign of radix parameter into account and |
139 | not its absolute value. |
140 | |
141 | RETURN VALUE |
142 | Pointer to ending NUL character. |
143 | */ |
144 | |
145 | char *int10_to_str(long int val,char *dst,int radix) |
146 | { |
147 | char buffer[65]; |
148 | register char *p; |
149 | long int new_val; |
150 | unsigned long int uval = (unsigned long int) val; |
151 | |
152 | if (radix < 0) /* -10 */ |
153 | { |
154 | if (val < 0) |
155 | { |
156 | *dst++ = '-'; |
157 | /* Avoid integer overflow in (-val) for LONGLONG_MIN (BUG#31799). */ |
158 | uval = (unsigned long int)0 - uval; |
159 | } |
160 | } |
161 | |
162 | p = &buffer[sizeof(buffer)-1]; |
163 | *p = '\0'; |
164 | new_val= (long) (uval / 10); |
165 | *--p = '0'+ (char) (uval - (unsigned long) new_val * 10); |
166 | val = new_val; |
167 | |
168 | while (val != 0) |
169 | { |
170 | new_val=val/10; |
171 | *--p = '0' + (char) (val-new_val*10); |
172 | val= new_val; |
173 | } |
174 | while ((*dst++ = *p++) != 0) ; |
175 | return dst-1; |
176 | } |
177 | |