Commits

Jens Alfke committed bab0ee7

Top-level writer destructor needs to call end().
Made Array methods const.
Added test of deep message nesting.

  • Participants
  • Parent commits 508c77d

Comments (0)

Files changed (7)

File FudgeArray.cpp

 {}
 
 
-int32_t Array::intAt(uint32_t index) {
+int32_t Array::intAt(uint32_t index) const {
     switch (_type) {
         case kByte:
         default:
 }
 
 
-int32_t IntArray::operator[] (uint32_t index) {
+int32_t IntArray::operator[] (uint32_t index) const {
     assert(index < _length);
     return intAt(index);
 }
 
 
-int64_t Int64Array::operator[] (uint32_t index) {
+int64_t Int64Array::operator[] (uint32_t index) const {
     assert(index < _length);
     switch (_type) {
         case kLong:
 }
 
 
-double DoubleArray::operator[] (uint32_t index) {
+double DoubleArray::operator[] (uint32_t index) const {
     assert(index < _length);
     switch (_type) {
         case kLong:

File FudgeArray.h

 class Array {
   public:
     Array(Type type, Data data);
-    Type itemType()                                 {return _type;}
-    uint32_t length()                               {return _length;}
+    Type itemType() const                           {return _type;}
+    uint32_t length() const                         {return _length;}
     
   protected:
-    int32_t intAt(uint32_t index);
+    int32_t intAt(uint32_t index) const;
 
     Type _type;
     const void* _start;
 class IntArray : public Array {
   public:
     IntArray(Type type, Data data)                  :Array(type, data) {}
-    int32_t operator[] (uint32_t index);
+    int32_t operator[] (uint32_t index) const;
 };
 
 class Int64Array : public Array {
   public:
     Int64Array(Type type, Data data)                :Array(type, data) {}
-    int64_t operator[] (uint32_t index);
+    int64_t operator[] (uint32_t index) const;
 };
 
 class DoubleArray : public Array {
   public:
     DoubleArray(Type type, Data data)               :Array(type, data) {}
-    double operator[] (uint32_t index);
+    double operator[] (uint32_t index) const;
 };
 
 }

File FudgeJSON.cpp

 
 #include "FudgeJSON.h"
 #include "FudgeMsg.h"
+#include "FudgeArray.h"
 #include <algorithm>
 #include <sstream>
 
 namespace fudge {
     
     
+static void WriteEscapedString(const std::string& str, std::ostream& out) {
+    out << '"';
+    int start = 0;  // index of next character in str remaining to be written
+    int i;
+    for (i=0; i<str.length(); ++i) {
+        unsigned char c = str[i];
+        if (c < 32 || c == 127 || c == '"' || c == '\\') {
+            if (start < i)
+                out << str.substr(start, i-start);
+            switch (c) {
+                case '"':   out << "\\\""; break;
+                case '\\':  out << "\\\\"; break;
+                default:    out << "\\u" << (unsigned)c; break;     //FIX: needs to be 4 hex digits
+            }
+            start = i + 1;
+            // Note: Do NOT escape bytes >= 128 as they are UTF-8 escape sequences, not single
+            // characters. Escaping them individually would break the string. They're valid in
+            // UTF-8 output, anyway, so they don't really need escaping.
+        }
+    }
+    if (start < i)
+        out << str.substr(start, i-start);
+    out << '"';
+}
+    
+    
+static void WriteJSON(const Int64Array& array, std::ostream& out, 
+               const std::string& indent, bool compact) {
+    out << "[";
+    for (int i=0; i<array.length(); ++i) {
+        if (i > 0)
+            out << ", ";
+        out << array[i];
+    }
+    out << "]";
+}
+
+    
+static void WriteJSON(const DoubleArray& array, std::ostream& out, 
+               const std::string& indent, bool compact) {
+    out << "[";
+    for (int i=0; i<array.length(); ++i) {
+        if (i > 0)
+            out << ", ";
+        out << array[i];
+    }
+    out << "]";
+}
+
+
 void WriteJSON(const Field& field, std::ostream& out, const std::string& indent, bool compact) {
     switch (field.type()) {
         case kIndicator:
-            out << "null";  // ???
+            out << "null";
             break;
         case kMessage:
             WriteJSON(field.asMessage(), out, indent, compact);
             out << field.asDouble();
             break;
         case kString:
-            out << '"' << field.asString() << '"';  //FIX: Escape quotes
+            WriteEscapedString(field.asString(), out);
             break;
         default:
-            out << "???" << (int)field.type() << "???";
+            if (field.isArray()) {
+                switch (field.arrayType()) {
+                    case kFloat:
+                    case kDouble:
+                        WriteJSON(field.asDoubleArray(), out, indent, compact);
+                        break;
+                    default:
+                        WriteJSON(field.asInt64Array(), out, indent, compact);
+                        break;
+                }
+            } else {
+                out << "???" << (int)field.type() << "???";
+            }
             break;
     }
 }
     
+    
 void WriteJSON(const Message& message, std::ostream& out, const std::string& indent, bool compact) {
     bool hasNames = false;
     for (Message::iterator i=message.begin(); i != message.end(); ++i) {
             if (!compact)
                 out << "\n" << indent;
         }
-        if (hasNames)
-            out << "\"" << i->name() << "\":";  //FIX: escape quotes in name
+        if (hasNames) {
+            WriteEscapedString(i->name(), out);
+            out << ":";
+        }
         WriteJSON(*i, out, nestedIndent, compact);
     }
 

File FudgeWriter.cpp

 
 
 Writer::~Writer() {
-    if (_parent)
-        end();
+    end();
 }
     
     

File TestArrays.cpp

 #include "FudgeWriter.h"
 #include "FudgeArray.h"
 #include "FudgeDump.h"
+#include "FudgeJSON.h"
 
 using namespace fudge;
 
     std::string result = out.str();
     
     const Envelope* envelope = Envelope::FromBytes(result.data(), result.size());
-    EXPECT_TRUE(envelope);
+    ASSERT_TRUE(envelope);
+    if (size < 20) {
+        WriteJSON(*envelope, std::cout);
+        std::cout << "\n";
+    }
     Message msg = envelope->message();
     Message::iterator i = msg.begin();
     
     std::string result = out.str();
         
     const Envelope* envelope = Envelope::FromBytes(result.data(), result.size());
-    EXPECT_TRUE(envelope);
-    Dump(*envelope, std::cout, true);
+    ASSERT_TRUE(envelope);
+    WriteJSON(*envelope, std::cout);
+    std::cout << "\n";
     Message msg = envelope->message();
     Message::iterator i = msg.begin();
     
     std::string result = out.str();
         
     const Envelope* envelope = Envelope::FromBytes(result.data(), result.size());
-    EXPECT_TRUE(envelope);
-    Dump(*envelope, std::cout, true);
+    ASSERT_TRUE(envelope);
+    WriteJSON(*envelope, std::cout);
+    std::cout << "\n";
     Message msg = envelope->message();
     Message::iterator i = msg.begin();
     
     std::string result = out.str();
     
     const Envelope* envelope = Envelope::FromBytes(result.data(), result.size());
-    EXPECT_TRUE(envelope);
-    Dump(*envelope, std::cout, true);
+    ASSERT_TRUE(envelope);
+    WriteJSON(*envelope, std::cout);
+    std::cout << "\n";
     Message msg = envelope->message();
     Message::iterator i = msg.begin();
     
     std::string result = out.str();
     
     const Envelope* envelope = Envelope::FromBytes(result.data(), result.size());
-    EXPECT_TRUE(envelope);
-    Dump(*envelope, std::cout, true);
+    ASSERT_TRUE(envelope);
+    WriteJSON(*envelope, std::cout);
+    std::cout << "\n";
     Message msg = envelope->message();
     Message::iterator i = msg.begin();
     

File TestFields.cpp

     Writer writer(out);
     writer.addString("");
     writer.addString("testing 1234");
+    writer.addString("testing 1234");
     writer.end();
     
     std::string result = out.str();

File TestNested.cpp

 #include "FudgeWriter.h"
 #include "FudgeArray.h"
 #include "FudgeDump.h"
+#include "FudgeJSON.h"
 
 using namespace fudge;
 
 }
 
 
+static void WriteSomeNested(Writer &writer, int depth) {
+    writer.addString("At depth ");
+    writer.addInt(depth);
+    Writer nested = writer.beginMessage();
+    if (depth > 0) {
+        WriteSomeNested(nested, depth - 1);
+        WriteSomeNested(nested, depth - 1);
+    }
+    nested.end();
+    writer.addString("!");
+}
+
+
+TEST(FudgeMessage, DeepNested) {
+    std::stringstream out;
+    {
+        Writer writer(out);
+        WriteSomeNested(writer, 4);
+    }
+    
+    std::string result = out.str();
+    const Envelope* envelope = Envelope::FromBytes(result.data(), result.size());
+    ASSERT_TRUE(envelope != NULL);
+    WriteJSON(*envelope, std::cout);
+    std::cout << "\n";
+    WriteJSON(*envelope, std::cout, true);
+    std::cout << "\n";
+}