LCOV - code coverage report
Current view: top level - sql/server - sql_decimal.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 71 74 95.9 %
Date: 2021-10-13 02:24:04 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : 
      11             : #include "sql_decimal.h"
      12             : 
      13             : 
      14             : DEC_TPE
      15        9025 : decimal_from_str(char *dec, int* digits, int* scale, int* has_errors)
      16             : {
      17             : 
      18             : #ifdef HAVE_HGE
      19             :     const hge max0 = GDK_hge_max / 10, max1 = GDK_hge_max % 10;
      20             : #else
      21             :     const lng max0 = GDK_lng_max / 10, max1 = GDK_lng_max % 10;
      22             : #endif
      23             : 
      24        9025 :         assert(digits);
      25        9025 :         assert(scale);
      26        9025 :         assert(has_errors);
      27             : 
      28             :         DEC_TPE res = 0;
      29        9025 :         *has_errors = 0;
      30             : 
      31             :         int _digits     = 0;
      32             :         int _scale      = 0;
      33             : 
      34             : // preceding whitespace:
      35             :         int neg = 0;
      36        9067 :         while(isspace((unsigned char) *dec))
      37          42 :                 dec++;
      38             : 
      39             : // optional sign:
      40        9025 :         if (*dec == '-') {
      41             :                 neg = 1;
      42         175 :                 dec++;
      43        8850 :         } else if (*dec == '+') {
      44           8 :                 dec++;
      45             :         }
      46             : 
      47             : // optional fractional separator first opportunity
      48        9025 :         if (*dec == '.') {  // case: (+|-).456
      49          46 : fractional_sep_first_opp:
      50        3411 :                 dec++;
      51        3411 :                 goto trailing_digits;
      52             :         }
      53             : 
      54             : // preceding_digits:
      55        8979 :         if (!isdigit((unsigned char) *dec)) {
      56          66 :                 *has_errors = 1;
      57          66 :                 goto end_state;
      58             :         }
      59        8950 :         while (*dec == '0'){
      60             :                 // skip leading zeros in preceding digits, e.g. '0004563.1234' => '4563.1234'
      61        3402 :                 dec++;
      62        3402 :                 if (*dec == '.') {
      63             :                         _digits = 1; // case: 0.xyz the zero. the single preceding zero counts for one digit by convention.
      64        3365 :                         goto fractional_sep_first_opp;
      65             :                 }
      66             :         }
      67       24007 :         for (; *dec && (isdigit((unsigned char) *dec)); dec++) {
      68       18459 :                 if (res > max0 || (res == max0 && *dec - '0' > max1)) {
      69           0 :                         *has_errors = 1;
      70           0 :                         return 0;
      71             :                 }
      72       18459 :                 res *= 10;
      73       18459 :                 res += *dec - '0';
      74       18459 :                 _digits++;
      75             :         }
      76             : 
      77             : // optional fractional separator second opportunity
      78        5548 :         if (*dec == '.')        // case: (+|-)123.(456)
      79        5429 :                 dec++;
      80             :         else                                    // case:  (+|-)123
      81         119 :                 goto trailing_whitespace;
      82             : 
      83        8840 : trailing_digits:
      84        8840 :         if (!isdigit((unsigned char) *dec))
      85          11 :                 goto trailing_whitespace;
      86       39650 :         for (; *dec && (isdigit((unsigned char) *dec)); dec++) {
      87       30973 :                 if (res > max0 || (res == max0 && *dec - '0' > max1)) {
      88         152 :                         *has_errors = 1;
      89         152 :                         return 0;
      90             :                 }
      91       30821 :                 res *= 10;
      92       30821 :                 res += *dec - '0';
      93       30821 :                 _scale++;
      94             :         }
      95        8677 :         _digits += _scale;
      96             : 
      97        8807 : trailing_whitespace:
      98        8821 :         while(isspace((unsigned char) *dec))
      99          14 :                 dec++;
     100             : 
     101        8807 : end_state:
     102             :         /* When the string cannot be parsed up to and including the null terminator,
     103             :          * the string is an invalid decimal representation. */
     104        8873 :         if (*dec != 0)
     105          73 :                 *has_errors = 1;
     106             : 
     107        8873 :         *digits = _digits;
     108        8873 :         *scale = _scale;
     109             : 
     110        8873 :         if (neg)
     111         175 :                 return -res;
     112             :         else
     113             :                 return res;
     114             : }
     115             : 
     116             : char *
     117             : #ifdef HAVE_HGE
     118        5220 : decimal_to_str(sql_allocator *sa, hge v, sql_subtype *t)
     119             : #else
     120             : decimal_to_str(sql_allocator *sa, lng v, sql_subtype *t)
     121             : #endif
     122             : {
     123             :         char buf[64];
     124        5220 :         unsigned int scale = t->scale, i;
     125             :         int cur = 63, neg = (v<0), done = 0;
     126             : 
     127             :         if (v<0) v = -v;
     128             : 
     129        5220 :         buf[cur--] = 0;
     130        5220 :         if (scale){
     131       15028 :                 for (i=0; i<scale; i++) {
     132       10934 :                         buf[cur--] = (char) (v%10 + '0');
     133       10934 :                         v /= 10;
     134             :                 }
     135        4094 :                 buf[cur--] = '.';
     136             :         }
     137       19857 :         while (v) {
     138       14637 :                 buf[cur--] = (char ) (v%10 + '0');
     139       14637 :                 v /= 10;
     140             :                 done = 1;
     141             :         }
     142        5220 :         if (!done)
     143         876 :                 buf[cur--] = '0';
     144        5220 :         if (neg)
     145           0 :                 buf[cur--] = '-';
     146        5220 :         assert(cur >= -1);
     147        5220 :         return sa_strdup(sa, buf+cur+1);
     148             : }
     149             : 
     150             : #ifdef HAVE_HGE
     151             : extern hge
     152             : #else
     153             : extern lng
     154             : #endif
     155          25 : scale2value(int scale)
     156             : {
     157             : #ifdef HAVE_HGE
     158             :         hge val = 1;
     159             : #else
     160             :         lng val = 1;
     161             : #endif
     162             : 
     163             :         if (scale < 0)
     164             :                 scale = -scale;
     165          85 :         for (; scale; scale--) {
     166          60 :                 val = val * 10;
     167             :         }
     168          25 :         return val;
     169             : }

Generated by: LCOV version 1.14