Просмотр исходного кода

HPCC-13623 Fix various bugs in REALFORMAT boundary cases

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 10 лет назад
Родитель
Сommit
00d3cc1982
3 измененных файлов с 455 добавлено и 10 удалено
  1. 25 10
      rtl/eclrtl/eclrtl.cpp
  2. 378 0
      testing/regress/ecl/key/realformat.xml
  3. 52 0
      testing/regress/ecl/realformat.ecl

+ 25 - 10
rtl/eclrtl/eclrtl.cpp

@@ -1226,18 +1226,28 @@ void holeIntFormat(size32_t maxlen, char * target, __int64 value, unsigned width
 
 void holeRealFormat(size32_t maxlen, char * target, double value, unsigned width, unsigned places)
 {
-    if ((int) width < 0)
+    if ((int) width <= 0)
         return;
-    char temp[500];
-    if (width > sizeof(temp)) 
+
+    const unsigned tempSize = 500;
+    char temp[tempSize*2+2];  // Space for leading digits/0, '-' and \0 terminator
+
+    //Ensure that we output at most 2*tempSize characters.
+    unsigned formatWidth = width < tempSize ? width : tempSize;
+    if (places >= formatWidth)
+        places = formatWidth-1;
+    unsigned written = sprintf(temp, "%*.*f", formatWidth, places, value);
+
+    const char * src = temp;
+    if (written > width)
     {
-        unsigned delta = width - sizeof(temp);
-        memset(target, ' ', delta);
-        target += delta;
-        width = sizeof(temp);
+        //Strip a leading 0 for very small numbers.
+        if (*src == '0')
+        {
+            written--;
+            src++;
+        }
     }
-    if (places >= width)             places = width-1;
-    unsigned written = sprintf(temp, "%*.*f", width, places, value);
     if (written > width)
     {
         memset(target, '*', width);
@@ -1245,7 +1255,12 @@ void holeRealFormat(size32_t maxlen, char * target, double value, unsigned width
             target[width-places-1] = '.';
     }
     else
-        memcpy(target, temp, width);
+    {
+        unsigned delta = width - written;
+        if (delta)
+            memset(target, ' ', delta);
+        memcpy(target+delta, src, written);
+    }
 }
 
 //=============================================================================

+ 378 - 0
testing/regress/ecl/key/realformat.xml

@@ -0,0 +1,378 @@
+<Dataset name='Result 1'>
+ <Row><Result_1></Result_1></Row>
+</Dataset>
+<Dataset name='Result 2'>
+ <Row><Result_2></Result_2></Row>
+</Dataset>
+<Dataset name='Result 3'>
+ <Row><Result_3>0</Result_3></Row>
+</Dataset>
+<Dataset name='Result 4'>
+ <Row><Result_4>0</Result_4></Row>
+</Dataset>
+<Dataset name='Result 5'>
+ <Row><Result_5>.0</Result_5></Row>
+</Dataset>
+<Dataset name='Result 6'>
+ <Row><Result_6>0.0</Result_6></Row>
+</Dataset>
+<Dataset name='Result 7'>
+ <Row><Result_7>.00</Result_7></Row>
+</Dataset>
+<Dataset name='Result 8'>
+ <Row><Result_8>  0.0</Result_8></Row>
+</Dataset>
+<Dataset name='Result 9'>
+ <Row><Result_9>true</Result_9></Row>
+</Dataset>
+<Dataset name='Result 10'>
+ <Row><Result_10>true</Result_10></Row>
+</Dataset>
+<Dataset name='Result 11'>
+ <Row><Result_11>true</Result_11></Row>
+</Dataset>
+<Dataset name='Result 12'>
+ <Row><Result_12>true</Result_12></Row>
+</Dataset>
+<Dataset name='Result 13'>
+ <Row><Result_13>true</Result_13></Row>
+</Dataset>
+<Dataset name='Result 14'>
+ <Row><Result_14>true</Result_14></Row>
+</Dataset>
+<Dataset name='Result 15'>
+ <Row><Result_15></Result_15></Row>
+</Dataset>
+<Dataset name='Result 16'>
+ <Row><Result_16></Result_16></Row>
+</Dataset>
+<Dataset name='Result 17'>
+ <Row><Result_17>0</Result_17></Row>
+</Dataset>
+<Dataset name='Result 18'>
+ <Row><Result_18>0</Result_18></Row>
+</Dataset>
+<Dataset name='Result 19'>
+ <Row><Result_19>.1</Result_19></Row>
+</Dataset>
+<Dataset name='Result 20'>
+ <Row><Result_20>0.1</Result_20></Row>
+</Dataset>
+<Dataset name='Result 21'>
+ <Row><Result_21>.10</Result_21></Row>
+</Dataset>
+<Dataset name='Result 22'>
+ <Row><Result_22>  0.1</Result_22></Row>
+</Dataset>
+<Dataset name='Result 23'>
+ <Row><Result_23>true</Result_23></Row>
+</Dataset>
+<Dataset name='Result 24'>
+ <Row><Result_24>true</Result_24></Row>
+</Dataset>
+<Dataset name='Result 25'>
+ <Row><Result_25>true</Result_25></Row>
+</Dataset>
+<Dataset name='Result 26'>
+ <Row><Result_26>true</Result_26></Row>
+</Dataset>
+<Dataset name='Result 27'>
+ <Row><Result_27>true</Result_27></Row>
+</Dataset>
+<Dataset name='Result 28'>
+ <Row><Result_28>true</Result_28></Row>
+</Dataset>
+<Dataset name='Result 29'>
+ <Row><Result_29></Result_29></Row>
+</Dataset>
+<Dataset name='Result 30'>
+ <Row><Result_30></Result_30></Row>
+</Dataset>
+<Dataset name='Result 31'>
+ <Row><Result_31>*</Result_31></Row>
+</Dataset>
+<Dataset name='Result 32'>
+ <Row><Result_32>*</Result_32></Row>
+</Dataset>
+<Dataset name='Result 33'>
+ <Row><Result_33>.*</Result_33></Row>
+</Dataset>
+<Dataset name='Result 34'>
+ <Row><Result_34>*.*</Result_34></Row>
+</Dataset>
+<Dataset name='Result 35'>
+ <Row><Result_35>.**</Result_35></Row>
+</Dataset>
+<Dataset name='Result 36'>
+ <Row><Result_36> -0.1</Result_36></Row>
+</Dataset>
+<Dataset name='Result 37'>
+ <Row><Result_37>true</Result_37></Row>
+</Dataset>
+<Dataset name='Result 38'>
+ <Row><Result_38>true</Result_38></Row>
+</Dataset>
+<Dataset name='Result 39'>
+ <Row><Result_39>true</Result_39></Row>
+</Dataset>
+<Dataset name='Result 40'>
+ <Row><Result_40>true</Result_40></Row>
+</Dataset>
+<Dataset name='Result 41'>
+ <Row><Result_41>true</Result_41></Row>
+</Dataset>
+<Dataset name='Result 42'>
+ <Row><Result_42>true</Result_42></Row>
+</Dataset>
+<Dataset name='Result 43'>
+ <Row><Result_43></Result_43></Row>
+</Dataset>
+<Dataset name='Result 44'>
+ <Row><Result_44></Result_44></Row>
+</Dataset>
+<Dataset name='Result 45'>
+ <Row><Result_45>2</Result_45></Row>
+</Dataset>
+<Dataset name='Result 46'>
+ <Row><Result_46>2</Result_46></Row>
+</Dataset>
+<Dataset name='Result 47'>
+ <Row><Result_47>.*</Result_47></Row>
+</Dataset>
+<Dataset name='Result 48'>
+ <Row><Result_48>2.1</Result_48></Row>
+</Dataset>
+<Dataset name='Result 49'>
+ <Row><Result_49>.**</Result_49></Row>
+</Dataset>
+<Dataset name='Result 50'>
+ <Row><Result_50>  2.1</Result_50></Row>
+</Dataset>
+<Dataset name='Result 51'>
+ <Row><Result_51>true</Result_51></Row>
+</Dataset>
+<Dataset name='Result 52'>
+ <Row><Result_52>true</Result_52></Row>
+</Dataset>
+<Dataset name='Result 53'>
+ <Row><Result_53>true</Result_53></Row>
+</Dataset>
+<Dataset name='Result 54'>
+ <Row><Result_54>true</Result_54></Row>
+</Dataset>
+<Dataset name='Result 55'>
+ <Row><Result_55>true</Result_55></Row>
+</Dataset>
+<Dataset name='Result 56'>
+ <Row><Result_56>true</Result_56></Row>
+</Dataset>
+<Dataset name='Result 57'>
+ <Row><Result_57></Result_57></Row>
+</Dataset>
+<Dataset name='Result 58'>
+ <Row><Result_58></Result_58></Row>
+</Dataset>
+<Dataset name='Result 59'>
+ <Row><Result_59>*</Result_59></Row>
+</Dataset>
+<Dataset name='Result 60'>
+ <Row><Result_60>*</Result_60></Row>
+</Dataset>
+<Dataset name='Result 61'>
+ <Row><Result_61>.*</Result_61></Row>
+</Dataset>
+<Dataset name='Result 62'>
+ <Row><Result_62>*.*</Result_62></Row>
+</Dataset>
+<Dataset name='Result 63'>
+ <Row><Result_63>.**</Result_63></Row>
+</Dataset>
+<Dataset name='Result 64'>
+ <Row><Result_64> -2.1</Result_64></Row>
+</Dataset>
+<Dataset name='Result 65'>
+ <Row><Result_65>true</Result_65></Row>
+</Dataset>
+<Dataset name='Result 66'>
+ <Row><Result_66>true</Result_66></Row>
+</Dataset>
+<Dataset name='Result 67'>
+ <Row><Result_67>true</Result_67></Row>
+</Dataset>
+<Dataset name='Result 68'>
+ <Row><Result_68>true</Result_68></Row>
+</Dataset>
+<Dataset name='Result 69'>
+ <Row><Result_69>true</Result_69></Row>
+</Dataset>
+<Dataset name='Result 70'>
+ <Row><Result_70>true</Result_70></Row>
+</Dataset>
+<Dataset name='Result 71'>
+ <Row><Result_71></Result_71></Row>
+</Dataset>
+<Dataset name='Result 72'>
+ <Row><Result_72></Result_72></Row>
+</Dataset>
+<Dataset name='Result 73'>
+ <Row><Result_73>*</Result_73></Row>
+</Dataset>
+<Dataset name='Result 74'>
+ <Row><Result_74>*</Result_74></Row>
+</Dataset>
+<Dataset name='Result 75'>
+ <Row><Result_75>.*</Result_75></Row>
+</Dataset>
+<Dataset name='Result 76'>
+ <Row><Result_76>*.*</Result_76></Row>
+</Dataset>
+<Dataset name='Result 77'>
+ <Row><Result_77>.**</Result_77></Row>
+</Dataset>
+<Dataset name='Result 78'>
+ <Row><Result_78> 23.1</Result_78></Row>
+</Dataset>
+<Dataset name='Result 79'>
+ <Row><Result_79>true</Result_79></Row>
+</Dataset>
+<Dataset name='Result 80'>
+ <Row><Result_80>true</Result_80></Row>
+</Dataset>
+<Dataset name='Result 81'>
+ <Row><Result_81>true</Result_81></Row>
+</Dataset>
+<Dataset name='Result 82'>
+ <Row><Result_82>true</Result_82></Row>
+</Dataset>
+<Dataset name='Result 83'>
+ <Row><Result_83>true</Result_83></Row>
+</Dataset>
+<Dataset name='Result 84'>
+ <Row><Result_84>true</Result_84></Row>
+</Dataset>
+<Dataset name='Result 85'>
+ <Row><Result_85></Result_85></Row>
+</Dataset>
+<Dataset name='Result 86'>
+ <Row><Result_86></Result_86></Row>
+</Dataset>
+<Dataset name='Result 87'>
+ <Row><Result_87>*</Result_87></Row>
+</Dataset>
+<Dataset name='Result 88'>
+ <Row><Result_88>*</Result_88></Row>
+</Dataset>
+<Dataset name='Result 89'>
+ <Row><Result_89>.*</Result_89></Row>
+</Dataset>
+<Dataset name='Result 90'>
+ <Row><Result_90>*.*</Result_90></Row>
+</Dataset>
+<Dataset name='Result 91'>
+ <Row><Result_91>.**</Result_91></Row>
+</Dataset>
+<Dataset name='Result 92'>
+ <Row><Result_92>-23.1</Result_92></Row>
+</Dataset>
+<Dataset name='Result 93'>
+ <Row><Result_93>true</Result_93></Row>
+</Dataset>
+<Dataset name='Result 94'>
+ <Row><Result_94>true</Result_94></Row>
+</Dataset>
+<Dataset name='Result 95'>
+ <Row><Result_95>true</Result_95></Row>
+</Dataset>
+<Dataset name='Result 96'>
+ <Row><Result_96>true</Result_96></Row>
+</Dataset>
+<Dataset name='Result 97'>
+ <Row><Result_97>true</Result_97></Row>
+</Dataset>
+<Dataset name='Result 98'>
+ <Row><Result_98>true</Result_98></Row>
+</Dataset>
+<Dataset name='Result 99'>
+ <Row><Result_99></Result_99></Row>
+</Dataset>
+<Dataset name='Result 100'>
+ <Row><Result_100></Result_100></Row>
+</Dataset>
+<Dataset name='Result 101'>
+ <Row><Result_101>*</Result_101></Row>
+</Dataset>
+<Dataset name='Result 102'>
+ <Row><Result_102>*</Result_102></Row>
+</Dataset>
+<Dataset name='Result 103'>
+ <Row><Result_103>.*</Result_103></Row>
+</Dataset>
+<Dataset name='Result 104'>
+ <Row><Result_104>*.*</Result_104></Row>
+</Dataset>
+<Dataset name='Result 105'>
+ <Row><Result_105>.**</Result_105></Row>
+</Dataset>
+<Dataset name='Result 106'>
+ <Row><Result_106>***.*</Result_106></Row>
+</Dataset>
+<Dataset name='Result 107'>
+ <Row><Result_107>true</Result_107></Row>
+</Dataset>
+<Dataset name='Result 108'>
+ <Row><Result_108>true</Result_108></Row>
+</Dataset>
+<Dataset name='Result 109'>
+ <Row><Result_109>true</Result_109></Row>
+</Dataset>
+<Dataset name='Result 110'>
+ <Row><Result_110>true</Result_110></Row>
+</Dataset>
+<Dataset name='Result 111'>
+ <Row><Result_111>true</Result_111></Row>
+</Dataset>
+<Dataset name='Result 112'>
+ <Row><Result_112>true</Result_112></Row>
+</Dataset>
+<Dataset name='Result 113'>
+ <Row><Result_113></Result_113></Row>
+</Dataset>
+<Dataset name='Result 114'>
+ <Row><Result_114></Result_114></Row>
+</Dataset>
+<Dataset name='Result 115'>
+ <Row><Result_115>*</Result_115></Row>
+</Dataset>
+<Dataset name='Result 116'>
+ <Row><Result_116>*</Result_116></Row>
+</Dataset>
+<Dataset name='Result 117'>
+ <Row><Result_117>.*</Result_117></Row>
+</Dataset>
+<Dataset name='Result 118'>
+ <Row><Result_118>*.*</Result_118></Row>
+</Dataset>
+<Dataset name='Result 119'>
+ <Row><Result_119>.**</Result_119></Row>
+</Dataset>
+<Dataset name='Result 120'>
+ <Row><Result_120>***.*</Result_120></Row>
+</Dataset>
+<Dataset name='Result 121'>
+ <Row><Result_121>true</Result_121></Row>
+</Dataset>
+<Dataset name='Result 122'>
+ <Row><Result_122>true</Result_122></Row>
+</Dataset>
+<Dataset name='Result 123'>
+ <Row><Result_123>true</Result_123></Row>
+</Dataset>
+<Dataset name='Result 124'>
+ <Row><Result_124>true</Result_124></Row>
+</Dataset>
+<Dataset name='Result 125'>
+ <Row><Result_125>true</Result_125></Row>
+</Dataset>
+<Dataset name='Result 126'>
+ <Row><Result_126>true</Result_126></Row>
+</Dataset>

+ 52 - 0
testing/regress/ecl/realformat.ecl

@@ -0,0 +1,52 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2015 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+//Windows and linux format floating point numbers with > 15 places differently, so only check the significant digits
+checkSignificant(real value, unsigned width, unsigned places, string expected) := FUNCTION
+    formatted := REALFORMAT(value, width, places);
+    RETURN PARALLEL(
+        OUTPUT(LENGTH(formatted) = width);
+        OUTPUT(TRIM(formatted, LEFT, RIGHT)[1..LENGTH(expected)] = expected);
+    );
+END;
+
+
+doFormat(real value, string expected1, string expected2, string expected3) := PARALLEL(
+    REALFORMAT(value, 0, 0);
+    REALFORMAT(value, 0, 1);
+    REALFORMAT(value, 1, 0);
+    REALFORMAT(value, 1, 1);
+    REALFORMAT(value, 2, 1);
+    REALFORMAT(value, 3, 1);
+    REALFORMAT(value, 3, 4);
+    REALFORMAT(value, 5, 1);
+    checkSignificant(value, 99, 10, expected1);
+    checkSignificant(value, 2000, 10, expected2);
+    checkSignificant(value, 2000, 1000, expected3);
+);
+
+doFormat(0.0,                   '0.0000000000', '0.0000000000',     '0.000000000000000');
+doFormat(0.1,                   '0.1000000000', '0.1000000000',     '0.100000000000000');
+doFormat(-0.1,                  '-0.1000000000', '-0.1000000000',  '-0.100000000000000');
+doFormat(2.1,                   '2.1000000000', '2.1000000000',     '2.10000000000000');
+doFormat(-2.1,                  '-2.1000000000', '-2.1000000000',  '-2.10000000000000');
+doFormat(23.1,                  '23.1000000000', '23.1000000000',  '23.1000000000000');
+doFormat(-23.1,                 '-23.1000000000', '-23.100000000','-23.1000000000000');
+
+// only coompare 14 significant digits since linux outputs exactly at 12345678901234499... and does not round up the 15th digit
+doFormat(1.23456789012345e200,  '**************', '12345678901234', '12345678901234');
+doFormat(-1.23456789012345E200, '**************', '-12345678901234', '-12345678901234');