csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 1 | using System;
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 2 | using System.Collections;
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 3 | using System.Collections.Generic;
|
| 4 | using System.IO;
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 5 | using System.Text;
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 6 | using Google.ProtocolBuffers.Descriptors;
|
| 7 |
|
| 8 | namespace Google.ProtocolBuffers.Serialization
|
| 9 | {
|
| 10 | /// <summary>
|
| 11 | /// JsonFormatWriter is a .NET 2.0 friendly json formatter for proto buffer messages. For .NET 3.5
|
| 12 | /// you may also use the XmlFormatWriter with an XmlWriter created by the
|
| 13 | /// <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory">JsonReaderWriterFactory</see>.
|
| 14 | /// </summary>
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 15 | public abstract class JsonFormatWriter : AbstractTextWriter
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 16 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 17 | #region buffering implementations
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 18 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 19 | private class JsonTextWriter : JsonFormatWriter
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 20 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 21 | private readonly char[] _buffer;
|
| 22 | private TextWriter _output;
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 23 | private int _bufferPos;
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 24 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 25 | public JsonTextWriter(TextWriter output)
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 26 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 27 | _buffer = new char[4096];
|
| 28 | _bufferPos = 0;
|
| 29 | _output = output;
|
| 30 | _counter.Add(0);
|
| 31 | }
|
| 32 |
|
| 33 | /// <summary>
|
| 34 | /// Returns the output of TextWriter.ToString() where TextWriter is the ctor argument.
|
| 35 | /// </summary>
|
| 36 | public override string ToString()
|
| 37 | {
|
| 38 | Flush();
|
| 39 |
|
| 40 | if (_output != null)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 41 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 42 | return _output.ToString();
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 43 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 44 |
|
| 45 | return new String(_buffer, 0, _bufferPos);
|
| 46 | }
|
| 47 |
|
| 48 | protected override void WriteToOutput(char[] chars, int offset, int len)
|
| 49 | {
|
| 50 | if (_bufferPos + len >= _buffer.Length)
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 51 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 52 | if (_output == null)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 53 | {
|
| 54 | _output = new StringWriter(new StringBuilder(_buffer.Length*2 + len));
|
| 55 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 56 | Flush();
|
| 57 | }
|
| 58 |
|
| 59 | if (len < _buffer.Length)
|
| 60 | {
|
| 61 | if (len <= 12)
|
| 62 | {
|
| 63 | int stop = offset + len;
|
| 64 | for (int i = offset; i < stop; i++)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 65 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 66 | _buffer[_bufferPos++] = chars[i];
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 67 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 68 | }
|
| 69 | else
|
| 70 | {
|
| 71 | Buffer.BlockCopy(chars, offset << 1, _buffer, _bufferPos << 1, len << 1);
|
| 72 | _bufferPos += len;
|
| 73 | }
|
| 74 | }
|
| 75 | else
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 76 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 77 | _output.Write(chars, offset, len);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 78 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 79 | }
|
| 80 |
|
| 81 | protected override void WriteToOutput(char ch)
|
| 82 | {
|
| 83 | if (_bufferPos >= _buffer.Length)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 84 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 85 | Flush();
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 86 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 87 | _buffer[_bufferPos++] = ch;
|
| 88 | }
|
| 89 |
|
| 90 | public override void Flush()
|
| 91 | {
|
| 92 | if (_bufferPos > 0 && _output != null)
|
| 93 | {
|
| 94 | _output.Write(_buffer, 0, _bufferPos);
|
| 95 | _bufferPos = 0;
|
| 96 | }
|
| 97 | base.Flush();
|
| 98 | }
|
| 99 | }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 100 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 101 | private class JsonStreamWriter : JsonFormatWriter
|
| 102 | {
|
| 103 | #if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
|
| 104 | static readonly Encoding Encoding = Encoding.UTF8;
|
| 105 | #else
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 106 | private static readonly Encoding Encoding = Encoding.ASCII;
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 107 | #endif
|
| 108 | private readonly byte[] _buffer;
|
| 109 | private Stream _output;
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 110 | private int _bufferPos;
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 111 |
|
| 112 | public JsonStreamWriter(Stream output)
|
| 113 | {
|
| 114 | _buffer = new byte[8192];
|
| 115 | _bufferPos = 0;
|
| 116 | _output = output;
|
| 117 | _counter.Add(0);
|
| 118 | }
|
| 119 |
|
| 120 | protected override void WriteToOutput(char[] chars, int offset, int len)
|
| 121 | {
|
| 122 | if (_bufferPos + len >= _buffer.Length)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 123 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 124 | Flush();
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 125 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 126 |
|
| 127 | if (len < _buffer.Length)
|
| 128 | {
|
| 129 | if (len <= 12)
|
| 130 | {
|
| 131 | int stop = offset + len;
|
| 132 | for (int i = offset; i < stop; i++)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 133 | {
|
| 134 | _buffer[_bufferPos++] = (byte) chars[i];
|
| 135 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 136 | }
|
| 137 | else
|
| 138 | {
|
| 139 | _bufferPos += Encoding.GetBytes(chars, offset, len, _buffer, _bufferPos);
|
| 140 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 141 | }
|
| 142 | else
|
| 143 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 144 | byte[] temp = Encoding.GetBytes(chars, offset, len);
|
| 145 | _output.Write(temp, 0, temp.Length);
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 146 | }
|
| 147 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 148 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 149 | protected override void WriteToOutput(char ch)
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 150 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 151 | if (_bufferPos >= _buffer.Length)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 152 | {
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 153 | Flush();
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 154 | }
|
| 155 | _buffer[_bufferPos++] = (byte) ch;
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 156 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 157 |
|
| 158 | public override void Flush()
|
| 159 | {
|
| 160 | if (_bufferPos > 0 && _output != null)
|
| 161 | {
|
| 162 | _output.Write(_buffer, 0, _bufferPos);
|
| 163 | _bufferPos = 0;
|
| 164 | }
|
| 165 | base.Flush();
|
| 166 | }
|
| 167 | }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 168 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 169 | #endregion
|
| 170 |
|
| 171 | private readonly List<int> _counter;
|
| 172 | private bool _isArray;
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 173 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 174 | /// <summary>
|
| 175 | /// Constructs a JsonFormatWriter, use the ToString() member to extract the final Json on completion.
|
| 176 | /// </summary>
|
| 177 | protected JsonFormatWriter()
|
| 178 | {
|
| 179 | _counter = new List<int>();
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 180 | }
|
| 181 |
|
| 182 | /// <summary>
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 183 | /// Constructs a JsonFormatWriter, use ToString() to extract the final output
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 184 | /// </summary>
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 185 | public static JsonFormatWriter CreateInstance()
|
| 186 | {
|
| 187 | return new JsonTextWriter(null);
|
| 188 | }
|
| 189 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 190 | /// <summary>
|
| 191 | /// Constructs a JsonFormatWriter to output to the given text writer
|
| 192 | /// </summary>
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 193 | public static JsonFormatWriter CreateInstance(TextWriter output)
|
| 194 | {
|
| 195 | return new JsonTextWriter(output);
|
| 196 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 197 |
|
| 198 | /// <summary>
|
| 199 | /// Constructs a JsonFormatWriter to output to the given stream
|
| 200 | /// </summary>
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 201 | public static JsonFormatWriter CreateInstance(Stream output)
|
| 202 | {
|
| 203 | return new JsonStreamWriter(output);
|
| 204 | }
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 205 |
|
| 206 | /// <summary> Write to the output stream </summary>
|
| 207 | protected void WriteToOutput(string format, params object[] args)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 208 | {
|
| 209 | WriteToOutput(String.Format(format, args));
|
| 210 | }
|
| 211 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 212 | /// <summary> Write to the output stream </summary>
|
| 213 | protected void WriteToOutput(string text)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 214 | {
|
| 215 | WriteToOutput(text.ToCharArray(), 0, text.Length);
|
| 216 | }
|
| 217 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 218 | /// <summary> Write to the output stream </summary>
|
| 219 | protected abstract void WriteToOutput(char ch);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 220 |
|
csharptest | 7fc785c | 2011-06-10 23:54:53 -0500 | [diff] [blame] | 221 | /// <summary> Write to the output stream </summary>
|
| 222 | protected abstract void WriteToOutput(char[] chars, int offset, int len);
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 223 |
|
| 224 | /// <summary> Sets the output formatting to use Environment.NewLine with 4-character indentions </summary>
|
| 225 | public JsonFormatWriter Formatted()
|
| 226 | {
|
| 227 | NewLine = Environment.NewLine;
|
| 228 | Indent = " ";
|
| 229 | Whitespace = " ";
|
| 230 | return this;
|
| 231 | }
|
| 232 |
|
| 233 | /// <summary> Gets or sets the characters to use for the new-line, default = empty </summary>
|
| 234 | public string NewLine { get; set; }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 235 |
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 236 | /// <summary> Gets or sets the text to use for indenting, default = empty </summary>
|
| 237 | public string Indent { get; set; }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 238 |
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 239 | /// <summary> Gets or sets the whitespace to use to separate the text, default = empty </summary>
|
| 240 | public string Whitespace { get; set; }
|
| 241 |
|
| 242 | private void Seperator()
|
| 243 | {
|
| 244 | if (_counter.Count == 0)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 245 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 246 | throw new InvalidOperationException("Missmatched open/close in Json writer.");
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 247 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 248 |
|
| 249 | int index = _counter.Count - 1;
|
| 250 | if (_counter[index] > 0)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 251 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 252 | WriteToOutput(',');
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 253 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 254 |
|
| 255 | WriteLine(String.Empty);
|
| 256 | _counter[index] = _counter[index] + 1;
|
| 257 | }
|
| 258 |
|
| 259 | private void WriteLine(string content)
|
| 260 | {
|
| 261 | if (!String.IsNullOrEmpty(NewLine))
|
| 262 | {
|
| 263 | WriteToOutput(NewLine);
|
| 264 | for (int i = 1; i < _counter.Count; i++)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 265 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 266 | WriteToOutput(Indent);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 267 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 268 | }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 269 | else if (!String.IsNullOrEmpty(Whitespace))
|
| 270 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 271 | WriteToOutput(Whitespace);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 272 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 273 |
|
| 274 | WriteToOutput(content);
|
| 275 | }
|
| 276 |
|
| 277 | private void WriteName(string field)
|
| 278 | {
|
| 279 | Seperator();
|
| 280 | if (!String.IsNullOrEmpty(field))
|
| 281 | {
|
| 282 | WriteToOutput('"');
|
| 283 | WriteToOutput(field);
|
| 284 | WriteToOutput('"');
|
| 285 | WriteToOutput(':');
|
| 286 | if (!String.IsNullOrEmpty(Whitespace))
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 287 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 288 | WriteToOutput(Whitespace);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 289 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 290 | }
|
| 291 | }
|
| 292 |
|
| 293 | private void EncodeText(string value)
|
| 294 | {
|
| 295 | char[] text = value.ToCharArray();
|
| 296 | int len = text.Length;
|
| 297 | int pos = 0;
|
| 298 |
|
| 299 | while (pos < len)
|
| 300 | {
|
| 301 | int next = pos;
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 302 | while (next < len && text[next] >= 32 && text[next] < 127 && text[next] != '\\' && text[next] != '/' &&
|
| 303 | text[next] != '"')
|
| 304 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 305 | next++;
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 306 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 307 | WriteToOutput(text, pos, next - pos);
|
| 308 | if (next < len)
|
| 309 | {
|
| 310 | switch (text[next])
|
| 311 | {
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 312 | case '"':
|
| 313 | WriteToOutput(@"\""");
|
| 314 | break;
|
| 315 | case '\\':
|
| 316 | WriteToOutput(@"\\");
|
| 317 | break;
|
| 318 | //odd at best to escape '/', most Json implementations don't, but it is defined in the rfc-4627
|
| 319 | case '/':
|
| 320 | WriteToOutput(@"\/");
|
| 321 | break;
|
| 322 | case '\b':
|
| 323 | WriteToOutput(@"\b");
|
| 324 | break;
|
| 325 | case '\f':
|
| 326 | WriteToOutput(@"\f");
|
| 327 | break;
|
| 328 | case '\n':
|
| 329 | WriteToOutput(@"\n");
|
| 330 | break;
|
| 331 | case '\r':
|
| 332 | WriteToOutput(@"\r");
|
| 333 | break;
|
| 334 | case '\t':
|
| 335 | WriteToOutput(@"\t");
|
| 336 | break;
|
| 337 | default:
|
| 338 | WriteToOutput(@"\u{0:x4}", (int) text[next]);
|
| 339 | break;
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 340 | }
|
| 341 | next++;
|
| 342 | }
|
| 343 | pos = next;
|
| 344 | }
|
| 345 | }
|
| 346 |
|
| 347 | /// <summary>
|
| 348 | /// Writes a String value
|
| 349 | /// </summary>
|
| 350 | protected override void WriteAsText(string field, string textValue, object typedValue)
|
| 351 | {
|
| 352 | WriteName(field);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 353 | if (typedValue is bool || typedValue is int || typedValue is uint || typedValue is long ||
|
| 354 | typedValue is ulong || typedValue is double || typedValue is float)
|
| 355 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 356 | WriteToOutput(textValue);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 357 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 358 | else
|
| 359 | {
|
| 360 | WriteToOutput('"');
|
| 361 | if (typedValue is string)
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 362 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 363 | EncodeText(textValue);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 364 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 365 | else
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 366 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 367 | WriteToOutput(textValue);
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 368 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 369 | WriteToOutput('"');
|
| 370 | }
|
| 371 | }
|
| 372 |
|
| 373 | /// <summary>
|
| 374 | /// Writes a Double value
|
| 375 | /// </summary>
|
| 376 | protected override void Write(string field, double value)
|
| 377 | {
|
| 378 | if (double.IsNaN(value) || double.IsNegativeInfinity(value) || double.IsPositiveInfinity(value))
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 379 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 380 | throw new InvalidOperationException("This format does not support NaN, Infinity, or -Infinity");
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 381 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 382 | base.Write(field, value);
|
| 383 | }
|
| 384 |
|
| 385 | /// <summary>
|
| 386 | /// Writes a Single value
|
| 387 | /// </summary>
|
| 388 | protected override void Write(string field, float value)
|
| 389 | {
|
| 390 | if (float.IsNaN(value) || float.IsNegativeInfinity(value) || float.IsPositiveInfinity(value))
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 391 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 392 | throw new InvalidOperationException("This format does not support NaN, Infinity, or -Infinity");
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 393 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 394 | base.Write(field, value);
|
| 395 | }
|
| 396 |
|
| 397 | // Treat enum as string
|
| 398 | protected override void WriteEnum(string field, int number, string name)
|
| 399 | {
|
| 400 | Write(field, name);
|
| 401 | }
|
| 402 |
|
| 403 | /// <summary>
|
| 404 | /// Writes an array of field values
|
| 405 | /// </summary>
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 406 | protected override void WriteArray(FieldType type, string field, IEnumerable items)
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 407 | {
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 408 | IEnumerator enumerator = items.GetEnumerator();
|
| 409 | try
|
| 410 | {
|
| 411 | if (!enumerator.MoveNext())
|
| 412 | {
|
| 413 | return;
|
| 414 | }
|
| 415 | }
|
| 416 | finally
|
| 417 | {
|
| 418 | if (enumerator is IDisposable)
|
| 419 | {
|
| 420 | ((IDisposable) enumerator).Dispose();
|
| 421 | }
|
| 422 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 423 |
|
| 424 | WriteName(field);
|
| 425 | WriteToOutput("[");
|
| 426 | _counter.Add(0);
|
| 427 |
|
| 428 | base.WriteArray(type, String.Empty, items);
|
| 429 |
|
| 430 | _counter.RemoveAt(_counter.Count - 1);
|
| 431 | WriteLine("]");
|
| 432 | }
|
| 433 |
|
| 434 | /// <summary>
|
| 435 | /// Writes a message
|
| 436 | /// </summary>
|
| 437 | protected override void WriteMessageOrGroup(string field, IMessageLite message)
|
| 438 | {
|
| 439 | WriteName(field);
|
| 440 | WriteMessage(message);
|
| 441 | }
|
| 442 |
|
| 443 | /// <summary>
|
| 444 | /// Writes the message to the the formatted stream.
|
| 445 | /// </summary>
|
| 446 | public override void WriteMessage(IMessageLite message)
|
| 447 | {
|
csharptest | c2d2c1a | 2011-09-08 20:02:11 -0500 | [diff] [blame^] | 448 | StartMessage();
|
| 449 | message.WriteTo(this);
|
| 450 | EndMessage();
|
| 451 | }
|
| 452 |
|
| 453 | /// <summary>
|
| 454 | /// Used to write the root-message preamble, in json this is the left-curly brace '{'.
|
| 455 | /// After this call you can call IMessageLite.MergeTo(...) and complete the message with
|
| 456 | /// a call to EndMessage().
|
| 457 | /// </summary>
|
| 458 | public override void StartMessage()
|
| 459 | {
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 460 | if (_isArray)
|
| 461 | {
|
| 462 | Seperator();
|
| 463 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 464 | WriteToOutput("{");
|
| 465 | _counter.Add(0);
|
csharptest | c2d2c1a | 2011-09-08 20:02:11 -0500 | [diff] [blame^] | 466 | }
|
| 467 |
|
| 468 | /// <summary>
|
| 469 | /// Used to complete a root-message previously started with a call to StartMessage()
|
| 470 | /// </summary>
|
| 471 | public override void EndMessage()
|
| 472 | {
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 473 | _counter.RemoveAt(_counter.Count - 1);
|
| 474 | WriteLine("}");
|
| 475 | Flush();
|
| 476 | }
|
| 477 |
|
| 478 | /// <summary>
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 479 | /// Used in streaming arrays of objects to the writer
|
| 480 | /// </summary>
|
| 481 | /// <example>
|
| 482 | /// <code>
|
| 483 | /// using(writer.StartArray())
|
| 484 | /// foreach(IMessageLite m in messages)
|
| 485 | /// writer.WriteMessage(m);
|
| 486 | /// </code>
|
| 487 | /// </example>
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 488 | public sealed class JsonArray : IDisposable
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 489 | {
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 490 | private JsonFormatWriter _writer;
|
| 491 |
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 492 | internal JsonArray(JsonFormatWriter writer)
|
| 493 | {
|
| 494 | _writer = writer;
|
| 495 | _writer.WriteToOutput("[");
|
| 496 | _writer._counter.Add(0);
|
| 497 | }
|
| 498 |
|
| 499 | /// <summary>
|
| 500 | /// Causes the end of the array character to be written.
|
| 501 | /// </summary>
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 502 | private void EndArray()
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 503 | {
|
| 504 | if (_writer != null)
|
| 505 | {
|
| 506 | _writer._counter.RemoveAt(_writer._counter.Count - 1);
|
| 507 | _writer.WriteLine("]");
|
| 508 | _writer.Flush();
|
| 509 | }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 510 | _writer = null;
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 511 | }
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 512 |
|
| 513 | void IDisposable.Dispose()
|
| 514 | {
|
| 515 | EndArray();
|
| 516 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 517 | }
|
| 518 |
|
| 519 | /// <summary>
|
| 520 | /// Used to write an array of messages as the output rather than a single message.
|
| 521 | /// </summary>
|
| 522 | /// <example>
|
| 523 | /// <code>
|
| 524 | /// using(writer.StartArray())
|
| 525 | /// foreach(IMessageLite m in messages)
|
| 526 | /// writer.WriteMessage(m);
|
| 527 | /// </code>
|
| 528 | /// </example>
|
| 529 | public JsonArray StartArray()
|
| 530 | {
|
csharptest | 74c5e0c | 2011-07-14 13:06:22 -0500 | [diff] [blame] | 531 | if (_isArray)
|
| 532 | {
|
| 533 | Seperator();
|
| 534 | }
|
csharptest | afe844b | 2011-06-10 16:03:22 -0500 | [diff] [blame] | 535 | _isArray = true;
|
| 536 | return new JsonArray(this);
|
| 537 | }
|
| 538 | }
|
| 539 | } |