ScriptStack 1.0.5
Loading...
Searching...
No Matches
ArrayList.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading;
5using System.Globalization;
6
8{
9
10 public class ArrayList : Dictionary<object, object>
11 {
12
13 #region Private Methods
14
15 private void OutputValue(StringBuilder stringBuilder, object objectValue)
16 {
17
18 if (objectValue.GetType() != typeof(ArrayList))
19 stringBuilder.Append("\"" + objectValue + "\"");
20
21 else
22 stringBuilder.Append(objectValue);
23
24 return;
25
26 }
27
28 private bool EqualValues(object objectValue1, object objectValue2)
29 {
30
31 Type type1 = objectValue1.GetType();
32
33 Type type2 = objectValue2.GetType();
34
35 if (type1 == typeof(int) && type2 == typeof(int))
36 return (int)objectValue1 == (int)objectValue2;
37
38 else if (type1 == typeof(int) && type2 == typeof(float))
39 return (int)objectValue1 == (float)objectValue2;
40
41 else if (type1 == typeof(float) && type2 == typeof(int))
42 return (float)objectValue1 == (int)objectValue2;
43
44 else if (type1 == typeof(float) && type2 == typeof(float))
45 return (float)objectValue1 == (float)objectValue2;
46
47 else if (type1 == typeof(string) || type2 == typeof(string))
48 return objectValue1.ToString() == objectValue2.ToString();
49
50 else return objectValue1 == objectValue2;
51
52 }
53
54 private void AddValue(object objectValue)
55 {
56 int iIndex = 0;
57 while (ContainsKey(iIndex)) ++iIndex;
58 this[iIndex] = objectValue;
59 }
60
61 private void SubtractValue(object objectValue)
62 {
63 List<object> listValues = new List<object>();
64 foreach (object objectOldValue in Values)
65 {
66 if (!EqualValues(objectOldValue, objectValue)) listValues.Add(objectOldValue);
67 }
68 Clear();
69 int iIndex = 0;
70 foreach (object objectOldValue in listValues)
71 {
72 this[iIndex++] = objectOldValue;
73 }
74 }
75
76 private void AddArray(ArrayList assocativeArray)
77 {
78 int iIndex = 0;
79 while (ContainsKey(iIndex)) ++iIndex;
80 foreach (object objectValue in assocativeArray.Values)
81 {
82 this[iIndex++] = objectValue;
83 }
84 }
85
86 private void SubtractArray(ArrayList associativeArray)
87 {
88 foreach (object objectValue in associativeArray.Values)
89 SubtractValue(objectValue);
90 }
91
92 #endregion
93
94 #region Public Methods
95
96 public void Add(object objectValue)
97 {
98
99 if (objectValue.GetType() == typeof(ArrayList))
100 AddArray((ArrayList)objectValue);
101
102 else
103 AddValue(objectValue);
104
105 }
106
107 public void Subtract(object objectValue)
108 {
109
110 if (objectValue.GetType() == typeof(ArrayList))
111 SubtractArray((ArrayList)objectValue);
112
113 else SubtractValue(objectValue);
114
115 }
116
117 public override string ToString()
118 {
119 // We intentionally output JSON here, because ScriptStack's "string(x)" uses Convert.ToString(x)
120 // which calls ToString(). Arrays vs. objects are distinguished by their key-shape:
121 // - purely non-negative int keys => JSON array (supports sparse arrays)
122 // - otherwise => JSON object
123 var sb = new StringBuilder();
124 var stack = new HashSet<object>(ReferenceEqualityComparer.Instance);
125 WriteJsonValue(sb, this, stack);
126 return sb.ToString();
127 }
128
129 private static void WriteJsonValue(StringBuilder sb, object value, HashSet<object> stack)
130 {
131 if (value == null || value is NullReference)
132 {
133 sb.Append("null");
134 return;
135 }
136
137 if (value is ArrayList al)
138 {
139 WriteJsonArrayList(sb, al, stack);
140 return;
141 }
142
143 switch (Type.GetTypeCode(value.GetType()))
144 {
145 case TypeCode.Boolean:
146 sb.Append(((bool)value) ? "true" : "false");
147 return;
148 case TypeCode.String:
149 WriteJsonString(sb, (string)value);
150 return;
151 case TypeCode.Char:
152 WriteJsonString(sb, value.ToString());
153 return;
154 case TypeCode.Int16:
155 case TypeCode.Int32:
156 case TypeCode.Int64:
157 case TypeCode.UInt16:
158 case TypeCode.UInt32:
159 case TypeCode.UInt64:
160 case TypeCode.Single:
161 case TypeCode.Double:
162 case TypeCode.Decimal:
163 case TypeCode.SByte:
164 case TypeCode.Byte:
165 // JSON numbers must be culture-invariant.
166 sb.Append(Convert.ToString(value, CultureInfo.InvariantCulture));
167 return;
168 case TypeCode.DateTime:
169 // No dedicated JSON date type: emit as ISO-8601 string.
170 WriteJsonString(sb, ((DateTime)value).ToString("O", CultureInfo.InvariantCulture));
171 return;
172 default:
173 // Fallback: emit as string.
174 WriteJsonString(sb, value.ToString());
175 return;
176 }
177 }
178
179 private static void WriteJsonArrayList(StringBuilder sb, ArrayList al, HashSet<object> stack)
180 {
181 if (!stack.Add(al))
182 {
183 // Cyclic structure: represent as null to avoid infinite recursion.
184 sb.Append("null");
185 return;
186 }
187
188 // Detect "array" shape: all keys are non-negative int.
189 bool allIntKeys = true;
190 int maxIndex = -1;
191 foreach (var k in al.Keys)
192 {
193 if (k is int i && i >= 0)
194 {
195 if (i > maxIndex) maxIndex = i;
196 continue;
197 }
198
199 allIntKeys = false;
200 break;
201 }
202
203 if (allIntKeys)
204 {
205 sb.Append('[');
206 for (int i = 0; i <= maxIndex; i++)
207 {
208 if (i > 0) sb.Append(',');
209 if (al.TryGetValue(i, out var v))
210 WriteJsonValue(sb, v, stack);
211 else
212 sb.Append("null");
213 }
214 sb.Append(']');
215 }
216 else
217 {
218 sb.Append('{');
219 bool first = true;
220 foreach (var kv in al)
221 {
222 if (!first) sb.Append(',');
223 first = false;
224 WriteJsonString(sb, kv.Key?.ToString() ?? "null");
225 sb.Append(':');
226 WriteJsonValue(sb, kv.Value, stack);
227 }
228 sb.Append('}');
229 }
230
231 stack.Remove(al);
232 }
233
234 private static void WriteJsonString(StringBuilder sb, string s)
235 {
236 sb.Append('"');
237 if (s != null)
238 {
239 foreach (char c in s)
240 {
241 switch (c)
242 {
243 case '"': sb.Append("\\\""); break;
244 case '\\': sb.Append("\\\\"); break;
245 case '\b': sb.Append("\\b"); break;
246 case '\f': sb.Append("\\f"); break;
247 case '\n': sb.Append("\\n"); break;
248 case '\r': sb.Append("\\r"); break;
249 case '\t': sb.Append("\\t"); break;
250 default:
251 if (c < 0x20)
252 sb.Append("\\u" + ((int)c).ToString("x4"));
253 else
254 sb.Append(c);
255 break;
256 }
257 }
258 }
259 sb.Append('"');
260 }
261
265 private sealed class ReferenceEqualityComparer : IEqualityComparer<object>
266 {
268 public new bool Equals(object x, object y) => ReferenceEquals(x, y);
269 public int GetHashCode(object obj) => System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
270 }
271
272 #endregion
273
274 #region Public Properties
275
276 public new object this[object objectKey]
277 {
278
279 get
280 {
281
282 if (objectKey.GetType() == typeof(string) && ((string)objectKey) == "size")
283 return this.Count;
284
285 if (!ContainsKey(objectKey))
286 return NullReference.Instance;
287
288 return base[objectKey];
289
290 }
291 set
292 {
293
294 if (objectKey == null)
295 objectKey = NullReference.Instance;
296
297 if (objectKey.GetType() == typeof(string) && ((string)objectKey) == "size")
298 throw new ExecutionException("Der Member 'size' eines Arrays ist eine 'read-only' Eigenschaft.");
299
300 if (value == null)
301 base[objectKey] = NullReference.Instance;
302
303 else
304 base[objectKey] = value;
305
306 }
307
308 }
309
310 #endregion
311
312 }
313
314}
Reference equality comparer for cycle detection.
Definition ArrayList.cs:266
static readonly ReferenceEqualityComparer Instance
Definition ArrayList.cs:267
void SubtractArray(ArrayList associativeArray)
Definition ArrayList.cs:86
static void WriteJsonArrayList(StringBuilder sb, ArrayList al, HashSet< object > stack)
Definition ArrayList.cs:179
override string ToString()
Definition ArrayList.cs:117
void Subtract(object objectValue)
Definition ArrayList.cs:107
void AddValue(object objectValue)
Definition ArrayList.cs:54
void SubtractValue(object objectValue)
Definition ArrayList.cs:61
bool EqualValues(object objectValue1, object objectValue2)
Definition ArrayList.cs:28
void Add(object objectValue)
Definition ArrayList.cs:96
static void WriteJsonString(StringBuilder sb, string s)
Definition ArrayList.cs:234
static void WriteJsonValue(StringBuilder sb, object value, HashSet< object > stack)
Definition ArrayList.cs:129
void AddArray(ArrayList assocativeArray)
Definition ArrayList.cs:76
void OutputValue(StringBuilder stringBuilder, object objectValue)
Definition ArrayList.cs:15