Commits

Jens Alfke committed f284b0b

The Great Renaming.

Comments (0)

Files changed (65)

Fudge.xcodeproj/project.pbxproj

 
 /* Begin PBXBuildFile section */
 		274D1100137736BB009EA268 /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 274D10FF137736BB009EA268 /* gtest.framework */; };
-		274D111C13773719009EA268 /* TestFields.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 274D111B13773719009EA268 /* TestFields.cpp */; };
-		274D12AD1377A765009EA268 /* TestArrays.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 274D12AC1377A765009EA268 /* TestArrays.cpp */; };
-		274D133A137846D5009EA268 /* TestNested.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 274D1339137846D5009EA268 /* TestNested.cpp */; };
-		274D136813789989009EA268 /* FudgeJSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 274D136713789989009EA268 /* FudgeJSON.cpp */; };
-		277240021380588B00136EFA /* TestExamples.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 277240011380588B00136EFA /* TestExamples.cpp */; };
-		27F6B1571361DC58009869C7 /* FudgeMsg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B1561361DC58009869C7 /* FudgeMsg.cpp */; };
-		27F6B23613666C91009869C7 /* FudgeWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B23513666C91009869C7 /* FudgeWriter.cpp */; };
-		27F6C81B136BB818009869C7 /* FudgeDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27F6C81A136BB818009869C7 /* FudgeDump.cpp */; };
-		27F6C963136DE840009869C7 /* FudgeArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27F6C962136DE840009869C7 /* FudgeArray.cpp */; };
-		8DD76F650486A84900D96B5E /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.cpp */; settings = {ATTRIBUTES = (); }; };
+		27724150138081CE00136EFA /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27724135138081CE00136EFA /* main.cpp */; };
+		27724151138081CE00136EFA /* TestArrays.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27724147138081CE00136EFA /* TestArrays.cpp */; };
+		27724152138081CE00136EFA /* TestExamples.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27724148138081CE00136EFA /* TestExamples.cpp */; };
+		27724153138081CE00136EFA /* TestFields.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27724149138081CE00136EFA /* TestFields.cpp */; };
+		27724154138081CE00136EFA /* TestNested.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2772414A138081CE00136EFA /* TestNested.cpp */; };
+		2772416D1380835200136EFA /* array.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 277241671380835200136EFA /* array.cpp */; };
+		2772416E1380835200136EFA /* dump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 277241681380835200136EFA /* dump.cpp */; };
+		2772416F1380835200136EFA /* json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2772416A1380835200136EFA /* json.cpp */; };
+		277241701380835200136EFA /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2772416B1380835200136EFA /* message.cpp */; };
+		277241711380835200136EFA /* writer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2772416C1380835200136EFA /* writer.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
-		08FB7796FE84155DC02AAC07 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
 		274D10FF137736BB009EA268 /* gtest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = gtest.framework; path = /Library/Frameworks/gtest.framework; sourceTree = "<absolute>"; };
-		274D111B13773719009EA268 /* TestFields.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestFields.cpp; sourceTree = "<group>"; };
-		274D12AC1377A765009EA268 /* TestArrays.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestArrays.cpp; sourceTree = "<group>"; };
-		274D1339137846D5009EA268 /* TestNested.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestNested.cpp; sourceTree = "<group>"; };
-		274D136613789989009EA268 /* FudgeJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FudgeJSON.h; sourceTree = "<group>"; };
-		274D136713789989009EA268 /* FudgeJSON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FudgeJSON.cpp; sourceTree = "<group>"; };
-		277240011380588B00136EFA /* TestExamples.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestExamples.cpp; sourceTree = "<group>"; };
-		27F6B1551361DC58009869C7 /* FudgeMsg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FudgeMsg.h; sourceTree = "<group>"; };
-		27F6B1561361DC58009869C7 /* FudgeMsg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FudgeMsg.cpp; sourceTree = "<group>"; };
-		27F6B23413666C91009869C7 /* FudgeWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FudgeWriter.h; sourceTree = "<group>"; };
-		27F6B23513666C91009869C7 /* FudgeWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FudgeWriter.cpp; sourceTree = "<group>"; };
-		27F6B2621366849E009869C7 /* FudgeInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FudgeInternal.h; sourceTree = "<group>"; };
-		27F6C819136BB818009869C7 /* FudgeDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FudgeDump.h; sourceTree = "<group>"; };
-		27F6C81A136BB818009869C7 /* FudgeDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FudgeDump.cpp; sourceTree = "<group>"; };
-		27F6C961136DE840009869C7 /* FudgeArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FudgeArray.h; sourceTree = "<group>"; };
-		27F6C962136DE840009869C7 /* FudgeArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FudgeArray.cpp; sourceTree = "<group>"; };
+		2772412A138081CE00136EFA /* array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array.h; sourceTree = "<group>"; };
+		2772412C138081CE00136EFA /* dump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dump.h; sourceTree = "<group>"; };
+		2772412F138081CE00136EFA /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = "<group>"; };
+		27724131138081CE00136EFA /* message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message.h; sourceTree = "<group>"; };
+		27724133138081CE00136EFA /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = "<group>"; };
+		27724135138081CE00136EFA /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+		27724137138081CE00136EFA /* allNames.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = allNames.dat; sourceTree = "<group>"; };
+		27724138138081CE00136EFA /* allNames.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = allNames.json; sourceTree = "<group>"; };
+		27724139138081CE00136EFA /* allOrdinals.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = allOrdinals.dat; sourceTree = "<group>"; };
+		2772413A138081CE00136EFA /* allOrdinals.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = allOrdinals.json; sourceTree = "<group>"; };
+		2772413B138081CE00136EFA /* dateTimes.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = dateTimes.dat; sourceTree = "<group>"; };
+		2772413C138081CE00136EFA /* dateTimes.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dateTimes.json; sourceTree = "<group>"; };
+		2772413D138081CE00136EFA /* deeper_fudge_msg.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = deeper_fudge_msg.dat; sourceTree = "<group>"; };
+		2772413E138081CE00136EFA /* deeper_fudge_msg.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = deeper_fudge_msg.json; sourceTree = "<group>"; };
+		2772413F138081CE00136EFA /* fixedWidthByteArrays.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = fixedWidthByteArrays.dat; sourceTree = "<group>"; };
+		27724140138081CE00136EFA /* fixedWidthByteArrays.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fixedWidthByteArrays.json; sourceTree = "<group>"; };
+		27724141138081CE00136EFA /* subMsg.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = subMsg.dat; sourceTree = "<group>"; };
+		27724142138081CE00136EFA /* subMsg.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = subMsg.json; sourceTree = "<group>"; };
+		27724143138081CE00136EFA /* unknown.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = unknown.dat; sourceTree = "<group>"; };
+		27724144138081CE00136EFA /* unknown.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = unknown.json; sourceTree = "<group>"; };
+		27724145138081CE00136EFA /* variableWidthColumnSizes.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = variableWidthColumnSizes.dat; sourceTree = "<group>"; };
+		27724146138081CE00136EFA /* variableWidthColumnSizes.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = variableWidthColumnSizes.json; sourceTree = "<group>"; };
+		27724147138081CE00136EFA /* TestArrays.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestArrays.cpp; sourceTree = "<group>"; };
+		27724148138081CE00136EFA /* TestExamples.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestExamples.cpp; sourceTree = "<group>"; };
+		27724149138081CE00136EFA /* TestFields.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestFields.cpp; sourceTree = "<group>"; };
+		2772414A138081CE00136EFA /* TestNested.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestNested.cpp; sourceTree = "<group>"; };
+		277241671380835200136EFA /* array.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = array.cpp; sourceTree = "<group>"; };
+		277241681380835200136EFA /* dump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dump.cpp; sourceTree = "<group>"; };
+		277241691380835200136EFA /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = "<group>"; };
+		2772416A1380835200136EFA /* json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json.cpp; sourceTree = "<group>"; };
+		2772416B1380835200136EFA /* message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message.cpp; sourceTree = "<group>"; };
+		2772416C1380835200136EFA /* writer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = writer.cpp; sourceTree = "<group>"; };
 		8DD76F6C0486A84900D96B5E /* Fudge */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Fudge; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 		08FB7794FE84155DC02AAC07 /* Fudge */ = {
 			isa = PBXGroup;
 			children = (
-				08FB7795FE84155DC02AAC07 /* Source */,
-				274D1119137736EE009EA268 /* Tests */,
+				27724128138081CE00136EFA /* fudge */,
+				277241661380835200136EFA /* src */,
+				27724134138081CE00136EFA /* test */,
 				274D10FF137736BB009EA268 /* gtest.framework */,
 				1AB674ADFE9D54B511CA2CBB /* Products */,
 			);
 			name = Fudge;
 			sourceTree = "<group>";
 		};
-		08FB7795FE84155DC02AAC07 /* Source */ = {
-			isa = PBXGroup;
-			children = (
-				08FB7796FE84155DC02AAC07 /* main.cpp */,
-				27F6B1551361DC58009869C7 /* FudgeMsg.h */,
-				27F6B1561361DC58009869C7 /* FudgeMsg.cpp */,
-				27F6C961136DE840009869C7 /* FudgeArray.h */,
-				27F6C962136DE840009869C7 /* FudgeArray.cpp */,
-				27F6B23413666C91009869C7 /* FudgeWriter.h */,
-				27F6B23513666C91009869C7 /* FudgeWriter.cpp */,
-				27F6C819136BB818009869C7 /* FudgeDump.h */,
-				27F6C81A136BB818009869C7 /* FudgeDump.cpp */,
-				274D136613789989009EA268 /* FudgeJSON.h */,
-				274D136713789989009EA268 /* FudgeJSON.cpp */,
-				27F6B2621366849E009869C7 /* FudgeInternal.h */,
-			);
-			name = Source;
-			sourceTree = "<group>";
-		};
 		1AB674ADFE9D54B511CA2CBB /* Products */ = {
 			isa = PBXGroup;
 			children = (
 			name = Products;
 			sourceTree = "<group>";
 		};
-		274D1119137736EE009EA268 /* Tests */ = {
+		27724128138081CE00136EFA /* fudge */ = {
 			isa = PBXGroup;
 			children = (
-				274D111B13773719009EA268 /* TestFields.cpp */,
-				274D12AC1377A765009EA268 /* TestArrays.cpp */,
-				274D1339137846D5009EA268 /* TestNested.cpp */,
-				277240011380588B00136EFA /* TestExamples.cpp */,
+				2772412A138081CE00136EFA /* array.h */,
+				2772412C138081CE00136EFA /* dump.h */,
+				2772412F138081CE00136EFA /* json.h */,
+				27724131138081CE00136EFA /* message.h */,
+				27724133138081CE00136EFA /* writer.h */,
 			);
-			name = Tests;
+			path = fudge;
+			sourceTree = "<group>";
+		};
+		27724134138081CE00136EFA /* test */ = {
+			isa = PBXGroup;
+			children = (
+				27724135138081CE00136EFA /* main.cpp */,
+				27724147138081CE00136EFA /* TestArrays.cpp */,
+				27724148138081CE00136EFA /* TestExamples.cpp */,
+				27724149138081CE00136EFA /* TestFields.cpp */,
+				2772414A138081CE00136EFA /* TestNested.cpp */,
+				27724136138081CE00136EFA /* test_data */,
+			);
+			path = test;
+			sourceTree = "<group>";
+		};
+		27724136138081CE00136EFA /* test_data */ = {
+			isa = PBXGroup;
+			children = (
+				27724137138081CE00136EFA /* allNames.dat */,
+				27724138138081CE00136EFA /* allNames.json */,
+				27724139138081CE00136EFA /* allOrdinals.dat */,
+				2772413A138081CE00136EFA /* allOrdinals.json */,
+				2772413B138081CE00136EFA /* dateTimes.dat */,
+				2772413C138081CE00136EFA /* dateTimes.json */,
+				2772413D138081CE00136EFA /* deeper_fudge_msg.dat */,
+				2772413E138081CE00136EFA /* deeper_fudge_msg.json */,
+				2772413F138081CE00136EFA /* fixedWidthByteArrays.dat */,
+				27724140138081CE00136EFA /* fixedWidthByteArrays.json */,
+				27724141138081CE00136EFA /* subMsg.dat */,
+				27724142138081CE00136EFA /* subMsg.json */,
+				27724143138081CE00136EFA /* unknown.dat */,
+				27724144138081CE00136EFA /* unknown.json */,
+				27724145138081CE00136EFA /* variableWidthColumnSizes.dat */,
+				27724146138081CE00136EFA /* variableWidthColumnSizes.json */,
+			);
+			path = test_data;
+			sourceTree = "<group>";
+		};
+		277241661380835200136EFA /* src */ = {
+			isa = PBXGroup;
+			children = (
+				277241671380835200136EFA /* array.cpp */,
+				277241681380835200136EFA /* dump.cpp */,
+				277241691380835200136EFA /* internal.h */,
+				2772416A1380835200136EFA /* json.cpp */,
+				2772416B1380835200136EFA /* message.cpp */,
+				2772416C1380835200136EFA /* writer.cpp */,
+			);
+			path = src;
 			sourceTree = "<group>";
 		};
 /* End PBXGroup section */
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				8DD76F650486A84900D96B5E /* main.cpp in Sources */,
-				27F6B1571361DC58009869C7 /* FudgeMsg.cpp in Sources */,
-				27F6B23613666C91009869C7 /* FudgeWriter.cpp in Sources */,
-				27F6C81B136BB818009869C7 /* FudgeDump.cpp in Sources */,
-				27F6C963136DE840009869C7 /* FudgeArray.cpp in Sources */,
-				274D111C13773719009EA268 /* TestFields.cpp in Sources */,
-				274D12AD1377A765009EA268 /* TestArrays.cpp in Sources */,
-				274D133A137846D5009EA268 /* TestNested.cpp in Sources */,
-				274D136813789989009EA268 /* FudgeJSON.cpp in Sources */,
-				277240021380588B00136EFA /* TestExamples.cpp in Sources */,
+				27724150138081CE00136EFA /* main.cpp in Sources */,
+				27724151138081CE00136EFA /* TestArrays.cpp in Sources */,
+				27724152138081CE00136EFA /* TestExamples.cpp in Sources */,
+				27724153138081CE00136EFA /* TestFields.cpp in Sources */,
+				27724154138081CE00136EFA /* TestNested.cpp in Sources */,
+				2772416D1380835200136EFA /* array.cpp in Sources */,
+				2772416E1380835200136EFA /* dump.cpp in Sources */,
+				2772416F1380835200136EFA /* json.cpp in Sources */,
+				277241701380835200136EFA /* message.cpp in Sources */,
+				277241711380835200136EFA /* writer.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				GCC_OPTIMIZATION_LEVEL = 0;
 				INSTALL_PATH = /usr/local/bin;
 				PRODUCT_NAME = Fudge;
+				USER_HEADER_SEARCH_PATHS = .;
 			};
 			name = Debug;
 		};
 				GCC_MODEL_TUNING = G5;
 				INSTALL_PATH = /usr/local/bin;
 				PRODUCT_NAME = Fudge;
+				USER_HEADER_SEARCH_PATHS = .;
 			};
 			name = Release;
 		};

FudgeArray.cpp

-/*
- *  FudgeArray.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 5/1/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeArray.h"
-#include "FudgeInternal.h"
-#include <assert.h>
-#include <math.h>
-#include <CoreFoundation/CFByteOrder.h>
-
-
-namespace fudge {
-    
-    
-Array::Array(Type type, Data data) 
-:_type(type), _start(data.ptr), _length(data.size / kFixedSizesByType[type]) 
-{}
-
-
-int32_t Array::intAt(uint32_t index) const {
-    switch (_type) {
-        case kByte:
-        default:
-            return ((const int8_t*)_start)[index];
-        case kShort:
-            return getShort((const uint16_t*)_start + index);
-        case kInt:
-            return getInt((const uint32_t*)_start + index);
-        case kLong:
-            return (int32_t) getLong((const uint64_t*)_start + index);
-        case kFloat:
-            return getFloat((const float*)_start + index);
-        case kDouble:
-            return getDouble((const double*)_start + index);
-    }
-}
-
-
-int32_t IntArray::operator[] (uint32_t index) const {
-    assert(index < _length);
-    return intAt(index);
-}
-
-
-int64_t Int64Array::operator[] (uint32_t index) const {
-    assert(index < _length);
-    switch (_type) {
-        case kLong:
-            return getLong((const uint64_t*)_start + index);
-        case kFloat:
-            return getFloat((const float*)_start + index);
-        case kDouble:
-            return getDouble((const double*)_start + index);
-        default:
-            return intAt(index);
-    }
-}
-
-
-double DoubleArray::operator[] (uint32_t index) const {
-    assert(index < _length);
-    switch (_type) {
-        case kLong:
-            return getLong((const uint64_t*)_start + index);
-        case kFloat:
-            return getFloat((const float*)_start + index);
-        case kDouble:
-            return getDouble((const double*)_start + index);
-        default:
-            return intAt(index);
-    }
-}
-
-    
-}

FudgeArray.h

-/*
- *  FudgeArray.h
- *  Fudge
- *
- *  Created by Jens Alfke on 5/1/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeMsg.h"
-
-namespace fudge {
-    
-class Array {
-  public:
-    Array(Type type, Data data);
-    Type itemType() const                           {return _type;}
-    uint32_t length() const                         {return _length;}
-    
-  protected:
-    int32_t intAt(uint32_t index) const;
-
-    Type _type;
-    const void* _start;
-    uint32_t _length;
-};
-
-class IntArray : public Array {
-  public:
-    IntArray(Type type, Data data)                  :Array(type, data) {}
-    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) const;
-};
-
-class DoubleArray : public Array {
-  public:
-    DoubleArray(Type type, Data data)               :Array(type, data) {}
-    double operator[] (uint32_t index) const;
-};
-
-}

FudgeDump.cpp

-/*
- *  FudgeDump.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 4/29/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeDump.h"
-#include "FudgeMsg.h"
-#include <algorithm>
-#include <sstream>
-
-namespace fudge {
-    
-static const char* kTypeName[kMaxBuiltinType+1] = {
-    "indicator", "boolean", "byte", "short", "int", "long",
-    "byte[]", "short[]", "int[]", "long[]",
-    "float", "double", "float[]", "double[]",
-    "string", "message", "???",
-    "byte[4]", "byte[8]", "byte[16]", "byte[20]", "byte[32]",
-    "byte[64]", "byte[128]", "byte[256]", "byte[512]", 
-};
-    
-    
-static std::string NameOfFieldType(Type type) {
-    if (type < kMaxBuiltinType)
-        return kTypeName[type];
-    else {
-        std::stringstream result;
-        result << "type#" << type;
-        return result.str();
-    }
-}
-    
-    
-void Dump(Data data, std::ostream& out, uint32_t maxLength) {
-    const uint8_t* bytes = (const uint8_t*)data.ptr;
-    const uint32_t length = std::min(data.size, maxLength);
-    for (unsigned i=0; i<length; i++) {
-        if (i > 0 && i%4 == 0)
-            out << " ";
-        char hex[3];
-        sprintf(hex, "%02X", bytes[i]);
-        out << hex;
-    }
-    if (length < data.size)
-        out << "...";
-}
-
-    
-void Dump(const Field& field, std::ostream& out, const std::string& indent, bool showHex) {
-    out << indent << NameOfFieldType(field.type()) << ": ";
-    
-    bool isMessage = false;
-    switch (field.type()) {
-        case kIndicator:
-            break;
-        case kMessage:
-            isMessage = true;
-            break;
-        case kBoolean ... kLong:
-            out << field.asInt64();
-            break;
-        case kFloat ... kDouble:
-            out << field.asDouble();
-            break;
-        case kString:
-            out << '"' << field.asString() << '"';
-            break;
-        default:
-            showHex = true;
-    }
-    
-    if (showHex && !isMessage) {
-        out << " <";
-        Dump(field.data(), out);
-        out << ">";
-    }
-
-    if (field.hasOrdinal())
-        out << "  [" << field.ordinal() << "]";
-    if (field.hasName())
-        out << "  {'" << field.name() << "'}";
-    out << "\n";
-    
-    if (isMessage)
-        Dump(field.asMessage(), out, indent + "  ", showHex);
-}
-    
-void Dump(const Message& message, std::ostream& out, const std::string& indent, bool showHex) {
-    for (Message::iterator i=message.begin(); i != message.end(); ++i) {
-        Dump(*i, out, indent, showHex);
-    }
-}
-    
-void Dump(const Envelope& env, std::ostream& out, bool showHex) {
-    out << "FudgeEnvelope: (schema=" << (int)env.schemaVersion()
-        << ", taxonomy=" << env.taxonomy() << ")\n";
-    Dump(env.message(), out, "  ", showHex);
-}
-    
-}

FudgeDump.h

-/*
- *  FudgeDump.h
- *  Fudge
- *
- *  Created by Jens Alfke on 4/29/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include <ostream>
-#include <string>
-
-namespace fudge {
-
-class Data;
-class Envelope;
-class Field;
-class Message;
-
-void Dump(const Envelope&, std::ostream& out, bool showHex = false);
-void Dump(const Field& field, std::ostream& out, const std::string& indent, bool showHex = false);
-void Dump(const Message& message, std::ostream& out, const std::string& indent, bool showHex = false);
-
-void Dump(Data data, std::ostream& out, uint32_t maxLength = 32);
-
-}

FudgeInternal.h

-/*
- *  FudgeInternal.h
- *  Fudge
- *
- *  Created by Jens Alfke on 4/25/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include <CoreFoundation/CFByteOrder.h>
-
-namespace fudge {
-
-const uint32_t kNoFixedSize = 0xFFFFFFFF;
-
-extern uint32_t kFixedSizesByType[];
-   
-
-//////// OS-specific utilities for handling big-endian numeric formats:
-    
-
-inline int16_t getShort(const void* ptr) {
-    return (int16_t)CFSwapInt16BigToHost(*(const uint16_t*)ptr);
-}
-
-inline int32_t getInt(const void* ptr) {
-    return (int32_t)CFSwapInt32BigToHost(*(const uint32_t*)ptr);
-}
-
-inline int64_t getLong(const void* ptr) {
-    return (int64_t)CFSwapInt64BigToHost(*(const uint64_t*)ptr);
-}
-
-inline float getFloat(const void* ptr) {
-    return CFConvertFloat32SwappedToHost(*(const CFSwappedFloat32*)ptr);
-}
-
-inline double getDouble(const void* ptr) {
-    return CFConvertFloat64SwappedToHost(*(const CFSwappedFloat64*)ptr);
-}
-    
-}

FudgeJSON.cpp

-/*
- *  FudgeJSON.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 5/9/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeJSON.h"
-#include "FudgeMsg.h"
-#include "FudgeArray.h"
-#include <algorithm>
-#include <sstream>
-
-namespace fudge {
-    
-    
-static void WriteJSON(const Message& message, std::ostream& out,
-                      const std::string& indent, bool compact);
-
-    
-void WriteJSON(const char *str, size_t length, std::ostream& out) {
-    static const char ctrlEscape[16] = {0, 0, 0, 0, 0, 0, 0, 0,
-                                        'b', 't', 'n', 0, 0, 'r', 0, 0};
-    out << '"';
-    int start = 0;  // index of next character in str remaining to be written
-    int i;
-    for (i=0; i<length; ++i) {
-        unsigned char c = str[i];
-        if (c < 32 || c == 127 || c == '"' || c == '\\') {
-            if (start < i)
-                out.write(&str[start], i-start);
-            switch (c) {
-                case '"': 
-                    out << "\\\""; 
-                    break;
-                case '\\':  
-                    out << "\\\\"; 
-                    break;
-                default:
-                    if (c < 16 && ctrlEscape[c])
-                        out << '\\' << ctrlEscape[c];
-                    else {
-                        char hex[7];
-                        sprintf(hex, "\\u%.04X", c);  //FIX: How do I do this directly with ostream?
-                        out << hex;
-                        break;
-                    }
-            }
-            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.write(&str[start], i-start);
-    out << '"';
-}
-    
-    
-void WriteJSON(const std::string& str, std::ostream& out) {
-    WriteJSON(str.data(), str.length(), 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 << "]";
-}
-
-
-static void WriteJSON(const Field& field, std::ostream& out,
-                      const std::string& indent, bool compact) {
-    switch (field.type()) {
-        case kIndicator:
-            out << "null";
-            break;
-        case kMessage:
-            WriteJSON(field.asMessage(), out, indent, compact);
-            break;
-        case kBoolean:
-            out << (field.asInt32() ? "true" : "false");
-            break;
-        case kByte ... kLong:
-            out << field.asInt64();
-            break;
-        case kFloat ... kDouble:
-            out << field.asDouble();
-            break;
-        case kString:
-            WriteJSON(field.asString(), out);
-            break;
-        default:
-            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 {
-                // TODO: Is there something better we can do with unknown types?
-                out << "\"(Unknown data of Fudge type " << (int)field.type() << ")\"";
-            }
-            break;
-    }
-}
-
-void WriteJSON(const Field& field, std::ostream& out, bool compact) {
-    WriteJSON(field, out, "", compact);
-}
-    
-    
-static 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 (i->hasName()) {
-            hasNames = true;
-            break;
-        }
-    }
-    
-    out << (hasNames ? "{" : "[");
-    if (!compact)
-        out << " ";
-
-    std::string nestedIndent = indent + "  ";
-    bool first = true;
-    for (Message::iterator i=message.begin(); i != message.end(); ++i) {
-        if (first)
-            first = false;
-        else {
-            out << ",";
-        }
-        if (!compact)
-            out << "\n" << indent;
-        if (hasNames) {
-            WriteJSON(i->name(), out);
-            out << ":";
-        }
-        WriteJSON(*i, out, nestedIndent, compact);
-    }
-
-    if (!compact)
-        out << " ";
-    out << (hasNames ? "}" : "]");
-}
-    
-void WriteJSON(const Message& message, std::ostream& out, bool compact) {
-    WriteJSON(message, out, "", compact);
-}
-
-    
-void WriteJSON(const Envelope& env, std::ostream& out, bool compact) {
-    WriteJSON(env.message(), out, "  ", compact);
-}
-    
-}

FudgeJSON.h

-/*
- *  FudgeJSON.h
- *  Fudge
- *
- *  Created by Jens Alfke on 5/9/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include <ostream>
-#include <string>
-
-namespace fudge {
-
-class Envelope;
-class Field;
-class Message;
-
-void WriteJSON(const Envelope&, std::ostream& out, 
-               bool compact = false);
-void WriteJSON(const Message& message, std::ostream& out, bool compact = false);
-void WriteJSON(const Field& field, std::ostream& out, bool compact = false);
-
-void WriteJSON(const char *str, size_t length, std::ostream& out);
-void WriteJSON(const std::string& str, std::ostream& out);
-
-}

FudgeMsg.cpp

-/*
- *  FudgeMsg.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 4/22/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeMsg.h"
-#include "FudgeArray.h"
-#include "FudgeInternal.h"
-#include <assert.h>
-#include <math.h>
-
-#include <CoreFoundation/CFByteOrder.h>
-
-
-namespace fudge {
-
-
-uint32_t kFixedSizesByType[kMaxBuiltinType + 1] = {
-    0, 1, 1, 2, 4, 8,
-    kNoFixedSize, kNoFixedSize, kNoFixedSize, kNoFixedSize,
-    4, 8,
-    kNoFixedSize, kNoFixedSize, kNoFixedSize, kNoFixedSize, kNoFixedSize,
-    4, 8, 16, 20, 32, 64, 128, 256, 512,
-    4, 8, 12
-};
-    
-    
-uint32_t Field::readDataSize(const uint8_t* &dataPtr) const {
-    switch (_width) {
-        case 0:
-        default:
-            return 0;
-        case 1:
-            return *(dataPtr++);
-        case 2: {
-            uint32_t size = (uint16_t)getShort(dataPtr);
-            dataPtr += 2;
-            return size;
-        }
-        case 3: {
-            uint32_t size = (uint32_t)getInt(dataPtr);
-            dataPtr += 4;
-            return size;
-        }
-    }
-}
-
-
-/** Verifies that a Field is syntactically correct and doesn't extend past the 'eof' pointer.
-    All Fields of a Message/Envelope are validated before the user is given access to them,
-    so other methods here do not need to do their own validation. */
-bool Field::validate(const void* eof) const {
-    const uint8_t* dataPtr = _data;
-    if (dataPtr > eof)
-        return false;       // Too short to hold field header
-    if (_hasOrdinal) {
-        dataPtr += 2;
-        if (dataPtr > eof)
-            return false;       // Too short to hold ordinal
-    }
-    if (_hasName) {
-        if (dataPtr+1 > eof)
-            return false;       // Too short to hold name length
-        dataPtr += *dataPtr + 1;
-        if (dataPtr > eof)
-            return false;       // Too short to hold name
-    }
-    
-    uint32_t dataSize;
-    if (_isFixedWidth) {
-        if (_type > kMaxBuiltinType)
-            return false;       // Fixed-size flag conflicts with type
-        dataSize = kFixedSizesByType[_type];
-        if (dataSize == kNoFixedSize)
-            return false;       // Fixed-size flag conflicts with type
-    } else {
-        unsigned sizeSize = _width + (_width == 3);
-        if (dataPtr + sizeSize > eof)
-            return false;       // Too short to hold data size field
-        
-        dataSize = readDataSize(dataPtr);
-        
-        if (_type <= kMaxBuiltinType && kFixedSizesByType[_type] != kNoFixedSize
-                && kFixedSizesByType[_type] != dataSize)
-            return false;       // Wrong size given for fixed-size type
-    }
-    
-    if (dataPtr + dataSize > eof)
-        return false;           // Too short to hold data
-    
-    if (_type == kMessage) {
-        // Recursively validate nested fields:
-        if (!asMessage().validate(eof))
-            return false;
-    } else {
-        // Validate array:
-        Type itemType = arrayType();
-        if (itemType > kByte && (dataSize % kFixedSizesByType[itemType]) != 0)
-            return false;       // Array size isn't an integral number of items
-    }
-    
-    // Alright, it passes
-    return true;
-}
-
-
-Data Field::data() const {
-    const uint8_t* dataPtr = _data;
-    if (_hasOrdinal)
-        dataPtr += 2;
-    if (_hasName)
-        dataPtr += *dataPtr + 1;
-
-    Data result;
-    
-    if (_isFixedWidth)
-        result.size = kFixedSizesByType[_type];
-    else
-        result.size = readDataSize(dataPtr);
-    result.ptr = dataPtr;
-    return result;
-}
-    
-    
-uint16_t Field::ordinal() const {
-    if (!_hasOrdinal)
-        return 0;
-    return CFSwapInt16BigToHost(*(const uint16_t*)_data);
-}
-    
-    
-Data Field::nameBytes() const {
-    if (!_hasName)
-        return Data();
-    const uint8_t* namePtr = _data;
-    if (_hasOrdinal)
-        namePtr += 2;
-    return Data(namePtr+1, *namePtr);
-}
-
-
-std::string Field::name() const {
-    Data name = nameBytes();
-    return std::string((const char*)name.ptr, name.size);
-}
-
-
-int32_t Field::asInt32() const {
-    Data myData = data();
-    switch (_type) {
-        case kIndicator:
-            return 0;
-        case kBoolean:
-            return  (*(const int8_t*)myData.ptr) != 0;
-        case kByte:
-            return (*(const int8_t*)myData.ptr);
-        case kShort:
-            return getShort(myData.ptr);
-        case kInt:
-            return getInt(myData.ptr);
-        case kLong:
-            return (int32_t)getLong(myData.ptr);
-        case kFloat:
-            return getFloat(myData.ptr);
-        case kDouble:
-            return getDouble(myData.ptr);
-        default:
-            return 0;
-    }
-}
-
-
-int64_t Field::asInt64() const {
-    Data myData = data();
-    switch (_type) {
-        case kLong:
-            return getLong(myData.ptr);
-        case kFloat:
-            return getFloat(myData.ptr);
-        case kDouble:
-            return getDouble(myData.ptr);
-        default:
-            return asInt32();
-    }
-}
-
-
-float Field::asFloat() const {
-    return (float) asDouble();
-}
-
-
-double Field::asDouble() const {
-    Data myData = data();
-    switch (_type) {
-        case kFloat:
-            return getFloat(myData.ptr);
-        case kDouble:
-            return getDouble(myData.ptr);
-        default:
-            return (double) asInt64();
-    }
-}
-    
-    
-bool Field::isArray() const {
-    return _type >= kByteArray && _type <= kLongArray
-        || _type >= kFloatArray && _type <= kDoubleArray
-        || _type >= kByteArray4 && _type <= kByteArray512;
-}
-    
-    
-Type Field::arrayType() const {
-    if (_type >= kByteArray && _type <= kLongArray)
-        return (Type)(_type - (kByteArray - kByte));
-    else if (_type >= kFloatArray && _type <= kDoubleArray)
-        return (Type)(_type - (kFloatArray - kFloat));
-    else if (_type >= kByteArray4 && _type <= kByteArray512)
-        return kByte;
-    else
-        return kIndicator;
-}
-    
-    
-IntArray Field::asIntArray() const {
-    return IntArray(arrayType(), data());
-}
-
-Int64Array Field::asInt64Array() const {
-    return Int64Array(arrayType(), data());
-}
-
-DoubleArray Field::asDoubleArray() const {
-    return DoubleArray(arrayType(), data());
-}
-
-    
-std::string Field::asString() const {
-    if (_type != kString)
-        return std::string();
-    Data myData = data();
-    return std::string((const char*)myData.ptr, myData.size);
-}
-
-
-Message Field::asMessage() const {
-    if (_type != kMessage)
-        return Message();      // empty / illegal
-    return Message(data());
-}
-
-
-Field::Field(Type type, bool fixedWidth, unsigned width, bool hasOrdinal, bool hasName)
-:_isFixedWidth(fixedWidth),
- _width(width),
- _hasOrdinal(hasOrdinal),
- _hasName(hasName),
- _reserved(0),
- _type(type)
-{ }
-
-
-#pragma mark -
-#pragma mark FUDGE MESSAGE:
-
-
-Message::Message()
-:_begin(NULL), _end(NULL)
-{ }
-
-
-Message::Message(Data data)
-:_begin((const Field*)data.ptr), _end((const Field*)data.end())
-{ }
-
-Message::iterator& Message::iterator::operator++() {
-    _current = (const Field*)_current->data().end();
-    return *this;
-}
-    
-    
-/** Verifies that a Message is syntactically correct and doesn't extend past the 'eof' pointer.
-    All Fields of a Message/Envelope are validated before the user is given access to them,
-    so other methods here do not need to do their own validation. */
-bool Message::validate(const void* eof) const {
-    iterator i = begin();
-    for (; i < end(); ++i)
-        if (!i->validate(eof))
-            return false;
-    return (i == end());
-}
-
-
-#pragma mark -
-#pragma mark FUDGE ENVELOPE:
-    
-    
-Envelope::Envelope(uint8_t schema, uint16_t taxonomy)
-: _processingDirectives(0),
-  _schemaVersion(schema), _taxonomy(CFSwapInt16HostToBig(taxonomy)), 
-  _size(0)
-{ }
-
-const Envelope* Envelope::FromBytes(Data data) {
-    if (data.size < sizeof(Envelope))
-        return NULL;
-    const Envelope* envelope = (const Envelope*)data.ptr;
-    if (envelope->size() != data.size)
-        return NULL;
-    if (!envelope->message().validate())
-        return NULL;    // Contents failed validation!
-    return envelope;
-}
-
-uint32_t Envelope::size() const {
-    return (uint32_t)getInt(&_size);
-}
-
-uint16_t Envelope::taxonomy() const {
-    return (uint16_t)getShort(&_taxonomy);
-}
-
-Message Envelope::message() const {
-    Data data(&_data, size() - sizeof(*this));
-    return Message(data);
-}
-
-}

FudgeMsg.h

-/*
- *  FudgeMsg.h
- *  Fudge
- *
- *  Created by Jens Alfke on 4/22/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- *  Spec:  <http://fudgemsg.org/display/FDG/Encoding+Specification>
- *  Types: <http://fudgemsg.org/display/FDG/Types>
- */
-
-#pragma once
-#include <string>
-
-
-namespace fudge {
-
-    
-class Field;
-class Message;
-class IntArray;
-class Int64Array;
-class DoubleArray;
-
-
-/** The set of standard data types in the Fudge schema. A Field is of one of these types.
-    You may define your own types as part of your own taxonomy, but to avoid future collisions they
-    should be numbered starting at kMaxType (255) and decreasing from there. */
-enum Type {
-    kIndicator = 0,
-    kBoolean,
-    kByte,
-    kShort,
-    kInt,
-    kLong, // 64-bit
-    kByteArray,
-    kShortArray,
-    kIntArray,
-    kLongArray,
-    kFloat,
-    kDouble,
-    kFloatArray,
-    kDoubleArray,
-    kString,
-    kMessage,
-    kUnallocatedType,   // Unused
-    kByteArray4,
-    kByteArray8,
-    kByteArray16,
-    kByteArray20,
-    kByteArray32,
-    kByteArray64,
-    kByteArray128,
-    kByteArray256,
-    kByteArray512,
-    kDate,
-    kTime,
-    kDateTime,
-    
-    kMaxType = 255,     // Maximum legal type value. User-defined types start here, then go downward
-    
-    kMaxBuiltinType = kDateTime
-};
-
-
-/** A convenient wrapper that points to a blob of untyped data. */
-struct Data {
-    Data() :ptr(NULL), size(0) {}
-    Data(const void* p, uint32_t s) :ptr(p), size(s) {}
-    Data(const std::string& str) :ptr(str.data()), size(str.size()) {}
-
-    const void *ptr;
-    uint32_t size;
-    
-    const void* begin() const { return ptr; }
-    const void* end() const   { return (const uint8_t*)ptr + size; }
-};
-    
-    
-/** A complete Fudge data block, containing metadata and the outer-level Message.
-    This is the primary form in which Fudge data is interchanged. */
-class Envelope {
-  public:
-    /** Parses a data blob and, if it's a valid Fudge envelope, returns a pointer to an Envelope
-        object for accessing its contents.
-        Important: The Envelope pointer, and all the other data pointers accessible from it, point
-        within the data blob you passed in to this method. That means that you must not modify or
-        free that memory while you're still using any of the Fudge objects derived from it! */
-    static const Envelope* FromBytes(Data data);
-    
-    uint8_t schemaVersion() const     {return _schemaVersion;}
-    uint16_t taxonomy() const;
-    uint32_t size() const;
-    
-    Message message() const;
-    
-  private:
-    friend class Writer;
-    Envelope(uint8_t schema, uint16_t taxonomy);
-    
-    uint8_t  _processingDirectives;
-    uint8_t  _schemaVersion;
-    uint16_t _taxonomy;
-    uint32_t _size;
-    uint8_t  _data[0];
-};
-
-
-/** A sequence of Fields. A Message is found as the top-level element of an Envelope,
-    and as the content of a field of type kMessage.
-    Random access to Fields is intentially not provided in this API, because it's inefficient:
-    much like a linked-list, it takes O(n) time. If you need it, you're better off iterating
-    the Fields once and mapping them into a more efficient container like a vector or map. */
-class Message {
-  public:
-    Message();
-    
-    class iterator;
-    iterator begin() const  {return iterator(_begin);}
-    iterator end() const    {return iterator(_end);}
- 
-    bool validate(const void* eof) const;
-    bool validate() const   {return validate(end());}
-    
-    class iterator {
-    public:
-        operator const Field*()            {return _current;}
-        const Field& operator*() const     {return *_current;}
-        const Field* operator->() const    {return _current;}
-        iterator& operator++();
-        bool operator==(iterator i) const   {return _current == i._current;}
-        
-    private:
-        friend class Message;
-        iterator(const Field* field) :_current(field) { }
-        const Field* _current;
-    };
-    
-  private:
-    friend class Field;
-    friend class Envelope;
-    Message(Data);
-
-    const Field* _begin;
-    const Field* _end;
-};
-
-
-/** A Field is a single data value: either a scalar, a numeric array, or a nested Message.
-    A Field may have an ordinal (integer tag) or name string, which can be used by schema to
-    identity this Field's purpose in its Message. */
-class Field {
-  public:    
-    Type type() const               {return _type;}
-    
-    Data data() const;
-    bool asBoolean() const          {return asInt32() != 0;}
-    int32_t asInt32() const;
-    int64_t asInt64() const;
-    float asFloat() const;
-    double asDouble() const;
-    std::string asString() const;   // allocates heap space for the string!
-    Message asMessage() const;
-    
-    bool isArray() const;
-    Type arrayType() const;
-    IntArray asIntArray() const;
-    Int64Array asInt64Array() const;
-    DoubleArray asDoubleArray() const;
-    
-    bool hasOrdinal() const         {return _hasOrdinal;}
-    uint16_t ordinal() const;
-    bool hasName() const            {return _hasName;}
-    std::string name() const;   // allocates heap space for the string!
-    Data nameBytes() const;
-
-    bool validate(const void* eof) const;
-
-  private:
-    friend class Writer;
-    Field();
-    ~Field() { }
-    Field(Type type, bool fixedWidth, unsigned width, bool hasOrdinal, bool hasName);
-    Field(const Field&);
-    uint32_t readDataSize(const uint8_t* &dataPtr) const;
-
-    // Members must be laid out exactly as in the Encoding Specification.
-    unsigned _reserved       :3;
-    bool     _hasName        :1;
-    bool     _hasOrdinal     :1;
-    unsigned _width          :2;
-    bool     _isFixedWidth   :1;
-    Type     _type           :8;
-    uint8_t  _data[0];
-};
-
-}

FudgeWriter.cpp

-/*
- *  Writer.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 4/25/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeWriter.h"
-#include "FudgeInternal.h"
-#include <assert.h>
-#include <math.h>
-#include <ostream>
-
-#include <CoreFoundation/CFByteOrder.h>
-
-
-namespace fudge {
-
-
-void Writer::_init() {
-    _open = true;
-    _hasOrdinal = _hasName = false;
-    _fieldStartPos = _dataStartPos = 0;
-}
-
-
-Writer::Writer(std::ostream& out, uint8_t schema, uint16_t taxonomy)
-: _parent(NULL), _out(out)
-{ 
-    Envelope envelope(schema, taxonomy);
-    _envelopeStartPos = _out.tellp();
-    _out.write((const char*)&envelope, sizeof(envelope));
-    _init();
-}
-
-
-Writer::Writer(Writer* parent, std::ostream& out)
-: _parent(parent), _out(out)
-{
-    assert(parent != NULL);
-    _init();
-}
-
-
-Writer::~Writer() {
-    end();
-}
-    
-    
-void Writer::_replaceBytes(std::streampos pos, const void* bytes, uint32_t size) {
-    _out.seekp(pos, std::ios_base::beg);
-    _out.write((const char*)bytes, size);
-    _out.seekp(0, std::ios_base::end);
-}
-
-
-bool Writer::end() {
-    if (!_open)
-        return false;
-    _open = false;
-    if (_parent) {
-        return _parent->endMessage();
-    } else {
-        uint32_t bigSize = CFSwapInt32HostToBig(_out.tellp() - _envelopeStartPos);
-        _replaceBytes(_envelopeStartPos + (std::streamoff)(sizeof(Envelope) - 4), &bigSize, 4);
-        return true;
-    }
-}
-
-
-// This is the primitive method to write a field (or just its header, if data==NULL)
-void Writer::addField(Type type, const void* data, uint32_t size) {
-    // Figure out the width based on the data size:
-    assert(!inNestedMessage());
-    bool fixedWidth = (type <= kMaxBuiltinType && size != kNoFixedSize
-                       && kFixedSizesByType[type] == size);
-    unsigned width;
-    if (size == 0 || fixedWidth)
-        width = 0;
-    else if (size <= UINT8_MAX)
-        width = 1;
-    else if (size <= UINT16_MAX)
-        width = 2;
-    else
-        width = 3;  // (a 3 in the header's width field means 4 bytes)
-    
-    // Write the header:
-    Field field(type, fixedWidth, width, _hasOrdinal, _hasName);
-    _out.write((const char*)&field, 2);
-    
-    // Write the optional ordinal and/or name:
-    if (_hasOrdinal) {
-        uint16_t ordinal = CFSwapInt16HostToBig(_ordinal);
-        _out.write((const char*)&ordinal, sizeof(ordinal));
-        _hasOrdinal = false;
-    }
-    if (_hasName) {
-        assert(_name.size() <= UINT8_MAX);
-        uint8_t nameSize = _name.size();
-        _out.write((const char*)&nameSize, 1);
-        _out << _name;
-        _hasName = false;
-    }
-    
-    // Write the variable-width data size:
-    if (width > 0) {
-        if (width == 3)
-            width = 4;  // convert it to a byte count
-        uint32_t lengthBytes = CFSwapInt32HostToBig(size);
-        _out.write((const char*)&lengthBytes + 4 - width, width);
-    }
-    
-    // And write the data itself, if it was given:
-    if (data)
-        _out.write((const char*)data, size);
-}
-
-
-void Writer::addIndicator() {
-    addField(kIndicator, NULL, 0);
-}
-    
-void Writer::addBoolean(bool b) {
-    uint8_t value = b;
-    addField(kBoolean, &value, 1);
-}
-    
-void Writer::addInt(int i) {
-    Type type;
-    unsigned size;
-    if (i >= INT8_MIN && i <= INT8_MAX) {
-        type = kByte;
-        size = 1;
-    } else if (i >= INT16_MIN && i <= INT16_MAX) {
-        type = kShort;
-        size = 2;
-    } else {
-        type = kInt;
-        size = 4;
-    }
-    int32_t bigi = CFSwapInt32HostToBig(i);
-    const void* data = (const uint8_t*)&bigi + 4 - size;
-    addField(type, data, size);
-}
-
-void Writer::addInt64(int64_t i) {
-    if (i >= INT32_MIN && i <= INT32_MAX)
-        addInt((int)i);
-    else {
-        int64_t value = CFSwapInt64HostToBig(i);
-        addField(kLong, &value, 8);
-    }
-}
-
-void Writer::addFloat(float f) {
-    CFSwappedFloat32 bigf = CFConvertFloat32HostToSwapped(f);
-    addField(kFloat, &bigf, sizeof(bigf));
-}
-
-void Writer::addDouble(double d) {
-    CFSwappedFloat64 bigd = CFConvertFloat64HostToSwapped(d);
-    addField(kDouble, &bigd, sizeof(bigd));
-}
-    
-    
-    
-void Writer::addArray(const int8_t* items, uint32_t count) {
-    Type type = kByteArray;
-    // Figure out if we can use one of the fixed-size array types:
-    for (int specialType = kByteArray4; specialType <= kByteArray512; ++specialType) {
-        if (count <= kFixedSizesByType[specialType]) {
-            if (count == kFixedSizesByType[specialType])
-                type = (Type)specialType;
-            break;
-        }
-    }
-    addField(type, items, count);
-}
-    
-void Writer::addArray(const int16_t* items, uint32_t count) {
-    addField(kShortArray, NULL, count*sizeof(int16_t));
-    for (int i=0; i<count; i++) {
-        uint16_t big = CFSwapInt16HostToBig(items[i]);
-        _out.write((const char*)&big, sizeof(big));
-    }
-    // TODO: This could be optimized by buffering items on the stack and writing bigger chunks
-}
-
-void Writer::addArray(const int32_t* items, uint32_t count) {
-    addField(kIntArray, NULL, count*sizeof(int32_t));
-    for (int i=0; i<count; i++) {
-        uint32_t big = CFSwapInt32HostToBig(items[i]);
-        _out.write((const char*)&big, sizeof(big));
-    }
-}
-
-void Writer::addArray(const int64_t* items, uint32_t count) {
-    addField(kLongArray, NULL, count*sizeof(int64_t));
-    for (int i=0; i<count; i++) {
-        uint64_t big = CFSwapInt64HostToBig(items[i]);
-        _out.write((const char*)&big, sizeof(big));
-    }
-}
-
-void Writer::addArray(const float* items, uint32_t count) {
-    addField(kFloatArray, NULL, count*sizeof(float));
-    for (int i=0; i<count; i++) {
-        CFSwappedFloat32 big = CFConvertFloat32HostToSwapped(items[i]);
-        _out.write((const char*)&big, sizeof(big));
-    }
-}
-
-void Writer::addArray(const double* items, uint32_t count) {
-    addField(kDoubleArray, NULL, count*sizeof(double));
-    for (int i=0; i<count; i++) {
-        CFSwappedFloat64 big = CFConvertFloat64HostToSwapped(items[i]);
-        _out.write((const char*)&big, sizeof(big));
-    }
-}
-    
-    
-
-
-Writer Writer::beginMessage(bool large) {
-    assert(_dataStartPos == 0);  // must not already be in a nested message
-    _fieldStartPos = _out.tellp();
-    addField(kMessage, NULL, (large ?UINT32_MAX :UINT16_MAX));
-    _dataStartPos = _out.tellp();
-    _largeMessage = large;
-    return Writer(this, _out);
-}
-
-
-bool Writer::endMessage() {
-    assert(_dataStartPos > 0);  // must already have begun a message
-    bool ok = true;
-    uint32_t realLength = _out.tellp() - _dataStartPos;
-    if (_largeMessage) {
-        uint32_t bigLength = CFSwapInt32HostToBig(realLength);
-        _replaceBytes(_dataStartPos - (std::streamoff)sizeof(bigLength),
-                          &bigLength, sizeof(bigLength));
-    } else if (realLength <= UINT16_MAX) {
-        uint16_t bigLength = CFSwapInt16HostToBig(realLength);
-        _replaceBytes(_dataStartPos - (std::streamoff)sizeof(bigLength),
-                          &bigLength, sizeof(bigLength));
-    } else {
-        // Field is too long for 16-bit count, so back out and return false
-        _out.seekp(_fieldStartPos, std::ios_base::beg);
-        ok = false;
-    }
-
-    _fieldStartPos = _dataStartPos = 0;
-    return ok;
-}
-
-}

FudgeWriter.h

-/*
- *  Writer.h
- *  Fudge
- *
- *  Created by Jens Alfke on 4/25/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include "FudgeMsg.h"
-#include <ostream>
-
-namespace fudge {
-
-/** Writes Fudge envelopes to a stream.
-    The stream must be seekable, so you can't write directly to a socket. */
-class Writer {
-  public:
-    Writer(std::ostream& out, uint8_t schema = 0, uint16_t taxonomy = 0);
-    Writer(const Writer&);
-    ~Writer();
-    
-    /** Call this after you're done adding fields. The output stream is not complete until the
-        outermost Writer has been ended.
-        @return  True on success, false if the nested message is too large (which can only happen if the 'large' flag was set to false in the beginMessage call that created this Writer.) */
-    bool end();
-    
-    void setNextOrdinal(uint16_t o)             {_hasOrdinal = true; _ordinal = o;}
-    void setNextName(const std::string& n)      {_hasName = true; _name = n;}
-    
-    void addIndicator();
-    void addBoolean(bool b);
-    void addInt(int);
-    void addInt64(int64_t);
-    void addFloat(float);
-    void addDouble(double);
-    
-    void addString(const std::string& s)        {addString(s.data(), s.size());}
-    void addString(const char *cString)         {addString(cString, strlen(cString));}
-    void addString(const char *str, uint32_t len)  {addField(kString, str, len);}
-    
-    void addArray(const int8_t*, uint32_t count);
-    void addArray(const int16_t*, uint32_t count);
-    void addArray(const int32_t*, uint32_t count);
-    void addArray(const int64_t*, uint32_t count);
-    void addArray(const float*, uint32_t count);
-    void addArray(const double*, uint32_t count);
-
-    /** Adds a Field containing a nested message. The returned Writer object will write fields to
-        the nested message. Call its end() method when you're done writing to it. You must end the
-        nested message before adding any more fields to the parent.
-        @param large  False if the nested message's length will always be less than 65536. This will save two bytes in the length field. A value of true (the default) allows for any length of nested message. */
-    Writer beginMessage(bool large = true);
-    
-    /** Returns true if this Writer is waiting for a nested message to be completed (that is,
-        beginMessage() has been called, but that Message's end() method hasn't been called yet.) */
-    bool inNestedMessage() const                {return _dataStartPos > 0;}
-    
-    /** Adds a raw field of any type, including taxonomy-defined nonstandard types.
-        If you use this to write numeric types (including arrays) make sure that you convert the
-        data to big-endian byte order, and that the data size is appropriate for that type. */
-    void addField(Type type, const void* data, uint32_t size);
-
-  private:
-    Writer(Writer* parent, std::ostream& output);
-    void _init();
-    void _writeHeader();
-    void _replaceBytes(std::streampos pos, const void* bytes, uint32_t size);
-    bool endMessage();
-    
-    Writer* _parent;
-    std::ostream& _out;
-    bool _open;
-    bool _largeMessage;
-    std::streampos _envelopeStartPos, _fieldStartPos, _dataStartPos;
-    bool _hasOrdinal, _hasName;
-    uint16_t _ordinal;
-    std::string _name;
-};
-
-}

TestArrays.cpp

-/*
- *  TestArrays.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 5/8/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include <gtest/gtest.h>
-
-#include <iostream>
-#include <sstream>
-
-#include "FudgeWriter.h"
-#include "FudgeArray.h"
-#include "FudgeDump.h"
-#include "FudgeJSON.h"
-
-using namespace fudge;
-
-
-template <typename T>
-static void VerifyArray(const T expected[], size_t expectedLength, const Field* field) {
-    IntArray outIntArray = field->asIntArray();
-    Int64Array outLongArray = field->asInt64Array();
-    DoubleArray outDoubleArray = field->asDoubleArray();
-    EXPECT_EQ(expectedLength, outIntArray.length());
-    for (int j=0; j<expectedLength; j++) {
-        EXPECT_EQ((int32_t)expected[j], outIntArray[j]);
-        EXPECT_EQ((int64_t)expected[j], outLongArray[j]);
-        EXPECT_EQ((double)expected[j], outDoubleArray[j]);
-    }
-}    
-
-
-static void TestByteArray(const int8_t bytes[], size_t size) {
-    std::stringstream out;
-    Writer writer(out);
-    writer.addArray(bytes, size);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope);
-    if (size < 20) {
-        WriteJSON(*envelope, std::cout);
-        std::cout << "\n";
-    }
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_EQ(kByte, i->arrayType());
-    
-    VerifyArray(bytes, size, i);
-    
-    ++i;
-    EXPECT_TRUE(i == msg.end());
-}
-
-
-TEST(FudgeField, ByteArray) {
-    const int8_t bytes[10] = {123, 100, 98, 1, 0, -1, -98, -100, -123, -128};
-    TestByteArray(bytes, sizeof(bytes));
-}
-
-
-TEST(FudgeField, ByteArraySizes) {
-    int8_t bytes[515];
-    memset(bytes, 0x0D, 515);
-    for (int size = 0; size <= 515; ++size) {
-        TestByteArray(bytes, size);
-    }
-}
-
-
-TEST(FudgeField, ShortArray) {
-    int16_t shorts[10] = {1234, 4321, 42, 17, 1964, 32767, 1337, -1234, -32768, 0};
-    
-    std::stringstream out;
-    Writer writer(out);
-    writer.addArray(shorts, 10);
-    writer.end();
-        
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope);
-    WriteJSON(*envelope, std::cout);
-    std::cout << "\n";
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_EQ(kShortArray, i->type());
-    EXPECT_EQ(kShort, i->arrayType());
-    
-    VerifyArray(shorts, 10, i);
-    
-    ++i;
-    EXPECT_TRUE(i == msg.end());
-}
-
-
-TEST(FudgeField, IntArray) {
-    int32_t ints[10] = {1234567, 87654321, 42, 17, 1964, INT32_MAX, 1337, INT32_MIN, -32768, 0};
-    
-    std::stringstream out;
-    Writer writer(out);
-    writer.addArray(ints, 10);
-    writer.end();
-        
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope);
-    WriteJSON(*envelope, std::cout);
-    std::cout << "\n";
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_EQ(kIntArray, i->type());
-    EXPECT_EQ(kInt, i->arrayType());
-    
-    VerifyArray(ints, 10, i);
-    
-    ++i;
-    EXPECT_TRUE(i == msg.end());
-}
-
-
-TEST(FudgeField, FloatArray) {
-    float floats[10] = {-1234567, -867.5309, -1, 3.14159, 2.71828, 186282, 1.0e10, 6.02e23, 0};
-    
-    std::stringstream out;
-    Writer writer(out);
-    writer.addArray(floats, 10);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope);
-    WriteJSON(*envelope, std::cout);
-    std::cout << "\n";
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_EQ(kFloatArray, i->type());
-    EXPECT_EQ(kFloat, i->arrayType());
-    
-    VerifyArray(floats, 10, i);
-    
-    ++i;
-    EXPECT_TRUE(i == msg.end());
-}
-
-
-TEST(FudgeField, DoubleArray) {
-    double doubles[10] = {-1234567, -867.5309, -1, 3.14159, 2.71828, 186282, 1.0e10, 6.02e23, 0};
-    
-    std::stringstream out;
-    Writer writer(out);
-    writer.addArray(doubles, 10);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope);
-    WriteJSON(*envelope, std::cout);
-    std::cout << "\n";
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_EQ(kDoubleArray, i->type());
-    EXPECT_EQ(kDouble, i->arrayType());
-    
-    VerifyArray(doubles, 10, i);
-    
-    ++i;
-    EXPECT_TRUE(i == msg.end());
-}

TestExamples.cpp

-/*
- *  TestExamples.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 5/15/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-
-#include <gtest/gtest.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-
-#include "FudgeWriter.h"
-#include "FudgeDump.h"
-#include "FudgeJSON.h"
-
-using namespace fudge;
-using namespace std;
-
-
-// Helper class for reading (mapping) the contents of a file into a Data object.
-class FileData : public Data {
-public:
-    FileData(string path)
-    : _fd(-1)
-    {
-        _fd = open(path.c_str(), O_RDONLY);
-        EXPECT_GT(_fd, 0) << "Couldn't open file " << path << " : " << strerror(errno);
-        if (_fd < 0)
-            return;
-        struct stat info;
-        int ok = fstat(_fd, &info);
-        EXPECT_GE(ok, 0) << "Couldn't access file " << path << " : " << strerror(errno);
-        if (ok < 0)
-            return;
-        this->size = info.st_size;
-        this->ptr = mmap(NULL, this->size, PROT_READ, MAP_PRIVATE, _fd, 0);
-        EXPECT_TRUE(this->ptr != NULL)  << "Couldn't map file " << path << " : " << strerror(errno);
-        if (!this->ptr)
-            this->size = 0;
-    }
-    
-    ~FileData() {
-        if (this->ptr)
-            munmap((void*)this->ptr, this->size);
-        if (_fd >= 0)
-            close(_fd);
-    }
-    
-private:
-    int _fd;
-};
-
-
-// Ick. This is platform specific (Xcode puts the binary in a build/Debug subfolder that
-// we then have to crawl out of to find the test_data folder at the top level.)
-static const string kTestFileDir("../../test_data/");
-
-
-// If you set this to 1, TestFile will rebuild the .json files from the generated JSON
-// rather than using them as input. Only do this if the .dat files have changed or the
-// JSON encoder has changed to produce slightly different formatting.
-#define REBUILD_EXPECTED_DATA_FILES 0
-
-
-static void TestFile(string name) {
-    string path = kTestFileDir + name;
-    FileData f(path + ".dat");
-    if (!f.ptr)
-        return;
-    const Envelope* envelope = Envelope::FromBytes(f);
-    EXPECT_TRUE(envelope != NULL);
-    if (!envelope)
-        return;
-    std::cout << "Parsed Fudge file " << (path + ".dat") << "\n";
-    
-#if REBUILD_EXPECTED_DATA_FILES
-    cout << "*** Writing JSON to " << (path + ".json") << "\n";
-    fstream jsonStream((path + ".json").c_str(), fstream::out | fstream::trunc);
-    EXPECT_FALSE(jsonStream.fail());
-    if (jsonStream.fail())
-        return;
-#else
-    stringstream jsonStream;
-#endif
-    
-    WriteJSON(*envelope, jsonStream);
-    
-#if REBUILD_EXPECTED_DATA_FILES
-    jsonStream.close();
-    EXPECT_TRUE(jsonStream.good());
-#else
-    FileData expected(path + ".json");
-    EXPECT_TRUE(expected.ptr != NULL);
-    if (!expected.ptr)
-        return;
-    string expectedStr((const char*)expected.ptr, expected.size);
-    EXPECT_EQ(expectedStr, jsonStream.str());
-#endif
-}
-
-
-TEST(FudgeExamples, allNames) {
-    TestFile("allNames");
-}
-
-TEST(FudgeExamples, allOrdinals) {
-    TestFile("allOrdinals");
-}
-
-TEST(FudgeExamples, dateTimes) {
-    TestFile("dateTimes");
-}
-
-TEST(FudgeExamples, deeper_fudge_msg) {
-    TestFile("deeper_fudge_msg");
-}
-
-TEST(FudgeExamples, fixedWidthByteArrays) {
-    TestFile("fixedWidthByteArrays");
-}
-
-TEST(FudgeExamples, subMsg) {
-    TestFile("subMsg");
-}
-
-TEST(FudgeExamples, unknown) {
-    TestFile("unknown");
-}
-
-TEST(FudgeExamples, variableWidthColumnSizes) {
-    TestFile("variableWidthColumnSizes");
-}

TestFields.cpp

-/*
- *  TestFields.cpp
- *  Fudge
- *
- *  Created by Jens Alfke on 5/8/11.
- *  Copyright 2011 Jens Alfke. All rights reserved.
- *
- */
-
-#include <gtest/gtest.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-
-#include "FudgeWriter.h"
-#include "FudgeArray.h"
-#include "FudgeDump.h"
-#include "FudgeJSON.h"
-
-using namespace fudge;
-
-
-static void HexDumpString(std::string str) {
-    std::cout << str.size() << " bytes: ";
-    Data data(str.data(), str.size());
-    Dump(data, std::cout, 4096);
-    std::cout << "\n";
-}
-
-
-static void CheckNextField(const Message& msg, Message::iterator i, Type expectedType) {
-    ASSERT_FALSE(i == msg.end());
-    printf("  type = %d, int = %i\n", i->type(), i->asInt32());
-    EXPECT_EQ(expectedType, i->type());
-}
-
-static void CheckNextField(const Message& msg, Message::iterator i,
-                           Type expectedType, int32_t expectedIntValue) {
-    CheckNextField(msg, i, expectedType);
-    EXPECT_EQ(expectedIntValue, i->asInt32());
-}
-
-
-TEST(FudgeEnvelope, Envelope) {
-    // Write an Envelope:
-    std::stringstream out;
-    Writer writer(out, 7, 1234);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope != NULL);
-    EXPECT_EQ(7, envelope->schemaVersion());
-    EXPECT_EQ(1234, envelope->taxonomy());
-}
-
-
-TEST(FudgeField, Ordinals) {
-    std::stringstream out;
-    Writer writer(out);
-    writer.setNextOrdinal(0);
-    writer.addInt(1234);
-    writer.setNextOrdinal(256);
-    writer.addInt(1234);
-    writer.setNextOrdinal(65535);
-    writer.addInt(1234);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope != NULL);
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_TRUE(i->hasOrdinal());
-    EXPECT_EQ(0, i->ordinal());
-    
-    ASSERT_FALSE(++i == msg.end());
-    EXPECT_TRUE(i->hasOrdinal());
-    EXPECT_EQ(256, i->ordinal());
-    
-    ASSERT_FALSE(++i == msg.end());
-    EXPECT_TRUE(i->hasOrdinal());
-    EXPECT_EQ(65535, i->ordinal());
-    
-    ASSERT_TRUE(++i == msg.end());
-}
-
-
-TEST(FudgeField, Names) {
-    std::string longestName(255, '!');
-    ASSERT_EQ(255, longestName.length());
-    std::stringstream out;
-    Writer writer(out);
-    writer.setNextName("");
-    writer.addInt(1234);
-    writer.setNextName("foo");
-    writer.addInt(1234);
-    writer.setNextName(longestName);
-    writer.addInt(1234);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope != NULL);
-
-    WriteJSON(*envelope, std::cout, true);
-    std::cout << "\n";
-
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_TRUE(i->hasName());
-    EXPECT_EQ("", i->name());
-    
-    ASSERT_FALSE(++i == msg.end());
-    EXPECT_TRUE(i->hasName());
-    EXPECT_EQ("foo", i->name());
-    
-    ASSERT_FALSE(++i == msg.end());
-    EXPECT_TRUE(i->hasName());
-    EXPECT_EQ(longestName, i->name());
-    
-    ASSERT_TRUE(++i == msg.end());
-}
-
-
-TEST(FudgeField, OrdinalsAndNames) {
-    std::string longestName(255, '!');
-    ASSERT_EQ(255, longestName.length());
-    std::stringstream out;
-    Writer writer(out);
-    writer.setNextOrdinal(0);
-    writer.setNextName("");
-    writer.addInt(1234);
-    writer.setNextOrdinal(256);
-    writer.setNextName("foo");
-    writer.addInt(1234);
-    writer.setNextOrdinal(65535);
-    writer.setNextName(longestName);
-    writer.addInt(1234);
-    writer.end();
-    
-    std::string result = out.str();
-    const Envelope* envelope = Envelope::FromBytes(result);
-    ASSERT_TRUE(envelope != NULL);
-    Message msg = envelope->message();
-    Message::iterator i = msg.begin();
-    
-    ASSERT_FALSE(i == msg.end());
-    EXPECT_TRUE(i->hasOrdinal());
-    EXPECT_EQ(0, i->ordinal());
-    EXPECT_TRUE(i->hasName());
-    EXPECT_EQ("", i->name());
-    
-    ASSERT_FALSE(++i == msg.end());
-    EXPECT_TRUE(i->hasOrdinal());
-    EXPECT_EQ(256, i->ordinal());
-    EXPECT_TRUE(i->hasName());
-    EXPECT_EQ("foo", i->name());
-    
-    ASSERT_FALSE(++i == msg.end());
-    EXPECT_TRUE(i->hasOrdinal());
-    EXPECT_EQ(65535, i->ordinal());
-    EXPECT_TRUE(i->hasName());