Mercurial > pub > ImplabNet
annotate Implab/JSON/JSONWriter.cs @ 123:f4d6ea6969cc v2
async queue improvements
| author | cin |
|---|---|
| date | Tue, 13 Jan 2015 01:42:38 +0300 |
| parents | 2573b562e328 |
| children | 0fa293bb1351 |
| rev | line source |
|---|---|
| 55 | 1 using System; |
| 2 using System.Collections.Generic; | |
| 3 using System.IO; | |
| 4 | |
| 5 namespace Implab.JSON { | |
| 6 public class JSONWriter { | |
| 7 struct Context { | |
| 8 public bool needComma; | |
| 9 public JSONElementContext element; | |
| 10 } | |
| 11 Stack<Context> m_contextStack = new Stack<Context>(); | |
| 12 Context m_context; | |
| 13 | |
| 14 TextWriter m_writer; | |
| 72 | 15 readonly bool m_indent = true; |
| 16 readonly int m_indentSize = 4; | |
| 55 | 17 |
| 18 static readonly char [] _escapeBKS, | |
| 19 _escapeFWD, | |
| 20 _escapeCR, | |
| 21 _escapeNL, | |
| 22 _escapeTAB, | |
| 23 _escapeBSLASH, | |
| 24 _escapeQ; | |
| 25 | |
| 26 static JSONWriter() { | |
| 27 _escapeBKS = "\\b".ToCharArray(); | |
| 28 _escapeFWD = "\\f".ToCharArray(); | |
| 29 _escapeCR = "\\r".ToCharArray(); | |
| 30 _escapeNL = "\\n".ToCharArray(); | |
| 31 _escapeTAB = "\\t".ToCharArray(); | |
| 32 _escapeBSLASH = "\\\\".ToCharArray(); | |
| 33 _escapeQ = "\\\"".ToCharArray(); | |
| 34 } | |
| 35 | |
| 36 public JSONWriter(TextWriter writer) { | |
| 37 Safe.ArgumentNotNull(writer, "writer"); | |
| 38 | |
| 39 m_writer = writer; | |
| 40 } | |
| 41 | |
| 72 | 42 public JSONWriter(TextWriter writer, bool indent) { |
| 43 Safe.ArgumentNotNull(writer, "writer"); | |
| 44 | |
| 45 m_writer = writer; | |
| 46 m_indent = indent; | |
| 47 } | |
| 48 | |
| 49 void WriteIndent() { | |
| 50 if (m_indent) { | |
| 51 var indent = new char[m_contextStack.Count * m_indentSize + 1]; | |
| 52 indent[0] = '\n'; | |
| 53 for (int i = 1; i < indent.Length; i++) | |
| 54 indent[i] = ' '; | |
| 55 m_writer.Write(new String(indent)); | |
| 56 } else { | |
| 57 m_writer.Write(' '); | |
| 58 } | |
| 59 } | |
| 60 | |
| 55 | 61 void WriteMemberName(string name) { |
| 62 Safe.ArgumentNotEmpty(name, "name"); | |
| 63 if (m_context.element != JSONElementContext.Object) | |
| 64 OperationNotApplicable("WriteMember"); | |
| 65 if (m_context.needComma) | |
| 72 | 66 m_writer.Write(","); |
| 67 | |
| 68 WriteIndent(); | |
| 55 | 69 m_context.needComma = true; |
| 70 Write(name); | |
| 71 m_writer.Write(" : "); | |
| 72 } | |
| 73 | |
| 74 public void WriteValue(string name, string value) { | |
| 75 WriteMemberName(name); | |
| 76 Write(value); | |
| 77 } | |
| 78 | |
| 79 public void WriteValue(string name, bool value) { | |
| 80 WriteMemberName(name); | |
| 81 Write(value); | |
| 82 } | |
| 83 | |
| 84 public void WriteValue(string name, double value) { | |
| 85 WriteMemberName(name); | |
| 86 Write(value); | |
| 87 } | |
| 88 | |
| 89 public void WriteValue(string value) { | |
| 90 if (m_context.element != JSONElementContext.Array) | |
| 91 OperationNotApplicable("WriteValue"); | |
| 92 if (m_context.needComma) | |
| 72 | 93 m_writer.Write(","); |
| 94 WriteIndent(); | |
| 55 | 95 m_context.needComma = true; |
| 96 | |
| 97 Write(value); | |
| 98 } | |
| 99 | |
| 100 public void WriteValue(bool value) { | |
| 101 if (m_context.element != JSONElementContext.Array) | |
| 102 OperationNotApplicable("WriteValue"); | |
| 103 if (m_context.needComma) | |
| 72 | 104 m_writer.Write(","); |
| 55 | 105 m_context.needComma = true; |
| 106 | |
| 72 | 107 WriteIndent(); |
| 55 | 108 Write(value); |
| 109 } | |
| 110 | |
| 111 public void WriteValue(double value) { | |
| 112 if (m_context.element != JSONElementContext.Array) | |
| 113 OperationNotApplicable("WriteValue"); | |
| 114 if (m_context.needComma) | |
| 72 | 115 m_writer.Write(","); |
| 55 | 116 m_context.needComma = true; |
| 117 | |
| 72 | 118 WriteIndent(); |
| 55 | 119 Write(value); |
| 120 } | |
| 121 | |
| 122 public void BeginObject() { | |
| 123 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array) | |
| 124 OperationNotApplicable("BeginObject"); | |
| 125 if (m_context.needComma) | |
| 72 | 126 m_writer.Write(","); |
| 127 | |
| 128 WriteIndent(); | |
| 129 | |
| 55 | 130 m_context.needComma = true; |
| 131 | |
| 132 m_contextStack.Push(m_context); | |
| 133 | |
| 134 m_context = new Context { element = JSONElementContext.Object, needComma = false }; | |
| 72 | 135 m_writer.Write("{"); |
| 55 | 136 } |
| 137 | |
| 138 public void BeginObject(string name) { | |
| 139 WriteMemberName(name); | |
| 140 | |
| 141 m_contextStack.Push(m_context); | |
| 142 | |
| 143 m_context = new Context { element = JSONElementContext.Object, needComma = false }; | |
| 72 | 144 m_writer.Write("{"); |
| 55 | 145 } |
| 146 | |
| 147 public void EndObject() { | |
| 148 if (m_context.element != JSONElementContext.Object) | |
| 149 OperationNotApplicable("EndArray"); | |
| 72 | 150 |
| 55 | 151 m_context = m_contextStack.Pop(); |
| 72 | 152 WriteIndent(); |
| 153 m_writer.Write("}"); | |
| 55 | 154 } |
| 155 | |
| 156 public void BeginArray() { | |
| 157 if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array) | |
| 158 throw new InvalidOperationException(); | |
| 72 | 159 if (m_context.needComma) { |
| 160 m_writer.Write(","); | |
| 161 | |
| 162 } | |
| 55 | 163 m_context.needComma = true; |
| 164 | |
| 72 | 165 WriteIndent(); |
| 55 | 166 m_contextStack.Push(m_context); |
| 167 m_context = new Context { element = JSONElementContext.Array, needComma = false }; | |
| 72 | 168 m_writer.Write("["); |
| 55 | 169 } |
| 170 | |
| 171 public void BeginArray(string name) { | |
| 172 WriteMemberName(name); | |
| 173 | |
| 174 m_contextStack.Push(m_context); | |
| 175 | |
| 176 m_context = new Context { element = JSONElementContext.Array, needComma = false }; | |
| 72 | 177 m_writer.Write("["); |
| 55 | 178 } |
| 179 | |
| 180 public void EndArray() { | |
| 181 if (m_context.element != JSONElementContext.Array) | |
| 182 OperationNotApplicable("EndArray"); | |
| 183 | |
| 184 m_context = m_contextStack.Pop(); | |
| 72 | 185 WriteIndent(); |
| 186 m_writer.Write("]"); | |
| 55 | 187 } |
| 188 | |
| 189 void Write(bool value) { | |
| 190 m_writer.Write(value ? "true" : "false"); | |
| 191 } | |
| 192 | |
| 193 | |
| 194 void Write(string value) { | |
| 115 | 195 if (value == null) { |
| 55 | 196 m_writer.Write("null"); |
| 115 | 197 return; |
| 198 } | |
| 55 | 199 |
| 200 var chars = value.ToCharArray(); | |
| 201 m_writer.Write('"'); | |
| 202 | |
|
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
118
diff
changeset
|
203 // Analysis disable once ForCanBeConvertedToForeach |
| 55 | 204 for (int i = 0; i < chars.Length; i++) { |
| 205 var ch = chars[i]; | |
| 206 | |
| 207 switch (ch) { | |
| 208 case '\b': | |
| 209 m_writer.Write(_escapeBKS); | |
| 210 break; | |
| 211 case '\f': | |
| 212 m_writer.Write(_escapeFWD); | |
| 213 break; | |
| 214 case '\r': | |
| 215 m_writer.Write(_escapeCR); | |
| 216 break; | |
| 217 case '\n': | |
| 218 m_writer.Write(_escapeNL); | |
| 219 break; | |
| 220 case '\t': | |
| 221 m_writer.Write(_escapeTAB); | |
| 222 break; | |
| 223 case '\\': | |
| 224 m_writer.Write(_escapeBSLASH); | |
| 225 break; | |
| 226 case '"': | |
| 227 m_writer.Write(_escapeQ); | |
| 228 break; | |
| 229 default: | |
| 230 if (ch < 0x20) { | |
| 231 m_writer.Write("\\u00{0:x2}",(int)ch); | |
| 232 } else { | |
| 233 m_writer.Write(ch); | |
| 234 } | |
| 235 break; | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 m_writer.Write('"'); | |
| 240 } | |
| 241 | |
| 242 void Write(double value) { | |
| 243 m_writer.Write(value); | |
| 244 } | |
| 245 | |
| 246 void OperationNotApplicable(string opName) { | |
| 247 throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element )); | |
| 248 } | |
| 249 | |
| 250 } | |
| 251 } |
