initial checkin. New assembly in Silverlight 2.0 beta 2.
[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                 public override sealed JsonValue this [string key] {
62                         get {
63                                 foreach (JsonPair pair in AsEnumerable ())
64                                         if (pair.Key == key)
65                                                 return pair.Value;
66                                 throw new KeyNotFoundException (String.Format ("key '{0}' was not found.", key));
67                         }
68                         set {
69                                 PopulateMap ();
70                                 map [key] = value;
71                         }
72                 }
73
74                 public override JsonType JsonType {
75                         get { return JsonType.Object; }
76                 }
77
78                 public IEnumerable<string> Keys {
79                         get {
80                                 foreach (JsonPair pair in AsEnumerable ())
81                                         yield return pair.Key;
82                         }
83                 }
84
85                 public IEnumerable<JsonValue> Values {
86                         get {
87                                 foreach (JsonPair pair in AsEnumerable ())
88                                         yield return pair.Value;
89                         }
90                 }
91
92                 public void Add (string key, JsonValue value)
93                 {
94                         if (key == null)
95                                 throw new ArgumentNullException ("key");
96                         if (value == null)
97                                 throw new ArgumentNullException ("value");
98                         PopulateMap ();
99                         map.Add (key, value);
100                 }
101
102                 public void Add (JsonPair pair)
103                 {
104                         Add (pair.Key, pair.Value);
105                 }
106
107                 public void AddRange (JsonPairEnumerable items)
108                 {
109                         if (items == null)
110                                 throw new ArgumentNullException ("items");
111                         source = new MergedEnumerable<JsonPair> (source, items);
112                         map = null;
113                 }
114
115                 public void AddRange (JsonPair [] items)
116                 {
117                         AddRange ((JsonPairEnumerable) items);
118                 }
119
120                 static readonly JsonPair [] empty = new JsonPair [0];
121
122                 public void Clear ()
123                 {
124                         if (map != null)
125                                 map.Clear ();
126                         else
127                                 source = empty;
128                 }
129
130                 public override bool ContainsKey (string key)
131                 {
132                         if (key == null)
133                                 throw new ArgumentNullException ("key");
134                         foreach (string k in Keys)
135                                 if (k == key)
136                                         return true;
137                         return false;
138                 }
139
140                 public void CopyTo (JsonPair [] array, int arrayIndex)
141                 {
142                         foreach (JsonPair p in AsEnumerable ())
143                                 array [arrayIndex++] = p;
144                 }
145
146                 public void Remove (string key)
147                 {
148                         PopulateMap ();
149                         map.Remove (key);
150                 }
151
152                 public override void Save (Stream stream)
153                 {
154                         if (stream == null)
155                                 throw new ArgumentNullException ("stream");
156                         stream.WriteByte ((byte) '{');
157                         foreach (JsonPair pair in this) {
158                                 stream.WriteByte ((byte) '"');
159                                 byte [] bytes = Encoding.UTF8.GetBytes (EscapeString (pair.Key));
160                                 stream.Write (bytes, 0, bytes.Length);
161                                 stream.WriteByte ((byte) '"');
162                                 stream.WriteByte ((byte) ',');
163                                 stream.WriteByte ((byte) ' ');
164                                 pair.Value.Save (stream);
165                         }
166                         stream.WriteByte ((byte) '}');
167                 }
168
169                 void PopulateMap ()
170                 {
171                         if (map == null) {
172                                 map = new Dictionary<string, JsonValue> ();
173                                 foreach (JsonPair pair in source)
174                                         map.Add (pair.Key, pair.Value);
175                         }
176                 }
177         }
178 }