Skip to content

Commit a5df8b8

Browse files
authored
Clone method added. Changelog extracted
Added Clone() method to allow cloning of a whole node tree. Extracted the changelog into a seperate Changelog.txt file
1 parent 07b1b17 commit a5df8b8

File tree

1 file changed

+56
-99
lines changed

1 file changed

+56
-99
lines changed

SimpleJSON.cs

Lines changed: 56 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -8,104 +8,11 @@
88
* Written by Bunny83
99
* 2012-06-09
1010
*
11-
* [2012-06-09 First Version]
12-
* - provides strongly typed node classes and lists / dictionaries
13-
* - provides easy access to class members / array items / data values
14-
* - the parser now properly identifies types. So generating JSON with this framework should work.
15-
* - only double quotes (") are used for quoting strings.
16-
* - provides "casting" properties to easily convert to / from those types:
17-
* int / float / double / bool
18-
* - provides a common interface for each node so no explicit casting is required.
19-
* - the parser tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined
20-
* - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might
21-
* be handy if you want to store things in a file and don't want it to be easily modifiable
22-
*
23-
* [2012-12-17 Update]
24-
* - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
25-
* Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
26-
* The class determines the required type by it's further use, creates the type and removes itself.
27-
* - Added binary serialization / deserialization.
28-
* - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
29-
* The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
30-
* - The serializer uses different types when it comes to store the values. Since my data values
31-
* are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
32-
* It's not the most efficient way but for a moderate amount of data it should work on all platforms.
33-
*
34-
* [2017-03-08 Update]
35-
* - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large
36-
* string data fields are contained in the json data.
37-
* - Finally refactored the badly named JSONClass into JSONObject.
38-
* - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this
39-
* allows to propertly convert the node tree back to json without type information loss. The actual value
40-
* parsing now happens at parsing time and not when you actually access one of the casting properties.
41-
*
42-
* [2017-04-11 Update]
43-
* - Fixed parsing bug where empty string values have been ignored.
44-
* - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files
45-
* - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)"
46-
*
47-
* [2017-11-29 Update]
48-
* - Removed the IEnumerator implementations on JSONArray & JSONObject and replaced it with a common
49-
* struct Enumerator in JSONNode that should avoid garbage generation. The enumerator always works
50-
* on KeyValuePair<string, JSONNode>, even for JSONArray.
51-
* - Added two wrapper Enumerators that allows for easy key or value enumeration. A JSONNode now has
52-
* a "Keys" and a "Values" enumerable property. Those are also struct enumerators / enumerables
53-
* - A KeyValuePair<string, JSONNode> can now be implicitly converted into a JSONNode. This allows
54-
* a foreach loop over a JSONNode to directly access the values only. Since KeyValuePair as well as
55-
* all the Enumerators are structs, no garbage is allocated.
56-
* - To add Linq support another "LinqEnumerator" is available through the "Linq" property. This
57-
* enumerator does implement the generic IEnumerable interface so most Linq extensions can be used
58-
* on this enumerable object. This one does allocate memory as it's a wrapper class.
59-
* - The Escape method now escapes all control characters (# < 32) in strings as uncode characters
60-
* (\uXXXX) and if the static bool JSONNode.forceASCII is set to true it will also escape all
61-
* characters # > 127. This might be useful if you require an ASCII output. Though keep in mind
62-
* when your strings contain many non-ascii characters the strings become much longer (x6) and are
63-
* no longer human readable.
64-
* - The node types JSONObject and JSONArray now have an "Inline" boolean switch which will default to
65-
* false. It can be used to serialize this element inline even you serialize with an indented format
66-
* This is useful for arrays containing numbers so it doesn't place every number on a new line
67-
* - Extracted the binary serialization code into a seperate extension file. All classes are now declared
68-
* as "partial" so an extension file can even add a new virtual or abstract method / interface to
69-
* JSONNode and override it in the concrete type classes. It's of course a hacky approach which is
70-
* generally not recommended, but i wanted to keep everything tightly packed.
71-
* - Added a static CreateOrGet method to the JSONNull class. Since this class is immutable it could
72-
* be reused without major problems. If you have a lot null fields in your data it will help reduce
73-
* the memory / garbage overhead. I also added a static setting (reuseSameInstance) to JSONNull
74-
* (default is true) which will change the behaviour of "CreateOrGet". If you set this to false
75-
* CreateOrGet will not reuse the cached instance but instead create a new JSONNull instance each time.
76-
* I made the JSONNull constructor private so if you need to create an instance manually use
77-
* JSONNull.CreateOrGet()
78-
*
79-
* [2018-01-09 Update]
80-
* - Changed all double.TryParse and double.ToString uses to use the invariant culture to avoid problems
81-
* on systems with a culture that uses a comma as decimal point.
82-
*
83-
* [2018-01-26 Update]
84-
* - Added AsLong. Note that a JSONNumber is stored as double and can't represent all long values. However
85-
* storing it as string would work.
86-
* - Added static setting "JSONNode.longAsString" which controls the default type that is used by the
87-
* LazyCreator when using AsLong
88-
*
89-
* [2018-04-25 Update]
90-
* - Added support for parsing single values (JSONBool, JSONString, JSONNumber, JSONNull) as top level value.
91-
*
92-
* [2019-02-18 Update]
93-
* - Added HasKey(key) and GetValueOrDefault(key, default) to the JSONNode class to provide way to read
94-
* values conditionally without creating a LazyCreator
95-
*
96-
* [2019-03-25 Update]
97-
* - Added static setting "allowLineComments" to the JSONNode class which is true by default. This allows
98-
* "//" line comments when parsing json text as long as it's not within quoted text. All text after // up
99-
* to the end of the line is completely ignored / skipped. This makes it easier to create human readable
100-
* and editable files. Note that stripped comments are not read, processed or preserved in any way. So
101-
* this feature is only relevant for human created files.
102-
* - Explicitly strip BOM (Byte Order Mark) when parsing to avoid getting it leaked into a single primitive
103-
* value. That's a rare case but better safe than sorry.
104-
* - Allowing adding the empty string as key
11+
* Changelog now external. See Changelog.txt
10512
*
10613
* The MIT License (MIT)
10714
*
108-
* Copyright (c) 2012-2017 Markus Göbel (Bunny83)
15+
* Copyright (c) 2012-2019 Markus Göbel (Bunny83)
10916
*
11017
* Permission is hereby granted, free of charge, to any person obtaining a copy
11118
* of this software and associated documentation files (the "Software"), to deal
@@ -176,7 +83,8 @@ public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
17683
}
17784
public KeyValuePair<string, JSONNode> Current
17885
{
179-
get {
86+
get
87+
{
18088
if (type == Type.Array)
18189
return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
18290
else if (type == Type.Object)
@@ -301,6 +209,11 @@ public virtual JSONNode Remove(JSONNode aNode)
301209
return aNode;
302210
}
303211

212+
public virtual JSONNode Clone()
213+
{
214+
return null;
215+
}
216+
304217
public virtual IEnumerable<JSONNode> Children
305218
{
306219
get
@@ -359,7 +272,7 @@ public virtual double AsDouble
359272
get
360273
{
361274
double v = 0.0;
362-
if (double.TryParse(Value,NumberStyles.Float, CultureInfo.InvariantCulture, out v))
275+
if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out v))
363276
return v;
364277
return 0.0;
365278
}
@@ -525,7 +438,8 @@ public override int GetHashCode()
525438
private static StringBuilder m_EscapeBuilder;
526439
internal static StringBuilder EscapeBuilder
527440
{
528-
get {
441+
get
442+
{
529443
if (m_EscapeBuilder == null)
530444
m_EscapeBuilder = new StringBuilder();
531445
return m_EscapeBuilder;
@@ -739,7 +653,7 @@ public static JSONNode Parse(string aJSON)
739653
}
740654
break;
741655
case '/':
742-
if (allowLineComments && !QuoteMode && i + 1 < aJSON.Length && aJSON[i+1] == '/')
656+
if (allowLineComments && !QuoteMode && i + 1 < aJSON.Length && aJSON[i + 1] == '/')
743657
{
744658
while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r') ;
745659
break;
@@ -838,6 +752,20 @@ public override JSONNode Remove(JSONNode aNode)
838752
return aNode;
839753
}
840754

755+
public override JSONNode Clone()
756+
{
757+
var node = new JSONArray();
758+
node.m_List.Capacity = m_List.Capacity;
759+
foreach(var n in m_List)
760+
{
761+
if (n != null)
762+
node.Add(n.Clone());
763+
else
764+
node.Add(null);
765+
}
766+
return node;
767+
}
768+
841769
public override IEnumerable<JSONNode> Children
842770
{
843771
get
@@ -981,6 +909,16 @@ public override JSONNode Remove(JSONNode aNode)
981909
}
982910
}
983911

912+
public override JSONNode Clone()
913+
{
914+
var node = new JSONObject();
915+
foreach (var n in m_Dict)
916+
{
917+
node.Add(n.Key, n.Value.Clone());
918+
}
919+
return node;
920+
}
921+
984922
public override bool HasKey(string aKey)
985923
{
986924
return m_Dict.ContainsKey(aKey);
@@ -1056,6 +994,10 @@ public JSONString(string aData)
1056994
{
1057995
m_Data = aData;
1058996
}
997+
public override JSONNode Clone()
998+
{
999+
return new JSONString(m_Data);
1000+
}
10591001

10601002
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
10611003
{
@@ -1120,6 +1062,11 @@ public JSONNumber(string aData)
11201062
Value = aData;
11211063
}
11221064

1065+
public override JSONNode Clone()
1066+
{
1067+
return new JSONNumber(m_Data);
1068+
}
1069+
11231070
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
11241071
{
11251072
aSB.Append(Value);
@@ -1187,6 +1134,11 @@ public JSONBool(string aData)
11871134
Value = aData;
11881135
}
11891136

1137+
public override JSONNode Clone()
1138+
{
1139+
return new JSONBool(m_Data);
1140+
}
1141+
11901142
internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
11911143
{
11921144
aSB.Append((m_Data) ? "true" : "false");
@@ -1233,6 +1185,11 @@ public override bool AsBool
12331185
set { }
12341186
}
12351187

1188+
public override JSONNode Clone()
1189+
{
1190+
return CreateOrGet();
1191+
}
1192+
12361193
public override bool Equals(object obj)
12371194
{
12381195
if (object.ReferenceEquals(this, obj))

0 commit comments

Comments
 (0)