You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
661 lines
25 KiB
661 lines
25 KiB
/* Copyright 2010-2011 10gen Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml;
|
|
|
|
namespace MongoDB.Bson.IO {
|
|
/// <summary>
|
|
/// Represents a BSON writer to a TextWriter (in JSON format).
|
|
/// </summary>
|
|
public class JsonWriter : BsonWriter {
|
|
#region private fields
|
|
private TextWriter textWriter;
|
|
private new JsonWriterSettings settings; // same value as in base class just declared as derived class
|
|
private JsonWriterContext context;
|
|
#endregion
|
|
|
|
#region constructors
|
|
/// <summary>
|
|
/// Initializes a new instance of the JsonWriter class.
|
|
/// </summary>
|
|
/// <param name="writer">A TextWriter.</param>
|
|
/// <param name="settings">Optional JsonWriter settings.</param>
|
|
public JsonWriter(
|
|
TextWriter writer,
|
|
JsonWriterSettings settings
|
|
)
|
|
: base(settings) {
|
|
this.textWriter = writer;
|
|
this.settings = settings; // already frozen by base class
|
|
context = new JsonWriterContext(null, ContextType.TopLevel, "");
|
|
state = BsonWriterState.Initial;
|
|
}
|
|
#endregion
|
|
|
|
#region public methods
|
|
/// <summary>
|
|
/// Closes the writer.
|
|
/// </summary>
|
|
public override void Close() {
|
|
// Close can be called on Disposed objects
|
|
if (state != BsonWriterState.Closed) {
|
|
Flush();
|
|
if (settings.CloseOutput) {
|
|
textWriter.Close();
|
|
}
|
|
context = null;
|
|
state = BsonWriterState.Closed;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flushes any pending data to the output destination.
|
|
/// </summary>
|
|
public override void Flush() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
textWriter.Flush();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes BSON binary data to the writer.
|
|
/// </summary>
|
|
/// <param name="bytes">The binary data.</param>
|
|
/// <param name="subType">The binary data subtype.</param>
|
|
/// <param name="guidRepresentation">The representation for Guids.</param>
|
|
public override void WriteBinaryData(
|
|
byte[] bytes,
|
|
BsonBinarySubType subType,
|
|
GuidRepresentation guidRepresentation // ignored for now (until we figure out how to represent this in the generated JSON)
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteBinaryData", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
if (settings.OutputMode == JsonOutputMode.Shell) {
|
|
WriteNameHelper(name);
|
|
textWriter.Write("new BinData({0}, \"{1}\")", (int) subType, Convert.ToBase64String(bytes));
|
|
} else {
|
|
WriteStartDocument();
|
|
WriteString("$binary", Convert.ToBase64String(bytes));
|
|
WriteString("$type", ((int) subType).ToString("x2"));
|
|
WriteEndDocument();
|
|
}
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON Boolean to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The Boolean value.</param>
|
|
public override void WriteBoolean(
|
|
bool value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteBoolean", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
textWriter.Write(value ? "true" : "false");
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON DateTime to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The number of milliseconds since the Unix epoch.</param>
|
|
public override void WriteDateTime(
|
|
long value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteDateTime", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
switch (settings.OutputMode) {
|
|
case JsonOutputMode.Strict:
|
|
WriteStartDocument();
|
|
WriteInt64("$date", value);
|
|
WriteEndDocument();
|
|
break;
|
|
case JsonOutputMode.JavaScript:
|
|
case JsonOutputMode.TenGen:
|
|
WriteNameHelper(name);
|
|
textWriter.Write("Date({0})", value);
|
|
break;
|
|
case JsonOutputMode.Shell:
|
|
WriteNameHelper(name);
|
|
// use ISODate for values that fall within .NET's DateTime range, and "new Date" for all others
|
|
if (
|
|
value >= BsonConstants.DateTimeMinValueMillisecondsSinceEpoch &&
|
|
value <= BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch
|
|
) {
|
|
var utcDateTime = BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(value);
|
|
textWriter.Write("ISODate(\"{0}\")", utcDateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFZ"));
|
|
} else {
|
|
textWriter.Write("new Date({0})", value);
|
|
}
|
|
break;
|
|
default:
|
|
throw new BsonInternalException("Unexpected JsonOutputMode.");
|
|
}
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON Double to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The Double value.</param>
|
|
public override void WriteDouble(
|
|
double value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteDouble", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
// if string representation looks like an integer add ".0" so that it looks like a double
|
|
var stringRepresentation = value.ToString("R", NumberFormatInfo.InvariantInfo);
|
|
if (Regex.IsMatch(stringRepresentation, @"^[+-]?\d+$")) {
|
|
stringRepresentation += ".0";
|
|
}
|
|
textWriter.Write(stringRepresentation);
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the end of a BSON array to the writer.
|
|
/// </summary>
|
|
public override void WriteEndArray() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value) {
|
|
ThrowInvalidState("WriteEndArray", BsonWriterState.Value);
|
|
}
|
|
|
|
textWriter.Write("]");
|
|
|
|
context = context.ParentContext;
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the end of a BSON document to the writer.
|
|
/// </summary>
|
|
public override void WriteEndDocument() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Name) {
|
|
ThrowInvalidState("WriteEndDocument", BsonWriterState.Name);
|
|
}
|
|
|
|
if (settings.Indent && context.HasElements) {
|
|
textWriter.Write(settings.NewLineChars);
|
|
if (context.ParentContext != null) {
|
|
textWriter.Write(context.ParentContext.Indentation);
|
|
}
|
|
textWriter.Write("}");
|
|
} else {
|
|
textWriter.Write(" }");
|
|
}
|
|
|
|
if (context.ContextType == ContextType.ScopeDocument) {
|
|
context = context.ParentContext;
|
|
WriteEndDocument();
|
|
} else {
|
|
context = context.ParentContext;
|
|
}
|
|
|
|
if (context == null) {
|
|
state = BsonWriterState.Done;
|
|
} else {
|
|
state = GetNextState();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON Int32 to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The Int32 value.</param>
|
|
public override void WriteInt32(
|
|
int value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteInt32", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
textWriter.Write(value);
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON Int64 to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The Int64 value.</param>
|
|
public override void WriteInt64(
|
|
long value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteInt64", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
switch (settings.OutputMode) {
|
|
case JsonOutputMode.Strict:
|
|
case JsonOutputMode.JavaScript:
|
|
WriteNameHelper(name);
|
|
textWriter.Write(value);
|
|
break;
|
|
case JsonOutputMode.TenGen:
|
|
case JsonOutputMode.Shell:
|
|
WriteNameHelper(name);
|
|
if (value >= int.MinValue && value <= int.MaxValue) {
|
|
textWriter.Write("NumberLong({0})", value);
|
|
} else {
|
|
textWriter.Write("NumberLong(\"{0}\")", value);
|
|
}
|
|
break;
|
|
default:
|
|
WriteNameHelper(name);
|
|
textWriter.Write(value);
|
|
break;
|
|
}
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON JavaScript to the writer.
|
|
/// </summary>
|
|
/// <param name="code">The JavaScript code.</param>
|
|
public override void WriteJavaScript(
|
|
string code
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteJavaScript", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteStartDocument();
|
|
WriteString("$code", code);
|
|
WriteEndDocument();
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON JavaScript to the writer (call WriteStartDocument to start writing the scope).
|
|
/// </summary>
|
|
/// <param name="code">The JavaScript code.</param>
|
|
public override void WriteJavaScriptWithScope(
|
|
string code
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteJavaScriptWithScope", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteStartDocument();
|
|
WriteString("$code", code);
|
|
WriteName("$scope");
|
|
|
|
state = BsonWriterState.ScopeDocument;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON MaxKey to the writer.
|
|
/// </summary>
|
|
public override void WriteMaxKey() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteMaxKey", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteStartDocument();
|
|
WriteInt32("$maxkey", 1);
|
|
WriteEndDocument();
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON MinKey to the writer.
|
|
/// </summary>
|
|
public override void WriteMinKey() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteMinKey", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteStartDocument();
|
|
WriteInt32("$minkey", 1);
|
|
WriteEndDocument();
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON null to the writer.
|
|
/// </summary>
|
|
public override void WriteNull() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteNull", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
textWriter.Write("null");
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON ObjectId to the writer.
|
|
/// </summary>
|
|
/// <param name="timestamp">The timestamp.</param>
|
|
/// <param name="machine">The machine hash.</param>
|
|
/// <param name="pid">The PID.</param>
|
|
/// <param name="increment">The increment.</param>
|
|
public override void WriteObjectId(
|
|
int timestamp,
|
|
int machine,
|
|
short pid,
|
|
int increment
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteObjectId", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
var bytes = ObjectId.Pack(timestamp, machine, pid, increment);
|
|
switch (settings.OutputMode) {
|
|
case JsonOutputMode.Strict:
|
|
case JsonOutputMode.JavaScript:
|
|
WriteStartDocument();
|
|
WriteString("$oid", BsonUtils.ToHexString(bytes));
|
|
WriteEndDocument();
|
|
break;
|
|
case JsonOutputMode.TenGen:
|
|
case JsonOutputMode.Shell:
|
|
WriteNameHelper(name);
|
|
textWriter.Write(string.Format("ObjectId(\"{0}\")", BsonUtils.ToHexString(bytes)));
|
|
break;
|
|
}
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON regular expression to the writer.
|
|
/// </summary>
|
|
/// <param name="pattern">A regular expression pattern.</param>
|
|
/// <param name="options">A regular expression options.</param>
|
|
public override void WriteRegularExpression(
|
|
string pattern,
|
|
string options
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteRegularExpression", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
switch (settings.OutputMode) {
|
|
case JsonOutputMode.Strict:
|
|
WriteStartDocument();
|
|
WriteString("$regex", pattern);
|
|
WriteString("$options", options);
|
|
WriteEndDocument();
|
|
break;
|
|
case JsonOutputMode.JavaScript:
|
|
case JsonOutputMode.TenGen:
|
|
case JsonOutputMode.Shell:
|
|
WriteNameHelper(name);
|
|
textWriter.Write("/");
|
|
var escaped = (pattern == "") ? "(?:)" : pattern.Replace(@"\", @"\\").Replace("/", @"\/");
|
|
textWriter.Write(escaped);
|
|
textWriter.Write("/");
|
|
textWriter.Write(options);
|
|
break;
|
|
}
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the start of a BSON array to the writer.
|
|
/// </summary>
|
|
public override void WriteStartArray() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteStartArray", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
textWriter.Write("[");
|
|
|
|
context = new JsonWriterContext(context, ContextType.Array, settings.IndentChars);
|
|
state = BsonWriterState.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the start of a BSON document to the writer.
|
|
/// </summary>
|
|
public override void WriteStartDocument() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial && state != BsonWriterState.ScopeDocument) {
|
|
ThrowInvalidState("WriteStartDocument", BsonWriterState.Value, BsonWriterState.Initial, BsonWriterState.ScopeDocument);
|
|
}
|
|
|
|
if (state == BsonWriterState.Value || state == BsonWriterState.ScopeDocument) {
|
|
WriteNameHelper(name);
|
|
}
|
|
textWriter.Write("{");
|
|
|
|
var contextType = (state == BsonWriterState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document;
|
|
context = new JsonWriterContext(context, contextType, settings.IndentChars);
|
|
state = BsonWriterState.Name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON String to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The String value.</param>
|
|
public override void WriteString(
|
|
string value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteString", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
WriteStringHelper(value);
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON Symbol to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The symbol.</param>
|
|
public override void WriteSymbol(
|
|
string value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteSymbol", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteStartDocument();
|
|
WriteString("$symbol", value);
|
|
WriteEndDocument();
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON timestamp to the writer.
|
|
/// </summary>
|
|
/// <param name="value">The combined timestamp/increment value.</param>
|
|
public override void WriteTimestamp(
|
|
long value
|
|
) {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteTimestamp", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteStartDocument();
|
|
WriteInt64("$timestamp", value);
|
|
WriteEndDocument();
|
|
|
|
state = GetNextState();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a BSON undefined to the writer.
|
|
/// </summary>
|
|
public override void WriteUndefined() {
|
|
if (disposed) { throw new ObjectDisposedException("JsonWriter"); }
|
|
if (state != BsonWriterState.Value && state != BsonWriterState.Initial) {
|
|
ThrowInvalidState("WriteUndefined", BsonWriterState.Value, BsonWriterState.Initial);
|
|
}
|
|
|
|
WriteNameHelper(name);
|
|
textWriter.Write("undefined");
|
|
|
|
state = GetNextState();
|
|
}
|
|
#endregion
|
|
|
|
#region protected methods
|
|
/// <summary>
|
|
/// Disposes of any resources used by the writer.
|
|
/// </summary>
|
|
/// <param name="disposing">True if called from Dispose.</param>
|
|
protected override void Dispose(
|
|
bool disposing
|
|
) {
|
|
if (disposing) {
|
|
Close();
|
|
textWriter.Dispose();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region private methods
|
|
private BsonWriterState GetNextState() {
|
|
if (context.ContextType == ContextType.Array) {
|
|
return BsonWriterState.Value;
|
|
} else {
|
|
return BsonWriterState.Name;
|
|
}
|
|
}
|
|
|
|
private void WriteNameHelper(
|
|
string name
|
|
) {
|
|
switch (context.ContextType) {
|
|
case ContextType.Array:
|
|
// don't write Array element names in Json
|
|
if (context.HasElements) {
|
|
textWriter.Write(", ");
|
|
}
|
|
break;
|
|
case ContextType.Document:
|
|
case ContextType.ScopeDocument:
|
|
if (context.HasElements) {
|
|
textWriter.Write(",");
|
|
}
|
|
if (settings.Indent) {
|
|
textWriter.Write(settings.NewLineChars);
|
|
textWriter.Write(context.Indentation);
|
|
} else {
|
|
textWriter.Write(" ");
|
|
}
|
|
WriteStringHelper(name);
|
|
textWriter.Write(" : ");
|
|
break;
|
|
case ContextType.TopLevel:
|
|
break;
|
|
default:
|
|
throw new BsonInternalException("Invalid ContextType.");
|
|
}
|
|
|
|
context.HasElements = true;
|
|
}
|
|
|
|
private void WriteStringHelper(
|
|
string value
|
|
) {
|
|
textWriter.Write("\"");
|
|
foreach (char c in value) {
|
|
switch (c) {
|
|
case '"': textWriter.Write("\\\""); break;
|
|
case '\\': textWriter.Write("\\\\"); break;
|
|
case '\b': textWriter.Write("\\b"); break;
|
|
case '\f': textWriter.Write("\\f"); break;
|
|
case '\n': textWriter.Write("\\n"); break;
|
|
case '\r': textWriter.Write("\\r"); break;
|
|
case '\t': textWriter.Write("\\t"); break;
|
|
default:
|
|
switch (char.GetUnicodeCategory(c)) {
|
|
case UnicodeCategory.UppercaseLetter:
|
|
case UnicodeCategory.LowercaseLetter:
|
|
case UnicodeCategory.TitlecaseLetter:
|
|
case UnicodeCategory.OtherLetter:
|
|
case UnicodeCategory.DecimalDigitNumber:
|
|
case UnicodeCategory.LetterNumber:
|
|
case UnicodeCategory.OtherNumber:
|
|
case UnicodeCategory.SpaceSeparator:
|
|
case UnicodeCategory.ConnectorPunctuation:
|
|
case UnicodeCategory.DashPunctuation:
|
|
case UnicodeCategory.OpenPunctuation:
|
|
case UnicodeCategory.ClosePunctuation:
|
|
case UnicodeCategory.InitialQuotePunctuation:
|
|
case UnicodeCategory.FinalQuotePunctuation:
|
|
case UnicodeCategory.OtherPunctuation:
|
|
case UnicodeCategory.MathSymbol:
|
|
case UnicodeCategory.CurrencySymbol:
|
|
case UnicodeCategory.ModifierSymbol:
|
|
case UnicodeCategory.OtherSymbol:
|
|
textWriter.Write(c);
|
|
break;
|
|
default:
|
|
textWriter.Write("\\u{0:x4}", (int) c);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
textWriter.Write("\"");
|
|
}
|
|
#endregion
|
|
}
|
|
}
|