| 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 | |