2008-09-15 Atsushi Enomoto <atsushi@ximian.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                 JsonPairEnumerable AsEnumerable ()
53                 {
54                         return map ?? source;
55                 }
56
57                 public bool IsReadOnly {
58                         get { return false; }
59                 }
60
61                 bool ICollection<JsonPair>.IsReadOnly {
62                         get { return ((ICollection<JsonPair>) map).IsReadOnly; }
63                 }
64
65                 public override sealed JsonValue this [string key] {
66                         get {
67                                 foreach (JsonPair pair in AsEnumerable ())
68                                         if (pair.Key == key)
69                                                 return pair.Value;
70                                 throw new KeyNotFoundException (String.Format ("key '{0}' was not found.", key));
71                         }
72                         set {
73                                 PopulateMap ();
74                                 map [key] = value;
75                         }
76                 }
77
78                 public override JsonType JsonType {
79                         get { return JsonType.Object; }
80                 }
81
82                 public ICollection<string> Keys {
83                         get {
84                                 PopulateMap ();
85                                 return map.Keys;
86                         }
87                 }
88
89                 public ICollection<JsonValue> Values {
90                         get {
91                                 PopulateMap ();
92                                 return map.Values;
93                         }
94                 }
95
96                 public void Add (string key, JsonValue value)
97                 {
98                         if (key == null)
99                                 throw new ArgumentNullException ("key");
100                         if (value == null)
101                                 throw new ArgumentNullException ("value");
102                         PopulateMap ();
103                         map.Add (key, value);
104                 }
105
106                 public void Add (JsonPair pair)
107                 {
108                         Add (pair.Key, pair.Value);
109                 }
110
111                 public void AddRange (JsonPairEnumerable items)
112                 {
113                         if (items == null)
114                                 throw new ArgumentNullException ("items");
115                         source = new MergedEnumerable<JsonPair> (source, items);
116                         map = null;
117                 }
118
119                 public void AddRange (JsonPair [] items)
120                 {
121                         AddRange ((JsonPairEnumerable) items);
122                 }
123
124                 static readonly JsonPair [] empty = new JsonPair [0];
125
126                 public void Clear ()
127                 {
128                         if (map != null)
129                                 map.Clear ();
130                         else
131                                 source = empty;
132                 }
133
134                 bool ICollection<JsonPair>.Contains (JsonPair item)
135                 {
136                         return ContainsKey (item.Key);
137                 }
138
139                 public override bool ContainsKey (string key)
140                 {
141                         if (key == null)
142                                 throw new ArgumentNullException ("key");
143                         foreach (JsonPair p in AsEnumerable ())
144                                 if (p.Key == key)
145                                         return true;
146                         return false;
147                 }
148
149                 public void CopyTo (JsonPair [] array, int arrayIndex)
150                 {
151                         foreach (JsonPair p in AsEnumerable ())
152                                 array [arrayIndex++] = p;
153                 }
154
155                 public bool Remove (string key)
156                 {
157                         PopulateMap ();
158                         return map.Remove (key);
159                 }
160
161                 bool ICollection<JsonPair>.Remove (JsonPair item)
162                 {
163                         return ((ICollection<JsonPair>) map).Remove (item);
164                 }
165
166                 public override void Save (Stream stream)
167                 {
168                         if (stream == null)
169                                 throw new ArgumentNullException ("stream");
170                         stream.WriteByte ((byte) '{');
171                         foreach (JsonPair pair in this) {
172                                 stream.WriteByte ((byte) '"');
173                                 byte [] bytes = Encoding.UTF8.GetBytes (EscapeString (pair.Key));
174                                 stream.Write (bytes, 0, bytes.Length);
175                                 stream.WriteByte ((byte) '"');
176                                 stream.WriteByte ((byte) ',');
177                                 stream.WriteByte ((byte) ' ');
178                                 pair.Value.Save (stream);
179                         }
180                         stream.WriteByte ((byte) '}');
181                 }
182
183                 public bool TryGetValue (string key, out JsonValue value)
184                 {
185                         foreach (JsonPair p in AsEnumerable ())
186                                 if (p.Key == key) {
187                                         value = p.Value;
188                                         return true;
189                                 }
190                         value = null;
191                         return false;
192                 }
193
194                 void PopulateMap ()
195                 {
196                         if (map == null) {
197                                 map = new Dictionary<string, JsonValue> ();
198                                 foreach (JsonPair pair in source)
199                                         map.Add (pair.Key, pair.Value);
200                         }
201                 }
202         }
203 }