Explorar el Código

Merge pull request #6282 from afishbeck/jsonRealInfiniteNaN

HPCC-11636 Fix JSON output of INIFINITE and NaN real values

Reviewed-by: Gavin Halliday <ghalliday@hpccsystems.com>
Gavin Halliday hace 11 años
padre
commit
26308bff4e

+ 21 - 3
common/thorhelper/roxiehelper.cpp

@@ -849,6 +849,18 @@ void FlushingStringBuffer::append(const char *data)
     append(strlen(data), data);
     append(strlen(data), data);
 }
 }
 
 
+void FlushingStringBuffer::append(double data)
+{
+    if (isRaw)
+        append(sizeof(data), (char *)&data);
+    else
+    {
+        StringBuffer v;
+        v.append(data);
+        append(v.length(), v.str());
+    }
+}
+
 void FlushingStringBuffer::append(unsigned len, const char *data)
 void FlushingStringBuffer::append(unsigned len, const char *data)
 {
 {
     try
     try
@@ -888,7 +900,9 @@ void FlushingStringBuffer::encodeString(const char *x, unsigned len, bool utf8)
 void FlushingStringBuffer::encodeData(const void *data, unsigned len)
 void FlushingStringBuffer::encodeData(const void *data, unsigned len)
 {
 {
     static char hexchar[] = "0123456789ABCDEF";
     static char hexchar[] = "0123456789ABCDEF";
-    if (mlFmt==MarkupFmt_XML)
+    if (isRaw)
+        append(len, (const char *) data);
+    else
     {
     {
         const byte *field = (const byte *) data;
         const byte *field = (const byte *) data;
         for (int i = 0; i < len; i++)
         for (int i = 0; i < len; i++)
@@ -897,8 +911,6 @@ void FlushingStringBuffer::encodeData(const void *data, unsigned len)
             append(hexchar[field[i] & 0x0f]);
             append(hexchar[field[i] & 0x0f]);
         }
         }
     }
     }
-    else
-        append(len, (const char *) data);
 }
 }
 
 
 void FlushingStringBuffer::addPayload(StringBuffer &s, unsigned int reserve)
 void FlushingStringBuffer::addPayload(StringBuffer &s, unsigned int reserve)
@@ -1117,6 +1129,12 @@ void FlushingStringBuffer::incrementRowCount()
     rowCount++;
     rowCount++;
 }
 }
 
 
+void FlushingJsonBuffer::append(double data)
+{
+    CriticalBlock b(crit);
+    appendJSONRealValue(s, NULL, data);
+}
+
 void FlushingJsonBuffer::encodeString(const char *x, unsigned len, bool utf8)
 void FlushingJsonBuffer::encodeString(const char *x, unsigned len, bool utf8)
 {
 {
     CriticalBlock b(crit);
     CriticalBlock b(crit);

+ 2 - 0
common/thorhelper/roxiehelper.hpp

@@ -154,6 +154,7 @@ public:
     virtual void append(char data) {append(1, &data);}
     virtual void append(char data) {append(1, &data);}
     virtual void append(const char *data);
     virtual void append(const char *data);
     virtual void append(unsigned len, const char *data);
     virtual void append(unsigned len, const char *data);
+    virtual void append(double data);
     virtual void appendf(const char *format, ...) __attribute__((format(printf, 2, 3)));
     virtual void appendf(const char *format, ...) __attribute__((format(printf, 2, 3)));
     virtual void encodeString(const char *x, unsigned len, bool utf8=false);
     virtual void encodeString(const char *x, unsigned len, bool utf8=false);
     virtual void encodeData(const void *data, unsigned len);
     virtual void encodeData(const void *data, unsigned len);
@@ -174,6 +175,7 @@ public:
     {
     {
     }
     }
 
 
+    void append(double data);
     void encodeString(const char *x, unsigned len, bool utf8=false);
     void encodeString(const char *x, unsigned len, bool utf8=false);
     void encodeData(const void *data, unsigned len);
     void encodeData(const void *data, unsigned len);
     void startDataset(const char *elementName, const char *resultName, unsigned sequence, bool _extend = false, const IProperties *xmlns=NULL);
     void startDataset(const char *elementName, const char *resultName, unsigned sequence, bool _extend = false, const IProperties *xmlns=NULL);

+ 1 - 6
roxie/ccd/ccdcontext.cpp

@@ -3375,16 +3375,11 @@ public:
         }
         }
         else
         else
         {
         {
-            StringBuffer v;
-            v.append(value);
             FlushingStringBuffer *r = queryResult(sequence);
             FlushingStringBuffer *r = queryResult(sequence);
             if (r)
             if (r)
             {
             {
                 r->startScalar(name, sequence);
                 r->startScalar(name, sequence);
-                if (r->isRaw)
-                    r->append(sizeof(value), (char *)&value);
-                else
-                    r->appendf("%s", v.str());
+                r->append(value);
             }
             }
         }
         }
         if (workUnit)
         if (workUnit)

+ 1 - 1
roxie/ccd/ccdserver.cpp

@@ -19908,7 +19908,7 @@ public:
                 if (response)
                 if (response)
                 {
                 {
                     if (response->isRaw)
                     if (response->isRaw)
-                        response->append(row == NULL);
+                        response->append((char)(row == NULL));
                     else
                     else
                     {
                     {
                         response->append("<Row __GroupBreak__=\"1\"/>");        // sensible, but need to handle on input
                         response->append("<Row __GroupBreak__=\"1\"/>");        // sensible, but need to handle on input

+ 12 - 0
system/jlib/jstring.cpp

@@ -1963,6 +1963,18 @@ jlib_decl StringBuffer &appendJSONDataValue(StringBuffer& s, const char *name, u
     return s.append('"');
     return s.append('"');
 }
 }
 
 
+StringBuffer &appendJSONRealValue(StringBuffer& s, const char *name, double value)
+{
+    appendJSONNameOrDelimit(s, name);
+    bool quoted = isnan(value) || isinf(value);
+    if (quoted)
+        s.append('"');
+    s.append(value);
+    if (quoted)
+        s.append('"');
+    return s;
+}
+
 inline StringBuffer &encodeJSONChar(StringBuffer &s, const char *&ch)
 inline StringBuffer &encodeJSONChar(StringBuffer &s, const char *&ch)
 {
 {
     switch (*ch)
     switch (*ch)

+ 13 - 0
system/jlib/jstring.hpp

@@ -440,6 +440,7 @@ jlib_decl StringBuffer &encodeJSON(StringBuffer &s, unsigned len, const char *va
 jlib_decl StringBuffer &appendJSONName(StringBuffer &s, const char *name);
 jlib_decl StringBuffer &appendJSONName(StringBuffer &s, const char *name);
 jlib_decl StringBuffer &appendfJSONName(StringBuffer &s, const char *format, ...);
 jlib_decl StringBuffer &appendfJSONName(StringBuffer &s, const char *format, ...);
 jlib_decl StringBuffer &appendJSONDataValue(StringBuffer& s, const char *name, unsigned len, const void *_value);
 jlib_decl StringBuffer &appendJSONDataValue(StringBuffer& s, const char *name, unsigned len, const void *_value);
+jlib_decl StringBuffer &appendJSONRealValue(StringBuffer& s, const char *name, double value);
 
 
 inline StringBuffer &appendJSONNameOrDelimit(StringBuffer &s, const char *name)
 inline StringBuffer &appendJSONNameOrDelimit(StringBuffer &s, const char *name)
 {
 {
@@ -498,6 +499,18 @@ inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, long val
 }
 }
 
 
 template <>
 template <>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, double value)
+{
+    return ::appendJSONRealValue(s, name, value);
+}
+
+template <>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, float value)
+{
+    return ::appendJSONRealValue(s, name,  value);
+}
+
+template <>
 inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, unsigned long value)
 inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, unsigned long value)
 {
 {
     appendJSONNameOrDelimit(s, name);
     appendJSONNameOrDelimit(s, name);