Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998-1999 Brian Bruns
3 : * Copyright (C) 2005-2015 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #include <stdarg.h>
24 : #include <stdio.h>
25 :
26 : #if HAVE_STRING_H
27 : #include <string.h>
28 : #endif /* HAVE_STRING_H */
29 :
30 : #include <freetds/tds.h>
31 : #include <freetds/convert.h>
32 : #include <freetds/bytes.h>
33 : #include <freetds/windows.h>
34 : #include <stdlib.h>
35 :
36 : /**
37 : * tds_numeric_bytes_per_prec is indexed by precision and will
38 : * tell us the number of bytes required to store the specified
39 : * precision (with the sign).
40 : * Support precision up to 77 digits
41 : */
42 : const int tds_numeric_bytes_per_prec[] = {
43 : /*
44 : * precision can't be 0 but using a value > 0 assure no
45 : * core if for some bug it's 0...
46 : */
47 : 1,
48 : 2, 2, 3, 3, 4, 4, 4, 5, 5,
49 : 6, 6, 6, 7, 7, 8, 8, 9, 9, 9,
50 : 10, 10, 11, 11, 11, 12, 12, 13, 13, 14,
51 : 14, 14, 15, 15, 16, 16, 16, 17, 17, 18,
52 : 18, 19, 19, 19, 20, 20, 21, 21, 21, 22,
53 : 22, 23, 23, 24, 24, 24, 25, 25, 26, 26,
54 : 26, 27, 27, 28, 28, 28, 29, 29, 30, 30,
55 : 31, 31, 31, 32, 32, 33, 33, 33
56 : };
57 :
58 : TDS_COMPILE_CHECK(maxprecision,
59 : MAXPRECISION < TDS_VECTOR_SIZE(tds_numeric_bytes_per_prec) );
60 :
61 : /*
62 : * money is a special case of numeric really...that why its here
63 : */
64 : char *
65 1592 : tds_money_to_string(const TDS_MONEY * money, char *s, bool use_2_digits)
66 : {
67 : TDS_INT8 mymoney;
68 : TDS_UINT8 n;
69 : char *p;
70 :
71 : /* sometimes money it's only 4-byte aligned so always compute 64-bit */
72 1592 : mymoney = (((TDS_INT8) money->tdsoldmoney.mnyhigh) << 32) | money->tdsoldmoney.mnylow;
73 :
74 1592 : p = s;
75 1592 : if (mymoney < 0) {
76 360 : *p++ = '-';
77 : /* we use unsigned cause this cause arithmetic problem for -2^63*/
78 360 : n = -mymoney;
79 : } else {
80 1232 : n = mymoney;
81 : }
82 : /* if machine is 64 bit you do not need to split n */
83 1592 : if (use_2_digits) {
84 0 : n = (n+ 50) / 100;
85 0 : sprintf(p, "%" PRIu64 ".%02u", n / 100u, (unsigned) (n % 100u));
86 : } else {
87 1592 : sprintf(p, "%" PRIu64 ".%04u", n / 10000u, (unsigned) (n % 10000u));
88 : }
89 1592 : return s;
90 : }
91 :
92 : /**
93 : * @return <0 if error
94 : */
95 : TDS_INT
96 10444 : tds_numeric_to_string(const TDS_NUMERIC * numeric, char *s)
97 : {
98 : const unsigned char *number;
99 :
100 : unsigned int packet[sizeof(numeric->array) / 2];
101 : unsigned int *pnum, *packet_start;
102 10444 : unsigned int *const packet_end = packet + TDS_VECTOR_SIZE(packet);
103 :
104 : unsigned int packet10k[(MAXPRECISION + 3) / 4];
105 : unsigned int *p;
106 :
107 : int num_bytes;
108 : unsigned int remainder, n, i, m;
109 :
110 : /* a bit of debug */
111 : #if ENABLE_EXTRA_CHECKS
112 10444 : memset(packet, 0x55, sizeof(packet));
113 10444 : memset(packet10k, 0x55, sizeof(packet10k));
114 : #endif
115 :
116 10444 : if (numeric->precision < 1 || numeric->precision > MAXPRECISION || numeric->scale > numeric->precision)
117 : return TDS_CONVERT_FAIL;
118 :
119 : /* set sign */
120 10444 : if (numeric->array[0] == 1)
121 4078 : *s++ = '-';
122 :
123 : /* put number in a 16bit array */
124 10444 : number = numeric->array;
125 10444 : num_bytes = tds_numeric_bytes_per_prec[numeric->precision];
126 :
127 10444 : n = num_bytes - 1;
128 10444 : pnum = packet_end;
129 52678 : for (; n > 1; n -= 2)
130 42234 : *--pnum = TDS_GET_UA2BE(&number[n - 1]);
131 10444 : if (n == 1)
132 9590 : *--pnum = number[n];
133 39256 : while (!*pnum) {
134 28948 : ++pnum;
135 28948 : if (pnum == packet_end) {
136 136 : *s++ = '0';
137 136 : if (numeric->scale) {
138 8 : *s++ = '.';
139 8 : i = numeric->scale;
140 : do {
141 32 : *s++ = '0';
142 32 : } while (--i);
143 : }
144 136 : *s = 0;
145 136 : return 1;
146 : }
147 : }
148 : packet_start = pnum;
149 :
150 : /* transform 2^16 base number in 10^4 base number */
151 37366 : for (p = packet10k + TDS_VECTOR_SIZE(packet10k); packet_start != packet_end;) {
152 27058 : pnum = packet_start;
153 27058 : n = *pnum;
154 27058 : remainder = n % 10000u;
155 27058 : if (!(*pnum++ = (n / 10000u)))
156 22876 : packet_start = pnum;
157 28370 : for (; pnum != packet_end; ++pnum) {
158 28370 : n = remainder * (256u * 256u) + *pnum;
159 28370 : remainder = n % 10000u;
160 28370 : *pnum = n / 10000u;
161 : }
162 27058 : *--p = remainder;
163 : }
164 :
165 : /* transform to 10 base number and output */
166 10308 : i = 4 * (unsigned int)((packet10k + TDS_VECTOR_SIZE(packet10k)) - p); /* current digit */
167 : /* skip leading zeroes */
168 10308 : n = 1000;
169 10308 : remainder = *p;
170 37194 : while (remainder < n)
171 16578 : n /= 10, --i;
172 10308 : if (i <= numeric->scale) {
173 32 : *s++ = '0';
174 32 : *s++ = '.';
175 32 : m = i;
176 128 : while (m < numeric->scale)
177 64 : *s++ = '0', ++m;
178 : }
179 : for (;;) {
180 91654 : *s++ = (remainder / n) + '0';
181 91654 : --i;
182 91654 : remainder %= n;
183 91654 : n /= 10;
184 91654 : if (!n) {
185 27058 : n = 1000;
186 27058 : if (++p == packet10k + TDS_VECTOR_SIZE(packet10k))
187 : break;
188 16750 : remainder = *p;
189 : }
190 81346 : if (i == numeric->scale)
191 1150 : *s++ = '.';
192 : }
193 10308 : *s = 0;
194 :
195 10308 : return 1;
196 : }
197 :
198 : #define TDS_WORD uint32_t
199 : #define TDS_DWORD uint64_t
200 : #define TDS_WORD_DDIGIT 9
201 :
202 : /* include to check limits */
203 :
204 : #include "num_limits.h"
205 :
206 : static int
207 35054 : tds_packet_check_overflow(TDS_WORD *packet, unsigned int packet_len, unsigned int prec)
208 : {
209 : unsigned int i, len, stop;
210 35054 : const TDS_WORD *limit = &limits[limit_indexes[prec] + LIMIT_INDEXES_ADJUST * prec];
211 35054 : len = limit_indexes[prec+1] - limit_indexes[prec] + LIMIT_INDEXES_ADJUST;
212 35054 : stop = prec / (sizeof(TDS_WORD) * 8);
213 : /*
214 : * Now a number is
215 : * ... P[3] P[2] P[1] P[0]
216 : * while upper limit + 1 is
217 : * zeroes limit[0 .. len-1] 0[0 .. stop-1]
218 : * we must assure that number < upper limit + 1
219 : */
220 35054 : if (packet_len >= len + stop) {
221 : /* higher packets must be zero */
222 26794 : for (i = packet_len; --i >= len + stop; )
223 7640 : if (packet[i] > 0)
224 : return TDS_CONVERT_OVERFLOW;
225 : /* test limit */
226 0 : for (;; --i, ++limit) {
227 19154 : if (i <= stop) {
228 : /* last must be >= not > */
229 16050 : if (packet[i] >= *limit)
230 : return TDS_CONVERT_OVERFLOW;
231 : break;
232 : }
233 3104 : if (packet[i] > *limit)
234 : return TDS_CONVERT_OVERFLOW;
235 928 : if (packet[i] < *limit)
236 : break;
237 : }
238 : }
239 18190 : return 0;
240 : }
241 :
242 : #undef USE_128_MULTIPLY
243 : #if defined(__GNUC__) && SIZEOF___INT128 > 0
244 : #define USE_128_MULTIPLY 1
245 : #undef __umulh
246 : #define __umulh(multiplier, multiplicand) \
247 : ((uint64_t) ((((unsigned __int128) (multiplier)) * (multiplicand)) >> 64))
248 : #endif
249 : #if defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64))
250 : #include <intrin.h>
251 : #define USE_128_MULTIPLY 1
252 : #endif
253 :
254 : #undef USE_I386_DIVIDE
255 : #undef USE_64_MULTIPLY
256 : #ifndef USE_128_MULTIPLY
257 : # if defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__)
258 : # define USE_I386_DIVIDE 1
259 : # else
260 : # define USE_64_MULTIPLY
261 : # endif
262 : #endif
263 :
264 : TDS_INT
265 64298 : tds_numeric_change_prec_scale(TDS_NUMERIC * numeric, unsigned char new_prec, unsigned char new_scale)
266 : {
267 : #define TDS_WORD_BITS (8 * sizeof(TDS_WORD))
268 : static const TDS_WORD factors[] = {
269 : 1, 10, 100, 1000, 10000,
270 : 100000, 1000000, 10000000, 100000000, 1000000000
271 : };
272 : #ifndef USE_I386_DIVIDE
273 : /* These numbers are computed as
274 : * (2 ** (reverse_dividers_shift[i] + 64)) / (10 ** i) + 1
275 : * (** is power).
276 : * The shifts are computed to make sure the multiplication error
277 : * does not cause a wrong result.
278 : *
279 : * See also misc/reverse_divisor script.
280 : */
281 : static const TDS_DWORD reverse_dividers[] = {
282 : 1 /* not used */,
283 : UINT64_C(1844674407370955162),
284 : UINT64_C(184467440737095517),
285 : UINT64_C(18446744073709552),
286 : UINT64_C(1844674407370956),
287 : UINT64_C(737869762948383),
288 : UINT64_C(2361183241434823),
289 : UINT64_C(15111572745182865),
290 : UINT64_C(48357032784585167),
291 : UINT64_C(1237940039285380275),
292 : };
293 : static const uint8_t reverse_dividers_shift[] = {
294 : 0 /* not used */,
295 : 0,
296 : 0,
297 : 0,
298 : 0,
299 : 2,
300 : 7,
301 : 13,
302 : 18,
303 : 26,
304 : };
305 : #endif
306 :
307 : TDS_WORD packet[(sizeof(numeric->array) - 1) / sizeof(TDS_WORD)];
308 :
309 : unsigned int i, packet_len;
310 : int scale_diff, bytes;
311 :
312 64298 : if (numeric->precision < 1 || numeric->precision > MAXPRECISION || numeric->scale > numeric->precision)
313 : return TDS_CONVERT_FAIL;
314 :
315 64298 : if (new_prec < 1 || new_prec > MAXPRECISION || new_scale > new_prec)
316 : return TDS_CONVERT_FAIL;
317 :
318 64298 : scale_diff = new_scale - numeric->scale;
319 64298 : if (scale_diff == 0 && new_prec >= numeric->precision) {
320 23886 : i = tds_numeric_bytes_per_prec[new_prec] - tds_numeric_bytes_per_prec[numeric->precision];
321 23886 : if (i > 0) {
322 9824 : memmove(numeric->array + 1 + i, numeric->array + 1, sizeof(numeric->array) - 1 - i);
323 9824 : memset(numeric->array + 1, 0, i);
324 : }
325 23886 : numeric->precision = new_prec;
326 23886 : return sizeof(TDS_NUMERIC);
327 : }
328 :
329 : /* package number */
330 40412 : bytes = tds_numeric_bytes_per_prec[numeric->precision] - 1;
331 40412 : i = 0;
332 : do {
333 : /*
334 : * note that if bytes are smaller we have a small buffer
335 : * overflow in numeric->array however is not a problem
336 : * cause overflow occurs in numeric and number is fixed below
337 : */
338 117994 : packet[i] = TDS_GET_UA4BE(&numeric->array[bytes-3]);
339 117994 : ++i;
340 117994 : } while ( (bytes -= sizeof(TDS_WORD)) > 0);
341 : /* fix last packet */
342 40412 : if (bytes < 0)
343 39704 : packet[i-1] &= 0xffffffffu >> (8 * -bytes);
344 104394 : while (i > 1 && packet[i-1] == 0)
345 : --i;
346 40412 : packet_len = i;
347 :
348 40412 : if (scale_diff >= 0) {
349 : /* check overflow before multiply */
350 34734 : if (tds_packet_check_overflow(packet, packet_len, new_prec - scale_diff))
351 : return TDS_CONVERT_OVERFLOW;
352 :
353 18070 : if (scale_diff == 0) {
354 12274 : i = tds_numeric_bytes_per_prec[numeric->precision] - tds_numeric_bytes_per_prec[new_prec];
355 12274 : if (i > 0)
356 12274 : memmove(numeric->array + 1, numeric->array + 1 + i, sizeof(numeric->array) - 1 - i);
357 12274 : numeric->precision = new_prec;
358 12274 : return sizeof(TDS_NUMERIC);
359 : }
360 :
361 : /* multiply */
362 : do {
363 : /* multiply by at maximun TDS_WORD_DDIGIT */
364 5812 : unsigned int n = scale_diff > TDS_WORD_DDIGIT ? TDS_WORD_DDIGIT : scale_diff;
365 5812 : TDS_WORD factor = factors[n];
366 5812 : TDS_WORD carry = 0;
367 5812 : scale_diff -= n;
368 12240 : for (i = 0; i < packet_len; ++i) {
369 6428 : TDS_DWORD n = packet[i] * ((TDS_DWORD) factor) + carry;
370 6428 : packet[i] = (TDS_WORD) n;
371 6428 : carry = n >> TDS_WORD_BITS;
372 : }
373 : /* here we can expand number safely cause we know that it can't overflow */
374 5812 : if (carry)
375 680 : packet[packet_len++] = carry;
376 5812 : } while (scale_diff > 0);
377 : } else {
378 : /* check overflow */
379 5678 : if (new_prec - scale_diff < numeric->precision)
380 320 : if (tds_packet_check_overflow(packet, packet_len, new_prec - scale_diff))
381 : return TDS_CONVERT_OVERFLOW;
382 :
383 : /* divide */
384 5478 : scale_diff = -scale_diff;
385 : do {
386 5558 : unsigned int n = scale_diff > TDS_WORD_DDIGIT ? TDS_WORD_DDIGIT : scale_diff;
387 5558 : TDS_WORD factor = factors[n];
388 5558 : TDS_WORD borrow = 0;
389 : #if defined(USE_128_MULTIPLY)
390 5558 : TDS_DWORD reverse_divider = reverse_dividers[n];
391 5558 : uint8_t shift = reverse_dividers_shift[n];
392 : #elif defined(USE_64_MULTIPLY)
393 : TDS_WORD reverse_divider_low = (TDS_WORD) reverse_dividers[n];
394 : TDS_WORD reverse_divider_high = (TDS_WORD) (reverse_dividers[n] >> TDS_WORD_BITS);
395 : uint8_t shift = reverse_dividers_shift[n];
396 : #endif
397 5558 : scale_diff -= n;
398 18066 : for (i = packet_len; i > 0; ) {
399 : #ifdef USE_I386_DIVIDE
400 : --i;
401 : /* For different reasons this code is still here.
402 : * But mainly because although compilers do wonderful things this is hard to get.
403 : * One of the reason is that it's hard to understand that the double-precision division
404 : * result will fit into 32-bit.
405 : */
406 : __asm__ ("divl %4": "=a"(packet[i]), "=d"(borrow): "0"(packet[i]), "1"(borrow), "r"(factor));
407 : #else
408 6950 : TDS_DWORD n = (((TDS_DWORD) borrow) << TDS_WORD_BITS) + packet[--i];
409 : #if defined(USE_128_MULTIPLY)
410 6950 : TDS_DWORD quotient = __umulh(n, reverse_divider);
411 : #else
412 : TDS_DWORD mul1 = (TDS_DWORD) packet[i] * reverse_divider_low;
413 : TDS_DWORD mul2 = (TDS_DWORD) borrow * reverse_divider_low + (mul1 >> TDS_WORD_BITS);
414 : TDS_DWORD mul3 = (TDS_DWORD) packet[i] * reverse_divider_high;
415 : TDS_DWORD quotient = (TDS_DWORD) borrow * reverse_divider_high + (mul3 >> TDS_WORD_BITS);
416 : quotient += (mul2 + (mul3 & 0xffffffffu)) >> TDS_WORD_BITS;
417 : #endif
418 6950 : quotient >>= shift;
419 6950 : packet[i] = (TDS_WORD) quotient;
420 6950 : borrow = (TDS_WORD) (n - quotient * factor);
421 : #endif
422 : }
423 5558 : } while (scale_diff > 0);
424 : }
425 :
426 : /* back to our format */
427 11274 : numeric->precision = new_prec;
428 11274 : numeric->scale = new_scale;
429 11274 : bytes = tds_numeric_bytes_per_prec[numeric->precision] - 1;
430 29320 : for (i = bytes / sizeof(TDS_WORD); i >= packet_len; --i)
431 18046 : packet[i] = 0;
432 20558 : for (i = 0; bytes >= (int) sizeof(TDS_WORD); bytes -= sizeof(TDS_WORD), ++i) {
433 20558 : TDS_PUT_UA4BE(&numeric->array[bytes-3], packet[i]);
434 : }
435 :
436 11274 : if (bytes) {
437 10746 : TDS_WORD remainder = packet[i];
438 : do {
439 11026 : numeric->array[bytes] = (TDS_UCHAR) remainder;
440 11026 : remainder >>= 8;
441 11026 : } while (--bytes);
442 : }
443 :
444 : return sizeof(TDS_NUMERIC);
445 : }
446 :
|