2
// Copyright (c) 2007 James Newton-King
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
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
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.
27
using System.Collections;
28
using System.Collections.Generic;
31
using Newtonsoft.Json.Utilities;
32
using Newtonsoft.Json.Linq;
33
using System.Globalization;
35
namespace Newtonsoft.Json.Bson
38
/// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
40
public class BsonWriter : JsonWriter
42
private readonly BsonBinaryWriter _writer;
44
private BsonToken _root;
45
private BsonToken _parent;
46
private string _propertyName;
49
/// Gets or sets the <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.
50
/// When set to <see cref="DateTimeKind.Unspecified" /> no conversion will occur.
52
/// <value>The <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.</value>
53
public DateTimeKind DateTimeKindHandling
55
get { return _writer.DateTimeKindHandling; }
56
set { _writer.DateTimeKindHandling = value; }
60
/// Initializes a new instance of the <see cref="BsonWriter"/> class.
62
/// <param name="stream">The stream.</param>
63
public BsonWriter(Stream stream)
65
ValidationUtils.ArgumentNotNull(stream, "stream");
66
_writer = new BsonBinaryWriter(new BinaryWriter(stream));
70
/// Initializes a new instance of the <see cref="BsonWriter"/> class.
72
/// <param name="writer">The writer.</param>
73
public BsonWriter(BinaryWriter writer)
75
ValidationUtils.ArgumentNotNull(writer, "writer");
76
_writer = new BsonBinaryWriter(writer);
80
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
82
public override void Flush()
90
/// <param name="token">The token.</param>
91
protected override void WriteEnd(JsonToken token)
98
_writer.WriteToken(_root);
103
/// Writes out a comment <code>/*...*/</code> containing the specified text.
105
/// <param name="text">Text to place inside the comment.</param>
106
public override void WriteComment(string text)
108
throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null);
112
/// Writes the start of a constructor with the given name.
114
/// <param name="name">The name of the constructor.</param>
115
public override void WriteStartConstructor(string name)
117
throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null);
123
/// <param name="json">The raw JSON to write.</param>
124
public override void WriteRaw(string json)
126
throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
130
/// Writes raw JSON where a value is expected and updates the writer's state.
132
/// <param name="json">The raw JSON to write.</param>
133
public override void WriteRawValue(string json)
135
throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
139
/// Writes the beginning of a Json array.
141
public override void WriteStartArray()
143
base.WriteStartArray();
145
AddParent(new BsonArray());
149
/// Writes the beginning of a Json object.
151
public override void WriteStartObject()
153
base.WriteStartObject();
155
AddParent(new BsonObject());
159
/// Writes the property name of a name/value pair on a Json object.
161
/// <param name="name">The name of the property.</param>
162
public override void WritePropertyName(string name)
164
base.WritePropertyName(name);
166
_propertyName = name;
170
/// Closes this stream and the underlying stream.
172
public override void Close()
176
if (CloseOutput && _writer != null)
180
private void AddParent(BsonToken container)
186
private void RemoveParent()
188
_parent = _parent.Parent;
191
private void AddValue(object value, BsonType type)
193
AddToken(new BsonValue(value, type));
196
internal void AddToken(BsonToken token)
200
if (_parent is BsonObject)
202
((BsonObject) _parent).Add(_propertyName, token);
203
_propertyName = null;
207
((BsonArray) _parent).Add(token);
212
if (token.Type != BsonType.Object && token.Type != BsonType.Array)
213
throw JsonWriterException.Create(this, "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), null);
220
#region WriteValue methods
223
/// Writes a null value.
225
public override void WriteNull()
228
AddValue(null, BsonType.Null);
232
/// Writes an undefined value.
234
public override void WriteUndefined()
236
base.WriteUndefined();
237
AddValue(null, BsonType.Undefined);
241
/// Writes a <see cref="String"/> value.
243
/// <param name="value">The <see cref="String"/> value to write.</param>
244
public override void WriteValue(string value)
246
base.WriteValue(value);
248
AddValue(null, BsonType.Null);
250
AddToken(new BsonString(value, true));
254
/// Writes a <see cref="Int32"/> value.
256
/// <param name="value">The <see cref="Int32"/> value to write.</param>
257
public override void WriteValue(int value)
259
base.WriteValue(value);
260
AddValue(value, BsonType.Integer);
264
/// Writes a <see cref="UInt32"/> value.
266
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
267
[CLSCompliant(false)]
268
public override void WriteValue(uint value)
270
if (value > int.MaxValue)
271
throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", null);
273
base.WriteValue(value);
274
AddValue(value, BsonType.Integer);
278
/// Writes a <see cref="Int64"/> value.
280
/// <param name="value">The <see cref="Int64"/> value to write.</param>
281
public override void WriteValue(long value)
283
base.WriteValue(value);
284
AddValue(value, BsonType.Long);
288
/// Writes a <see cref="UInt64"/> value.
290
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
291
[CLSCompliant(false)]
292
public override void WriteValue(ulong value)
294
if (value > long.MaxValue)
295
throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", null);
297
base.WriteValue(value);
298
AddValue(value, BsonType.Long);
302
/// Writes a <see cref="Single"/> value.
304
/// <param name="value">The <see cref="Single"/> value to write.</param>
305
public override void WriteValue(float value)
307
base.WriteValue(value);
308
AddValue(value, BsonType.Number);
312
/// Writes a <see cref="Double"/> value.
314
/// <param name="value">The <see cref="Double"/> value to write.</param>
315
public override void WriteValue(double value)
317
base.WriteValue(value);
318
AddValue(value, BsonType.Number);
322
/// Writes a <see cref="Boolean"/> value.
324
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
325
public override void WriteValue(bool value)
327
base.WriteValue(value);
328
AddValue(value, BsonType.Boolean);
332
/// Writes a <see cref="Int16"/> value.
334
/// <param name="value">The <see cref="Int16"/> value to write.</param>
335
public override void WriteValue(short value)
337
base.WriteValue(value);
338
AddValue(value, BsonType.Integer);
342
/// Writes a <see cref="UInt16"/> value.
344
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
345
[CLSCompliant(false)]
346
public override void WriteValue(ushort value)
348
base.WriteValue(value);
349
AddValue(value, BsonType.Integer);
353
/// Writes a <see cref="Char"/> value.
355
/// <param name="value">The <see cref="Char"/> value to write.</param>
356
public override void WriteValue(char value)
358
base.WriteValue(value);
360
#if !(NETFX_CORE || PORTABLE)
361
s = value.ToString(CultureInfo.InvariantCulture);
363
s = value.ToString();
365
AddToken(new BsonString(s, true));
369
/// Writes a <see cref="Byte"/> value.
371
/// <param name="value">The <see cref="Byte"/> value to write.</param>
372
public override void WriteValue(byte value)
374
base.WriteValue(value);
375
AddValue(value, BsonType.Integer);
379
/// Writes a <see cref="SByte"/> value.
381
/// <param name="value">The <see cref="SByte"/> value to write.</param>
382
[CLSCompliant(false)]
383
public override void WriteValue(sbyte value)
385
base.WriteValue(value);
386
AddValue(value, BsonType.Integer);
390
/// Writes a <see cref="Decimal"/> value.
392
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
393
public override void WriteValue(decimal value)
395
base.WriteValue(value);
396
AddValue(value, BsonType.Number);
400
/// Writes a <see cref="DateTime"/> value.
402
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
403
public override void WriteValue(DateTime value)
405
base.WriteValue(value);
406
value = JsonConvert.EnsureDateTime(value, DateTimeZoneHandling);
407
AddValue(value, BsonType.Date);
410
#if !PocketPC && !NET20
412
/// Writes a <see cref="DateTimeOffset"/> value.
414
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
415
public override void WriteValue(DateTimeOffset value)
417
base.WriteValue(value);
418
AddValue(value, BsonType.Date);
423
/// Writes a <see cref="T:Byte[]"/> value.
425
/// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
426
public override void WriteValue(byte[] value)
428
base.WriteValue(value);
429
AddValue(value, BsonType.Binary);
433
/// Writes a <see cref="Guid"/> value.
435
/// <param name="value">The <see cref="Guid"/> value to write.</param>
436
public override void WriteValue(Guid value)
438
base.WriteValue(value);
439
AddToken(new BsonString(value.ToString(), true));
443
/// Writes a <see cref="TimeSpan"/> value.
445
/// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
446
public override void WriteValue(TimeSpan value)
448
base.WriteValue(value);
449
AddToken(new BsonString(value.ToString(), true));
453
/// Writes a <see cref="Uri"/> value.
455
/// <param name="value">The <see cref="Uri"/> value to write.</param>
456
public override void WriteValue(Uri value)
458
base.WriteValue(value);
459
AddToken(new BsonString(value.ToString(), true));
465
/// Writes a <see cref="T:Byte[]"/> value that represents a BSON object id.
467
/// <param name="value">The Object ID value to write.</param>
468
public void WriteObjectId(byte[] value)
470
ValidationUtils.ArgumentNotNull(value, "value");
472
if (value.Length != 12)
473
throw JsonWriterException.Create(this, "An object id must be 12 bytes", null);
475
// hack to update the writer state
476
UpdateScopeWithFinishedValue();
477
AutoComplete(JsonToken.Undefined);
478
AddValue(value, BsonType.Oid);
482
/// Writes a BSON regex.
484
/// <param name="pattern">The regex pattern.</param>
485
/// <param name="options">The regex options.</param>
486
public void WriteRegex(string pattern, string options)
488
ValidationUtils.ArgumentNotNull(pattern, "pattern");
490
// hack to update the writer state
491
UpdateScopeWithFinishedValue();
492
AutoComplete(JsonToken.Undefined);
493
AddToken(new BsonRegex(pattern, options));
b'\\ No newline at end of file'