2010-01-20 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / System.Json / System.Json / JsonObject.cs
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.IO;
6 using System.Text;
7
8 using JsonPair = System.Collections.Generic.KeyValuePair<string, System.Json.JsonValue>;
9 using JsonPairEnumerable = System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, System.Json.JsonValue>>;
10
11
12 namespace System.Json
13 {
14         public class JsonObject : JsonValue, IDictionary<string, JsonValue>, ICollection<KeyValuePair<string, JsonValue>>
15         {
16                 int known_count = -1;
17                 Dictionary<string, JsonValue> map;
18                 JsonPairEnumerable source;
19
20                 public JsonObject (params KeyValuePair<string, JsonValue> [] items)
21                         : this ((JsonPairEnumerable) items)
22                 {
23                 }
24
25                 public JsonObject (JsonPairEnumerable items)
26                 {
27                         if (items == null)
28                                 throw new ArgumentNullException ("items");
29                         this.source = items;
30                 }
31
32                 public override int Count {
33                         get {
34                                 if (known_count < 0) {
35                                         if (map != null)
36                                                 known_count = map.Count;
37                                         else {
38                                                 known_count = 0;
39                                                 foreach (JsonPair p in source)
40                                                         known_count++;
41                                         }
42                                 }
43                                 return known_count;
44                         }
45                 }
46
47                 public IEnumerator<JsonPair> GetEnumerator ()
48                 {
49                         return AsEnumerable ().GetEnumerator ();
50                 }
51
52                 IEnumerator IEnumerable.GetEnumerator ()
53                 {
54                         return AsEnumerable ().GetEnumerator ();
55                 }
56                         
57                 JsonPairEnumerable AsEnumerable ()
58                 {
59                         return map ?? source;
60                 }
61
62                 public bool IsReadOnly {
63                         get { return false; }
64                 }
65
66                 bool ICollection<JsonPair>.IsReadOnly {
67                         get { return ((ICollection<JsonPair>) map).IsReadOnly; }
68                 }
69
70                 public override sealed JsonValue this [string key] {
71                         get {
72                                 foreach (JsonPair pair in AsEnumerable ())
73                                         if (pair.Key == key)
74                                                 return pair.Value;
75                                 throw new KeyNotFoundException (String.Format ("key '{0}' was not found.", key));
76                         }
77                         set {
78                                 PopulateMap ();
79                                 map [key] = value;
80                         }
81                 }
82
83                 public override JsonType JsonType {
84                         get { return JsonType.Object; }
85                 }
86
87                 public ICollection<string> Keys {
88                         get {
89                                 PopulateMap ();
90                                 return map.Keys;
91                         }
92                 }
93
94                 public ICollection<JsonValue> Values {
95                         get {
96                                 PopulateMap ();
97                                 return map.Values;
98                         }
99                 }
100
101                 public void Add (string key, JsonValue value)
102                 {
103                         if (key == null)
104                                 throw new ArgumentNullException ("key");
105                         if (value == null)
106                                 throw new ArgumentNullException ("value");
107                         PopulateMap ();
108                         map.Add (key, value);
109                 }
110
111                 public void Add (JsonPair pair)
112                 {
113                         Add (pair.Key, pair.Value);
114                 }
115
116                 public void AddRange (JsonPairEnumerable items)
117                 {
118                         if (items == null)
119                                 throw new ArgumentNullException ("items");
120                         source = new MergedEnumerable<JsonPair> (source, items);
121                         map = null;
122                 }
123
124                 public void AddRange (JsonPair [] items)
125                 {
126                         AddRange ((JsonPairEnumerable) items);
127                 }
128
129                 static readonly JsonPair [] empty = new JsonPair [0];
130
131                 public void Clear ()
132                 {
133                         if (map != null)
134                                 map.Clear ();
135                         else
136                                 source = empty;
137                 }
138
139                 bool ICollection<JsonPair>.Contains (JsonPair item)
140                 {
141                         return ContainsKey (item.Key);
142                 }
143
144                 public override bool ContainsKey (string key)
145                 {
146                         if (key == null)
147                                 throw new ArgumentNullException ("key");
148                         foreach (JsonPair p in AsEnumerable ())
149                                 if (p.Key == key)
150                                         return true;
151                         return false;
152                 }
153
154                 public void CopyTo (JsonPair [] array, int arrayIndex)
155                 {
156                         foreach (JsonPair p in AsEnumerable ())
157                                 array [arrayIndex++] = p;
158                 }
159
160                 public bool Remove (string key)
161                 {
162                         PopulateMap ();
163                         return map.Remove (key);
164                 }
165
166                 bool ICollection<JsonPair>.Remove (JsonPair item)
167                 {
168                         return ((ICollection<JsonPair>) map).Remove (item);
169                 }
170
171                 public override void Save (Stream stream)
172                 {
173                         if (stream == null)
174                                 throw new ArgumentNullException ("stream");
175                         stream.WriteByte ((byte) '{');
176                         foreach (JsonPair pair in this) {
177                                 stream.WriteByte ((byte) '"');
178                                 byte [] bytes = Encoding.UTF8.GetBytes (EscapeString (pair.Key));
179                                 stream.Write (bytes, 0, bytes.Length);
180                                 stream.WriteByte ((byte) '"');
181                                 stream.WriteByte ((byte) ',');
182                                 stream.WriteByte ((byte) ' ');
183                                 pair.Value.Save (stream);
184                         }
185                         stream.WriteByte ((byte) '}');
186                 }
187
188                 public bool TryGetValue (string key, out JsonValue value)
189                 {
190                         foreach (JsonPair p in AsEnumerable ())
191                                 if (p.Key == key) {
192                                         value = p.Value;
193                                         return true;
194                                 }
195                         value = null;
196                         return false;
197                 }
198
199                 void PopulateMap ()
200                 {
201                         if (map == null) {
202                                 map = new Dictionary<string, JsonValue> ();
203                                 foreach (JsonPair pair in source)
204                                         map.Add (pair.Key, pair.Value);
205                         }
206                 }
207         }
208 }