瀏覽代碼

HPCC-10882 Allow cast real to string<n> if string preserves whole value

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 11 年之前
父節點
當前提交
284f5f3dd7
共有 3 個文件被更改,包括 240 次插入6 次删除
  1. 74 6
      rtl/eclrtl/eclrtl.cpp
  2. 61 0
      testing/regress/ecl/issue10882.ecl
  3. 105 0
      testing/regress/ecl/key/issue10882.xml

+ 74 - 6
rtl/eclrtl/eclrtl.cpp

@@ -799,12 +799,19 @@ double rtlUnicodeToReal(size32_t l, UChar const * t)
 
 //---------------------------------------------------------------------------
 
-void rtlRealToStr(size32_t l, char * t, double val)
+static void truncFixedReal(size32_t l, char * t, StringBuffer & temp)
 {
-    StringBuffer temp;
-    temp.append(val);
+    const char * str = temp.str();
     unsigned len = temp.length();
     if (len > l)
+    {
+        //If we don't lose significant digits left of the decimal point then truncate the string.
+        const char * dot = strchr(str, '.');
+        if (dot && ((size_t)(dot - str) <= l))
+            len = l;
+    }
+
+    if (len > l)
         memset(t,'*',l);
     else
     {
@@ -813,12 +820,53 @@ void rtlRealToStr(size32_t l, char * t, double val)
     }
 }
 
-void rtlRealToStr(size32_t l, char * t, float val)
+static void roundFixedReal(size32_t l, char * t, StringBuffer & temp)
 {
-    StringBuffer temp;
-    temp.append(val);
+    const char * str = temp.str();
     unsigned len = temp.length();
     if (len > l)
+    {
+        //If we don't lose significant digits left of the decimal point then truncate the string.
+        const char * dot = strchr(str, '.');
+        if (dot && ((size_t)(dot - str) <= l))
+        {
+            len = l;
+            //Unfortunately we now need to potentially round the number which could even lead to
+            //an extra digit, and failure to fit.  Is there a simpler way of handling this?
+            bool decimalIsNext = ((dot - str) == l);
+            char next = decimalIsNext ? dot[1] : str[len];
+            bool rounding = (next >= '5');
+            unsigned cur = len;
+            while ((cur > 0) && rounding)
+            {
+                next = str[cur-1];
+                if (next == '-')
+                    break;
+                if (next != '.')
+                {
+                    if (next != '9')
+                    {
+                        temp.setCharAt(cur-1, next+1);
+                        rounding = false;
+                        break;
+                    }
+                    else
+                        temp.setCharAt(cur-1, '0');
+                }
+                cur--;
+            }
+            if (rounding)
+            {
+                //Ugly, but it is an exceptional case.
+                if (!decimalIsNext)
+                    temp.insert(cur, '1');
+                else
+                    len++; // overflow
+            }
+        }
+    }
+
+    if (len > l)
         memset(t,'*',l);
     else
     {
@@ -827,6 +875,26 @@ void rtlRealToStr(size32_t l, char * t, float val)
     }
 }
 
+void rtlRealToStr(size32_t l, char * t, double val)
+{
+    StringBuffer temp;
+    temp.append(val);
+
+    //This could either truncate or round when converting a real to a string
+    //Rounding is more user friendly, but then (string3)(string)1.99 != (string3)1.99 which is
+    //rather count intuitive.  (That is still true if the value is out of range.)
+    truncFixedReal(l, t, temp);
+}
+
+void rtlRealToStr(size32_t l, char * t, float val)
+{
+    StringBuffer temp;
+    temp.append(val);
+
+    //See comment above
+    truncFixedReal(l, t, temp);
+}
+
 void rtlRealToStrX(size32_t & l, char * & t, double val)
 {
     StringBuffer temp;

+ 61 - 0
testing/regress/ecl/issue10882.ecl

@@ -0,0 +1,61 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2014 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.
+############################################################################## */
+
+
+value := 12345.678901234;
+
+output(value);
+output((string)value);
+output((string4)value);
+output((string4)nofold(value));
+output((string5)value);
+output((string5)nofold(value));
+output((string6)value);
+output((string6)nofold(value));
+output((string7)value);
+output((string7)nofold(value));
+output((string8)value);
+output((string8)nofold(value));
+output((string20)value);
+output((string20)nofold(value));
+
+value2 := 0.01456;
+
+output((string1)value2);
+output((string2)value2);
+output((string3)value2);
+output((string4)value2);
+output((string5)value2);
+output((string6)value2);
+output((string7)value2);
+
+output((string5)1.9994);
+output((string5)1.9995);
+output((string5)9.9995);
+output((string5)9.99951);
+
+output((string5)-1.994);
+output((string5)-1.995);
+output((string5)-9.995);
+output((string5)-9.995001);
+
+output((string5)-199.4);
+output((string5)-199.6);
+output((string5)-1999.4);
+output((string5)-1999.6);
+output((string5)-9999.4);
+output((string5)-9999.6);

+ 105 - 0
testing/regress/ecl/key/issue10882.xml

@@ -0,0 +1,105 @@
+<Dataset name='Result 1'>
+ <Row><Result_1>12345.678901234</Result_1></Row>
+</Dataset>
+<Dataset name='Result 2'>
+ <Row><Result_2>12345.678901234</Result_2></Row>
+</Dataset>
+<Dataset name='Result 3'>
+ <Row><Result_3>****</Result_3></Row>
+</Dataset>
+<Dataset name='Result 4'>
+ <Row><Result_4>****</Result_4></Row>
+</Dataset>
+<Dataset name='Result 5'>
+ <Row><Result_5>12345</Result_5></Row>
+</Dataset>
+<Dataset name='Result 6'>
+ <Row><Result_6>12345</Result_6></Row>
+</Dataset>
+<Dataset name='Result 7'>
+ <Row><Result_7>12345.</Result_7></Row>
+</Dataset>
+<Dataset name='Result 8'>
+ <Row><Result_8>12345.</Result_8></Row>
+</Dataset>
+<Dataset name='Result 9'>
+ <Row><Result_9>12345.6</Result_9></Row>
+</Dataset>
+<Dataset name='Result 10'>
+ <Row><Result_10>12345.6</Result_10></Row>
+</Dataset>
+<Dataset name='Result 11'>
+ <Row><Result_11>12345.67</Result_11></Row>
+</Dataset>
+<Dataset name='Result 12'>
+ <Row><Result_12>12345.67</Result_12></Row>
+</Dataset>
+<Dataset name='Result 13'>
+ <Row><Result_13>12345.678901234     </Result_13></Row>
+</Dataset>
+<Dataset name='Result 14'>
+ <Row><Result_14>12345.678901234     </Result_14></Row>
+</Dataset>
+<Dataset name='Result 15'>
+ <Row><Result_15>0</Result_15></Row>
+</Dataset>
+<Dataset name='Result 16'>
+ <Row><Result_16>0.</Result_16></Row>
+</Dataset>
+<Dataset name='Result 17'>
+ <Row><Result_17>0.0</Result_17></Row>
+</Dataset>
+<Dataset name='Result 18'>
+ <Row><Result_18>0.01</Result_18></Row>
+</Dataset>
+<Dataset name='Result 19'>
+ <Row><Result_19>0.014</Result_19></Row>
+</Dataset>
+<Dataset name='Result 20'>
+ <Row><Result_20>0.0145</Result_20></Row>
+</Dataset>
+<Dataset name='Result 21'>
+ <Row><Result_21>0.01456</Result_21></Row>
+</Dataset>
+<Dataset name='Result 22'>
+ <Row><Result_22>1.999</Result_22></Row>
+</Dataset>
+<Dataset name='Result 23'>
+ <Row><Result_23>1.999</Result_23></Row>
+</Dataset>
+<Dataset name='Result 24'>
+ <Row><Result_24>9.999</Result_24></Row>
+</Dataset>
+<Dataset name='Result 25'>
+ <Row><Result_25>9.999</Result_25></Row>
+</Dataset>
+<Dataset name='Result 26'>
+ <Row><Result_26>-1.99</Result_26></Row>
+</Dataset>
+<Dataset name='Result 27'>
+ <Row><Result_27>-1.99</Result_27></Row>
+</Dataset>
+<Dataset name='Result 28'>
+ <Row><Result_28>-9.99</Result_28></Row>
+</Dataset>
+<Dataset name='Result 29'>
+ <Row><Result_29>-9.99</Result_29></Row>
+</Dataset>
+<Dataset name='Result 30'>
+ <Row><Result_30>-199.</Result_30></Row>
+</Dataset>
+<Dataset name='Result 31'>
+ <Row><Result_31>-199.</Result_31></Row>
+</Dataset>
+<Dataset name='Result 32'>
+ <Row><Result_32>-1999</Result_32></Row>
+</Dataset>
+<Dataset name='Result 33'>
+ <Row><Result_33>-1999</Result_33></Row>
+</Dataset>
+<Dataset name='Result 34'>
+ <Row><Result_34>-9999</Result_34></Row>
+</Dataset>
+<Dataset name='Result 35'>
+ <Row><Result_35>-9999</Result_35></Row>
+</Dataset>