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