mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1074591 (part 1) - Allow JSON collections to be printed on a single line. r=froydnj.
--HG-- extra : rebase_source : d576a70d2d1ff83311ab8cce849ec0b5a6b3fa80
This commit is contained in:
parent
b6419e9f3a
commit
56daec2fe6
@ -33,6 +33,10 @@
|
||||
// pretty-printing, which are (a) correctly escaping strings, and (b) adding
|
||||
// appropriate indentation and commas between items.
|
||||
//
|
||||
// By default, every property is placed on its own line. However, it is
|
||||
// possible to request that objects and arrays be placed entirely on a single
|
||||
// line, which can reduce output size significantly in some cases.
|
||||
//
|
||||
// Strings used (for property names and string property values) are |const
|
||||
// char*| throughout, and can be ASCII or UTF-8.
|
||||
//
|
||||
@ -54,6 +58,13 @@
|
||||
// w.StartObjectElement();
|
||||
// {
|
||||
// w.PointerProperty("ptr", (void*)0x12345678);
|
||||
// w.StartArrayProperty("single-line array", w.SingleLineStyle);
|
||||
// {
|
||||
// w.IntElement(1);
|
||||
// w.StartObjectElement(); // SingleLineStyle is inherited from
|
||||
// w.EndObjectElement(); // above for this collection
|
||||
// }
|
||||
// w.EndArray();
|
||||
// }
|
||||
// w.EndObjectElement();
|
||||
// }
|
||||
@ -71,7 +82,8 @@
|
||||
// "array": [
|
||||
// 3.4,
|
||||
// {
|
||||
// "ptr": "0x12345678"
|
||||
// "ptr": "0x12345678",
|
||||
// "single-line array": [1, {}]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
@ -217,8 +229,21 @@ class JSONWriter
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
// Collections (objects and arrays) are printed in a multi-line style by
|
||||
// default. This can be changed to a single-line style if SingleLineStyle is
|
||||
// specified. If a collection is printed in single-line style, every nested
|
||||
// collection within it is also printed in single-line style, even if
|
||||
// multi-line style is requested.
|
||||
enum CollectionStyle {
|
||||
MultiLineStyle, // the default
|
||||
SingleLineStyle
|
||||
};
|
||||
|
||||
private:
|
||||
const UniquePtr<JSONWriteFunc> mWriter;
|
||||
Vector<bool, 8> mNeedComma; // do we need a comma at depth N?
|
||||
Vector<bool, 8> mNeedNewlines; // do we need newlines at depth N?
|
||||
size_t mDepth; // the current nesting depth
|
||||
|
||||
void Indent()
|
||||
@ -236,10 +261,12 @@ class JSONWriter
|
||||
if (mNeedComma[mDepth]) {
|
||||
mWriter->Write(",");
|
||||
}
|
||||
if (mDepth > 0) {
|
||||
if (mDepth > 0 && mNeedNewlines[mDepth]) {
|
||||
mWriter->Write("\n");
|
||||
Indent();
|
||||
} else if (mNeedComma[mDepth]) {
|
||||
mWriter->Write(" ");
|
||||
}
|
||||
Indent();
|
||||
}
|
||||
|
||||
void PropertyNameAndColon(const char* aName)
|
||||
@ -272,15 +299,18 @@ class JSONWriter
|
||||
mNeedComma[mDepth] = true;
|
||||
}
|
||||
|
||||
void NewCommaEntry()
|
||||
void NewVectorEntries()
|
||||
{
|
||||
// If this tiny allocation OOMs we might as well just crash because we must
|
||||
// be in serious memory trouble.
|
||||
// If these tiny allocations OOM we might as well just crash because we
|
||||
// must be in serious memory trouble.
|
||||
MOZ_RELEASE_ASSERT(mNeedComma.growByUninitialized(1));
|
||||
MOZ_RELEASE_ASSERT(mNeedNewlines.growByUninitialized(1));
|
||||
mNeedComma[mDepth] = false;
|
||||
mNeedNewlines[mDepth] = true;
|
||||
}
|
||||
|
||||
void StartCollection(const char* aMaybePropertyName, const char* aStartChar)
|
||||
void StartCollection(const char* aMaybePropertyName, const char* aStartChar,
|
||||
CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
Separator();
|
||||
if (aMaybePropertyName) {
|
||||
@ -291,15 +321,21 @@ class JSONWriter
|
||||
mWriter->Write(aStartChar);
|
||||
mNeedComma[mDepth] = true;
|
||||
mDepth++;
|
||||
NewCommaEntry();
|
||||
NewVectorEntries();
|
||||
mNeedNewlines[mDepth] =
|
||||
mNeedNewlines[mDepth - 1] && aStyle == MultiLineStyle;
|
||||
}
|
||||
|
||||
// Adds the whitespace and closing char necessary to end a collection.
|
||||
void EndCollection(const char* aEndChar)
|
||||
{
|
||||
mDepth--;
|
||||
mWriter->Write("\n");
|
||||
Indent();
|
||||
if (mNeedNewlines[mDepth]) {
|
||||
mWriter->Write("\n");
|
||||
mDepth--;
|
||||
Indent();
|
||||
} else {
|
||||
mDepth--;
|
||||
}
|
||||
mWriter->Write(aEndChar);
|
||||
}
|
||||
|
||||
@ -307,9 +343,10 @@ public:
|
||||
explicit JSONWriter(UniquePtr<JSONWriteFunc> aWriter)
|
||||
: mWriter(Move(aWriter))
|
||||
, mNeedComma()
|
||||
, mNeedNewlines()
|
||||
, mDepth(0)
|
||||
{
|
||||
NewCommaEntry();
|
||||
NewVectorEntries();
|
||||
}
|
||||
|
||||
// Returns the JSONWriteFunc passed in at creation, for temporary use. The
|
||||
@ -317,15 +354,18 @@ public:
|
||||
JSONWriteFunc* WriteFunc() const { return mWriter.get(); }
|
||||
|
||||
// For all the following functions, the "Prints:" comment indicates what the
|
||||
// basic output looks like. However, it doesn't indicate the indentation and
|
||||
// basic output looks like. However, it doesn't indicate the whitespace and
|
||||
// trailing commas, which are automatically added as required.
|
||||
//
|
||||
// All property names and string properties are escaped as necessary.
|
||||
|
||||
// Prints: {
|
||||
void Start() { StartCollection(nullptr, "{"); }
|
||||
void Start(CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartCollection(nullptr, "{", aStyle);
|
||||
}
|
||||
|
||||
// Prints: }\n
|
||||
// Prints: }
|
||||
void End() { EndCollection("}\n"); }
|
||||
|
||||
// Prints: "<aName>": null
|
||||
@ -396,19 +436,33 @@ public:
|
||||
void PointerElement(const void* aPtr) { PointerProperty(nullptr, aPtr); }
|
||||
|
||||
// Prints: "<aName>": [
|
||||
void StartArrayProperty(const char* aName) { StartCollection(aName, "["); }
|
||||
void StartArrayProperty(const char* aName,
|
||||
CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartCollection(aName, "[", aStyle);
|
||||
}
|
||||
|
||||
// Prints: [
|
||||
void StartArrayElement() { StartArrayProperty(nullptr); }
|
||||
void StartArrayElement(CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartArrayProperty(nullptr, aStyle);
|
||||
}
|
||||
|
||||
// Prints: ]
|
||||
void EndArray() { EndCollection("]"); }
|
||||
|
||||
// Prints: "<aName>": {
|
||||
void StartObjectProperty(const char* aName) { StartCollection(aName, "{"); }
|
||||
void StartObjectProperty(const char* aName,
|
||||
CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartCollection(aName, "{", aStyle);
|
||||
}
|
||||
|
||||
// Prints: {
|
||||
void StartObjectElement() { StartObjectProperty(nullptr); }
|
||||
void StartObjectElement(CollectionStyle aStyle = MultiLineStyle)
|
||||
{
|
||||
StartObjectProperty(nullptr, aStyle);
|
||||
}
|
||||
|
||||
// Prints: }
|
||||
void EndObject() { EndCollection("}"); }
|
||||
|
@ -73,20 +73,23 @@ void TestBasicProperties()
|
||||
\"ptr1\": \"0x0\",\n\
|
||||
\"ptr2\": \"0xdeadbeef\",\n\
|
||||
\"ptr3\": \"0xfacade\",\n\
|
||||
\"len 0 array\": [\n\
|
||||
\"len 0 array, multi-line\": [\n\
|
||||
],\n\
|
||||
\"len 0 array, single-line\": [],\n\
|
||||
\"len 1 array\": [\n\
|
||||
1\n\
|
||||
],\n\
|
||||
\"len 5 array\": [\n\
|
||||
\"len 5 array, multi-line\": [\n\
|
||||
1,\n\
|
||||
2,\n\
|
||||
3,\n\
|
||||
4,\n\
|
||||
5\n\
|
||||
],\n\
|
||||
\"len 0 object\": {\n\
|
||||
\"len 3 array, single-line\": [1, [{}, 2, []], 3],\n\
|
||||
\"len 0 object, multi-line\": {\n\
|
||||
},\n\
|
||||
\"len 0 object, single-line\": {},\n\
|
||||
\"len 1 object\": {\n\
|
||||
\"one\": 1\n\
|
||||
},\n\
|
||||
@ -96,7 +99,8 @@ void TestBasicProperties()
|
||||
\"three\": 3,\n\
|
||||
\"four\": 4,\n\
|
||||
\"five\": 5\n\
|
||||
}\n\
|
||||
},\n\
|
||||
\"len 3 object, single-line\": {\"a\": 1, \"b\": [{}, 2, []], \"c\": 3}\n\
|
||||
}\n\
|
||||
";
|
||||
|
||||
@ -127,7 +131,10 @@ void TestBasicProperties()
|
||||
w.PointerProperty("ptr2", (void*)0xdeadbeef);
|
||||
w.PointerProperty("ptr3", (void*)0xFaCaDe);
|
||||
|
||||
w.StartArrayProperty("len 0 array");
|
||||
w.StartArrayProperty("len 0 array, multi-line", w.MultiLineStyle);
|
||||
w.EndArray();
|
||||
|
||||
w.StartArrayProperty("len 0 array, single-line", w.SingleLineStyle);
|
||||
w.EndArray();
|
||||
|
||||
w.StartArrayProperty("len 1 array");
|
||||
@ -136,7 +143,7 @@ void TestBasicProperties()
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.StartArrayProperty("len 5 array");
|
||||
w.StartArrayProperty("len 5 array, multi-line", w.MultiLineStyle);
|
||||
{
|
||||
w.IntElement(1);
|
||||
w.IntElement(2);
|
||||
@ -146,7 +153,28 @@ void TestBasicProperties()
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.StartObjectProperty("len 0 object");
|
||||
w.StartArrayProperty("len 3 array, single-line", w.SingleLineStyle);
|
||||
{
|
||||
w.IntElement(1);
|
||||
w.StartArrayElement();
|
||||
{
|
||||
w.StartObjectElement(w.SingleLineStyle);
|
||||
w.EndObject();
|
||||
|
||||
w.IntElement(2);
|
||||
|
||||
w.StartArrayElement(w.MultiLineStyle); // style overridden from above
|
||||
w.EndArray();
|
||||
}
|
||||
w.EndArray();
|
||||
w.IntElement(3);
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.StartObjectProperty("len 0 object, multi-line");
|
||||
w.EndObject();
|
||||
|
||||
w.StartObjectProperty("len 0 object, single-line", w.SingleLineStyle);
|
||||
w.EndObject();
|
||||
|
||||
w.StartObjectProperty("len 1 object");
|
||||
@ -164,6 +192,24 @@ void TestBasicProperties()
|
||||
w.IntProperty("five", 5);
|
||||
}
|
||||
w.EndObject();
|
||||
|
||||
w.StartObjectProperty("len 3 object, single-line", w.SingleLineStyle);
|
||||
{
|
||||
w.IntProperty("a", 1);
|
||||
w.StartArrayProperty("b");
|
||||
{
|
||||
w.StartObjectElement();
|
||||
w.EndObject();
|
||||
|
||||
w.IntElement(2);
|
||||
|
||||
w.StartArrayElement(w.SingleLineStyle);
|
||||
w.EndArray();
|
||||
}
|
||||
w.EndArray();
|
||||
w.IntProperty("c", 3);
|
||||
}
|
||||
w.EndObject();
|
||||
}
|
||||
w.End();
|
||||
|
||||
@ -194,6 +240,7 @@ void TestBasicElements()
|
||||
\"0xfacade\",\n\
|
||||
[\n\
|
||||
],\n\
|
||||
[],\n\
|
||||
[\n\
|
||||
1\n\
|
||||
],\n\
|
||||
@ -204,8 +251,10 @@ void TestBasicElements()
|
||||
4,\n\
|
||||
5\n\
|
||||
],\n\
|
||||
[1, [{}, 2, []], 3],\n\
|
||||
{\n\
|
||||
},\n\
|
||||
{},\n\
|
||||
{\n\
|
||||
\"one\": 1\n\
|
||||
},\n\
|
||||
@ -215,7 +264,8 @@ void TestBasicElements()
|
||||
\"three\": 3,\n\
|
||||
\"four\": 4,\n\
|
||||
\"five\": 5\n\
|
||||
}\n\
|
||||
},\n\
|
||||
{\"a\": 1, \"b\": [{}, 2, []], \"c\": 3}\n\
|
||||
]\n\
|
||||
}\n\
|
||||
";
|
||||
@ -251,6 +301,9 @@ void TestBasicElements()
|
||||
w.StartArrayElement();
|
||||
w.EndArray();
|
||||
|
||||
w.StartArrayElement(w.SingleLineStyle);
|
||||
w.EndArray();
|
||||
|
||||
w.StartArrayElement();
|
||||
{
|
||||
w.IntElement(1);
|
||||
@ -267,9 +320,30 @@ void TestBasicElements()
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.StartArrayElement(w.SingleLineStyle);
|
||||
{
|
||||
w.IntElement(1);
|
||||
w.StartArrayElement();
|
||||
{
|
||||
w.StartObjectElement(w.SingleLineStyle);
|
||||
w.EndObject();
|
||||
|
||||
w.IntElement(2);
|
||||
|
||||
w.StartArrayElement(w.MultiLineStyle); // style overridden from above
|
||||
w.EndArray();
|
||||
}
|
||||
w.EndArray();
|
||||
w.IntElement(3);
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.StartObjectElement();
|
||||
w.EndObject();
|
||||
|
||||
w.StartObjectElement(w.SingleLineStyle);
|
||||
w.EndObject();
|
||||
|
||||
w.StartObjectElement();
|
||||
{
|
||||
w.IntProperty("one", 1);
|
||||
@ -285,6 +359,24 @@ void TestBasicElements()
|
||||
w.IntProperty("five", 5);
|
||||
}
|
||||
w.EndObject();
|
||||
|
||||
w.StartObjectElement(w.SingleLineStyle);
|
||||
{
|
||||
w.IntProperty("a", 1);
|
||||
w.StartArrayProperty("b");
|
||||
{
|
||||
w.StartObjectElement();
|
||||
w.EndObject();
|
||||
|
||||
w.IntElement(2);
|
||||
|
||||
w.StartArrayElement(w.SingleLineStyle);
|
||||
w.EndArray();
|
||||
}
|
||||
w.EndArray();
|
||||
w.IntProperty("c", 3);
|
||||
}
|
||||
w.EndObject();
|
||||
}
|
||||
w.EndArray();
|
||||
w.End();
|
||||
@ -292,6 +384,47 @@ void TestBasicElements()
|
||||
Check(w.WriteFunc(), expected);
|
||||
}
|
||||
|
||||
void TestOneLineObject()
|
||||
{
|
||||
const char* expected = "\
|
||||
{\"i\": 1, \"array\": [null, [{}], {\"o\": {}}, \"s\"], \"d\": 3.33}\n\
|
||||
";
|
||||
|
||||
JSONWriter w(MakeUnique<StringWriteFunc>());
|
||||
|
||||
w.Start(w.SingleLineStyle);
|
||||
|
||||
w.IntProperty("i", 1);
|
||||
|
||||
w.StartArrayProperty("array");
|
||||
{
|
||||
w.NullElement();
|
||||
|
||||
w.StartArrayElement(w.MultiLineStyle); // style overridden from above
|
||||
{
|
||||
w.StartObjectElement();
|
||||
w.EndObject();
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.StartObjectElement();
|
||||
{
|
||||
w.StartObjectProperty("o");
|
||||
w.EndObject();
|
||||
}
|
||||
w.EndObject();
|
||||
|
||||
w.StringElement("s");
|
||||
}
|
||||
w.EndArray();
|
||||
|
||||
w.DoubleProperty("d", 3.33);
|
||||
|
||||
w.End();
|
||||
|
||||
Check(w.WriteFunc(), expected);
|
||||
}
|
||||
|
||||
void TestStringEscaping()
|
||||
{
|
||||
// This test uses hexadecimal character escapes because UTF8 literals cause
|
||||
@ -412,6 +545,7 @@ int main(void)
|
||||
{
|
||||
TestBasicProperties();
|
||||
TestBasicElements();
|
||||
TestOneLineObject();
|
||||
TestStringEscaping();
|
||||
TestDeepNesting();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user