Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Bson\BsonWriter.cs

Symbol Coverage: 89.29% (100 of 112)

Branch Coverage: 86.96% (40 of 46)

Cyclomatic Complexity Avg: 1.20 Max:3

Code Lines: 112


L V Source
1
#region License
2
// Copyright (c) 2007 James Newton-King
3
//
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
11
// conditions:
12
//
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
24
#endregion
25

  
26
using System;
27
using System.Collections;
28
using System.Collections.Generic;
29
using System.IO;
30
using System.Text;
31
using Newtonsoft.Json.Utilities;
32
using Newtonsoft.Json.Linq;
33
using System.Globalization;
34

  
35
namespace Newtonsoft.Json.Bson
36
{
37
  /// <summary>
38
  /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
39
  /// </summary>
40
  public class BsonWriter : JsonWriter
41
  {
42
    private readonly BsonBinaryWriter _writer;
43

  
44
    private BsonToken _root;
45
    private BsonToken _parent;
46
    private string _propertyName;
47

  
48
    /// <summary>
49
    /// Initializes a new instance of the <see cref="BsonWriter"/> class.
50
    /// </summary>
51
    /// <param name="stream">The stream.</param>
52
 10443
    public BsonWriter(Stream stream)
53
    {
54
 10443
      ValidationUtils.ArgumentNotNull(stream, "stream");
55
 10443
      _writer = new BsonBinaryWriter(stream);
56
 10443
    }
57

  
58
    /// <summary>
59
    /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
60
    /// </summary>
61
    public override void Flush()
62
    {
63
 404
      _writer.Flush();
64
 404
    }
65

  
66
    /// <summary>
67
    /// Writes the end.
68
    /// </summary>
69
    /// <param name="token">The token.</param>
70
    protected override void WriteEnd(JsonToken token)
71
    {
72
 136696
      base.WriteEnd(token);
73
 136696
      RemoveParent();
74

  
75
 136696
      if (Top == 0)
76
      {
77
 10439
        _writer.WriteToken(_root);
78
      }
79
 136696
    }
80

  
81
    /// <summary>
82
    /// Writes out a comment <code>/*...*/</code> containing the specified text.
83
    /// </summary>
84
    /// <param name="text">Text to place inside the comment.</param>
85
    public override void WriteComment(string text)
86
    {
87
 1
      throw new JsonWriterException("Cannot write JSON comment as BSON.");
88
    }
89

  
90
    /// <summary>
91
    /// Writes the start of a constructor with the given name.
92
    /// </summary>
93
    /// <param name="name">The name of the constructor.</param>
94
    public override void WriteStartConstructor(string name)
95
    {
96
 1
      throw new JsonWriterException("Cannot write JSON constructor as BSON.");
97
    }
98

  
99
    /// <summary>
100
    /// Writes raw JSON.
101
    /// </summary>
102
    /// <param name="json">The raw JSON to write.</param>
103
    public override void WriteRaw(string json)
104
    {
105
 1
      throw new JsonWriterException("Cannot write raw JSON as BSON.");
106
    }
107

  
108
    /// <summary>
109
    /// Writes raw JSON where a value is expected and updates the writer's state.
110
    /// </summary>
111
    /// <param name="json">The raw JSON to write.</param>
112
    public override void WriteRawValue(string json)
113
    {
114
 1
      throw new JsonWriterException("Cannot write raw JSON as BSON.");
115
    }
116

  
117
    /// <summary>
118
    /// Writes the beginning of a Json array.
119
    /// </summary>
120
    public override void WriteStartArray()
121
    {
122
 10425
      base.WriteStartArray();
123

  
124
 10425
      AddParent(new BsonArray());
125
 10425
    }
126

  
127
    /// <summary>
128
    /// Writes the beginning of a Json object.
129
    /// </summary>
130
    public override void WriteStartObject()
131
    {
132
 126275
      base.WriteStartObject();
133

  
134
 126275
      AddParent(new BsonObject());
135
 126275
    }
136

  
137
    /// <summary>
138
    /// Writes the property name of a name/value pair on a Json object.
139
    /// </summary>
140
    /// <param name="name">The name of the property.</param>
141
    public override void WritePropertyName(string name)
142
    {
143
 399791
      base.WritePropertyName(name);
144

  
145
 399791
      _propertyName = name;
146
 399791
    }
147

  
148
    private void AddParent(BsonToken container)
149
    {
150
 136700
      AddToken(container);
151
 136700
      _parent = container;
152
 136700
    }
153

  
154
    private void RemoveParent()
155
    {
156
 136696
      _parent = _parent.Parent;
157
 136696
    }
158

  
159
    private void AddValue(object value, BsonType type)
160
    {
161
 157327
      AddToken(new BsonValue(value, type));
162
 157327
    }
163

  
164
    internal void AddToken(BsonToken token)
165
    {
166
 436324
      if (_parent != null)
167
      {
168
 425881
        if (_parent is BsonObject)
169
        {
170
 399791
          ((BsonObject)_parent).Add(_propertyName, token);
171
 399791
          _propertyName = null;
172
        }
173
        else
174
        {
175
 26090
          ((BsonArray)_parent).Add(token);
176
        }
177
      }
178
      else
179
      {
180
 10443
        _parent = token;
181
 10443
        _root = token;
182
      }
183
 436324
    }
184

  
185
    #region WriteValue methods
186
    /// <summary>
187
    /// Writes a null value.
188
    /// </summary>
189
    public override void WriteNull()
190
    {
191
 15411
      base.WriteNull();
192
 15411
      AddValue(null, BsonType.Null);
193
 15411
    }
194

  
195
    /// <summary>
196
    /// Writes an undefined value.
197
    /// </summary>
198
    public override void WriteUndefined()
199
    {
200
 0
      base.WriteUndefined();
201
 0
      AddValue(null, BsonType.Undefined);
202
 0
    }
203

  
204
    /// <summary>
205
    /// Writes a <see cref="String"/> value.
206
    /// </summary>
207
    /// <param name="value">The <see cref="String"/> value to write.</param>
208
    public override void WriteValue(string value)
209
    {
210
 142290
      base.WriteValue(value);
211
 142290
      if (value == null)
212
 1
        AddValue(null, BsonType.Null);
213
      else
214
 142289
        AddToken(new BsonString(value, true));
215
 142290
    }
216

  
217
    /// <summary>
218
    /// Writes a <see cref="Int32"/> value.
219
    /// </summary>
220
    /// <param name="value">The <see cref="Int32"/> value to write.</param>
221
    public override void WriteValue(int value)
222
    {
223
 115648
      base.WriteValue(value);
224
 115648
      AddValue(value, BsonType.Integer);
225
 115648
    }
226

  
227
    /// <summary>
228
    /// Writes a <see cref="UInt32"/> value.
229
    /// </summary>
230
    /// <param name="value">The <see cref="UInt32"/> value to write.</param>
231
    public override void WriteValue(uint value)
232
    {
233
 1
      if (value > int.MaxValue)
234
 0
        throw new JsonWriterException("Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.");
235

  
236
 1
      base.WriteValue(value);
237
 1
      AddValue(value, BsonType.Integer);
238
 1
    }
239

  
240
    /// <summary>
241
    /// Writes a <see cref="Int64"/> value.
242
    /// </summary>
243
    /// <param name="value">The <see cref="Int64"/> value to write.</param>
244
    public override void WriteValue(long value)
245
    {
246
 1
      base.WriteValue(value);
247
 1
      AddValue(value, BsonType.Long);
248
 1
    }
249

  
250
    /// <summary>
251
    /// Writes a <see cref="UInt64"/> value.
252
    /// </summary>
253
    /// <param name="value">The <see cref="UInt64"/> value to write.</param>
254
    public override void WriteValue(ulong value)
255
    {
256
 1
      if (value > long.MaxValue)
257
 0
        throw new JsonWriterException("Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.");
258

  
259
 1
      base.WriteValue(value);
260
 1
      AddValue(value, BsonType.Long);
261
 1
    }
262

  
263
    /// <summary>
264
    /// Writes a <see cref="Single"/> value.
265
    /// </summary>
266
    /// <param name="value">The <see cref="Single"/> value to write.</param>
267
    public override void WriteValue(float value)
268
    {
269
 1
      base.WriteValue(value);
270
 1
      AddValue(value, BsonType.Number);
271
 1
    }
272

  
273
    /// <summary>
274
    /// Writes a <see cref="Double"/> value.
275
    /// </summary>
276
    /// <param name="value">The <see cref="Double"/> value to write.</param>
277
    public override void WriteValue(double value)
278
    {
279
 19
      base.WriteValue(value);
280
 19
      AddValue(value, BsonType.Number);
281
 19
    }
282

  
283
    /// <summary>
284
    /// Writes a <see cref="Boolean"/> value.
285
    /// </summary>
286
    /// <param name="value">The <see cref="Boolean"/> value to write.</param>
287
    public override void WriteValue(bool value)
288
    {
289
 3
      base.WriteValue(value);
290
 3
      AddValue(value, BsonType.Boolean);
291
 3
    }
292

  
293
    /// <summary>
294
    /// Writes a <see cref="Int16"/> value.
295
    /// </summary>
296
    /// <param name="value">The <see cref="Int16"/> value to write.</param>
297
    public override void WriteValue(short value)
298
    {
299
 0
      base.WriteValue(value);
300
 0
      AddValue(value, BsonType.Integer);
301
 0
    }
302

  
303
    /// <summary>
304
    /// Writes a <see cref="UInt16"/> value.
305
    /// </summary>
306
    /// <param name="value">The <see cref="UInt16"/> value to write.</param>
307
    public override void WriteValue(ushort value)
308
    {
309
 0
      base.WriteValue(value);
310
 0
      AddValue(value, BsonType.Integer);
311
 0
    }
312

  
313
    /// <summary>
314
    /// Writes a <see cref="Char"/> value.
315
    /// </summary>
316
    /// <param name="value">The <see cref="Char"/> value to write.</param>
317
    public override void WriteValue(char value)
318
    {
319
 3
      base.WriteValue(value);
320
 3
      AddToken(new BsonString(value.ToString(), true));
321
 3
    }
322

  
323
    /// <summary>
324
    /// Writes a <see cref="Byte"/> value.
325
    /// </summary>
326
    /// <param name="value">The <see cref="Byte"/> value to write.</param>
327
    public override void WriteValue(byte value)
328
    {
329
 1
      base.WriteValue(value);
330
 1
      AddValue(value, BsonType.Integer);
331
 1
    }
332

  
333
    /// <summary>
334
    /// Writes a <see cref="SByte"/> value.
335
    /// </summary>
336
    /// <param name="value">The <see cref="SByte"/> value to write.</param>
337
    public override void WriteValue(sbyte value)
338
    {
339
 1
      base.WriteValue(value);
340
 1
      AddValue(value, BsonType.Integer);
341
 1
    }
342

  
343
    /// <summary>
344
    /// Writes a <see cref="Decimal"/> value.
345
    /// </summary>
346
    /// <param name="value">The <see cref="Decimal"/> value to write.</param>
347
    public override void WriteValue(decimal value)
348
    {
349
 5215
      base.WriteValue(value);
350
 5215
      AddValue(value, BsonType.Number);
351
 5215
    }
352

  
353
    /// <summary>
354
    /// Writes a <see cref="DateTime"/> value.
355
    /// </summary>
356
    /// <param name="value">The <see cref="DateTime"/> value to write.</param>
357
    public override void WriteValue(DateTime value)
358
    {
359
 20816
      base.WriteValue(value);
360
 20816
      AddValue(value, BsonType.Date);
361
 20816
    }
362

  
363
#if !PocketPC && !NET20
364
    /// <summary>
365
    /// Writes a <see cref="DateTimeOffset"/> value.
366
    /// </summary>
367
    /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
368
    public override void WriteValue(DateTimeOffset value)
369
    {
370
 1
      base.WriteValue(value);
371
 1
      AddValue(value, BsonType.Date);
372
 1
    }
373
#endif
374

  
375
    /// <summary>
376
    /// Writes a <see cref="T:Byte[]"/> value.
377
    /// </summary>
378
    /// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
379
    public override void WriteValue(byte[] value)
380
    {
381
 204
      base.WriteValue(value);
382
 204
      AddValue(value, BsonType.Binary);
383
 204
    }
384
    #endregion
385

  
386
    /// <summary>
387
    /// Writes a <see cref="T:Byte[]"/> value that represents a BSON object id.
388
    /// </summary>
389
    /// <param name="value"></param>
390
    public void WriteObjectId(byte[] value)
391
    {
392
 3
      ValidationUtils.ArgumentNotNull(value, "value");
393

  
394
 3
      if (value.Length != 12)
395
 0
        throw new Exception("An object id must be 12 bytes");
396

  
397
      // hack to update the writer state
398
 3
      AutoComplete(JsonToken.Undefined);
399
 3
      AddValue(value, BsonType.Oid);
400
 3
    }
401

  
402
    /// <summary>
403
    /// Writes a BSON regex.
404
    /// </summary>
405
    /// <param name="pattern">The regex pattern.</param>
406
    /// <param name="options">The regex options.</param>
407
    public void WriteRegex(string pattern, string options)
408
    {
409
 5
      ValidationUtils.ArgumentNotNull(pattern, "pattern");
410

  
411
      // hack to update the writer state
412
 5
      AutoComplete(JsonToken.Undefined);
413
 5
      AddToken(new BsonRegex(pattern, options));
414
 5
    }
415
  }
416
}