Commit 7fc785c1 authored by csharptest's avatar csharptest Committed by rogerk

Reader/Writer implementations changed to use static factories

parent ea5fd37d
......@@ -131,30 +131,40 @@ namespace Google.ProtocolBuffers.ProtoBench
MemoryStream inputStream = new MemoryStream(inputData);
ByteString inputString = ByteString.CopyFrom(inputData);
IMessage sampleMessage = defaultMessage.WeakCreateBuilderForType().WeakMergeFrom(inputString, registry).WeakBuild();
StringWriter temp = new StringWriter();
new XmlFormatWriter(temp).WriteMessage(sampleMessage);
string xmlMessageText = temp.ToString();
temp = new StringWriter();
new JsonFormatWriter(temp).WriteMessage(sampleMessage);
string jsonMessageText = temp.ToString();
byte[] jsonBytes /*no pun intended*/ = Encoding.UTF8.GetBytes(jsonMessageText);
byte[] jsonBytes, xmlBytes;/*no pun intended, well... maybe for xml*/
using (MemoryStream temp = new MemoryStream())
{
XmlFormatWriter.CreateInstance(temp).WriteMessage(sampleMessage);
xmlBytes = temp.ToArray();
}
using (MemoryStream temp = new MemoryStream())
{
JsonFormatWriter.CreateInstance(temp).WriteMessage(sampleMessage);
jsonBytes = temp.ToArray();
}
IDictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
new DictionaryWriter(dictionary).WriteMessage(sampleMessage);
//Serializers
if(!FastTest) RunBenchmark("Serialize to byte string", inputData.Length, () => sampleMessage.ToByteString());
RunBenchmark("Serialize to byte array", inputData.Length, () => sampleMessage.ToByteArray());
if (!FastTest) RunBenchmark("Serialize to memory stream", inputData.Length,
() => sampleMessage.WriteTo(new MemoryStream()));
RunBenchmark("Serialize to xml", xmlMessageText.Length, () => new XmlFormatWriter(new StringWriter()).WriteMessage(sampleMessage));
RunBenchmark("Serialize to json", jsonMessageText.Length, () => new JsonFormatWriter(new StringWriter()).WriteMessage(sampleMessage));
RunBenchmark("Serialize to json via xml", jsonMessageText.Length,
() => new XmlFormatWriter(JsonReaderWriterFactory.CreateJsonWriter(new MemoryStream(), Encoding.UTF8))
{ Options = XmlWriterOptions.OutputJsonTypes }.WriteMessage(sampleMessage)
RunBenchmark("Serialize to xml", xmlBytes.Length, () =>
{
XmlFormatWriter.CreateInstance(new MemoryStream(), Encoding.UTF8).WriteMessage(sampleMessage);
} );
RunBenchmark("Serialize to json", jsonBytes.Length, () =>
{
JsonFormatWriter.CreateInstance(new MemoryStream()).WriteMessage(sampleMessage);
});
RunBenchmark("Serialize to json via xml", jsonBytes.Length,
() =>
XmlFormatWriter.CreateInstance(JsonReaderWriterFactory.CreateJsonWriter(new MemoryStream(), Encoding.UTF8))
.SetOptions(XmlWriterOptions.OutputJsonTypes)
.WriteMessage(sampleMessage)
);
RunBenchmark("Serialize to dictionary", sampleMessage.SerializedSize, () => new DictionaryWriter().WriteMessage(sampleMessage));
......@@ -179,12 +189,11 @@ namespace Google.ProtocolBuffers.ProtoBench
.WeakBuild();
});
RunBenchmark("Deserialize from xml", xmlMessageText.Length, () => new XmlFormatReader(xmlMessageText).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from json", jsonMessageText.Length, () => new JsonFormatReader(jsonMessageText).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from json via xml", jsonMessageText.Length,
() => new XmlFormatReader(JsonReaderWriterFactory.CreateJsonReader(jsonBytes, System.Xml.XmlDictionaryReaderQuotas.Max))
{ Options = XmlReaderOptions.ReadNestedArrays }
.Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from xml", xmlBytes.Length, () => XmlFormatReader.CreateInstance(xmlBytes).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from json", jsonBytes.Length, () => JsonFormatReader.CreateInstance(jsonBytes).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from json via xml", jsonBytes.Length,
() => XmlFormatReader.CreateInstance(JsonReaderWriterFactory.CreateJsonReader(jsonBytes, System.Xml.XmlDictionaryReaderQuotas.Max))
.SetOptions(XmlReaderOptions.ReadNestedArrays).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
RunBenchmark("Deserialize from dictionary", sampleMessage.SerializedSize, () => new DictionaryReader(dictionary).Merge(defaultMessage.WeakCreateBuilderForType()).WeakBuild());
......
......@@ -56,15 +56,9 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Runtime.Serialization, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.ServiceModel.Web" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
......@@ -105,11 +99,11 @@
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
......@@ -71,5 +71,117 @@ namespace Google.ProtocolBuffers.CompatTests
Assert.AreEqual(TestResources.google_message2, copy.ToByteArray());
}
#region Test message builders
private static TestAllTypes.Builder AddAllTypes(TestAllTypes.Builder builder)
{
return builder.SetOptionalInt32(1001)
.SetOptionalInt64(1001)
.SetOptionalUint32(1001)
.SetOptionalUint64(1001)
.SetOptionalSint32(-1001)
.SetOptionalSint64(-1001)
.SetOptionalFixed32(1001)
.SetOptionalFixed64(1001)
.SetOptionalSfixed32(-1001)
.SetOptionalSfixed64(-1001)
.SetOptionalFloat(1001.1001f)
.SetOptionalDouble(1001.1001)
.SetOptionalBool(true)
.SetOptionalString("this is a string value")
.SetOptionalBytes(ByteString.CopyFromUtf8("this is an array of bytes"))
.SetOptionalGroup(new TestAllTypes.Types.OptionalGroup.Builder().SetA(1001))
.SetOptionalNestedMessage(new TestAllTypes.Types.NestedMessage.Builder().SetBb(1001))
.SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.FOO)
;
}
private static TestAllTypes.Builder AddRepeatedTypes(TestAllTypes.Builder builder, int size)
{
//repeated values
for (int i = 0; i < size; i++)
builder.AddRepeatedInt32(1001 + i)
.AddRepeatedInt64(1001)
.AddRepeatedUint32(1001)
.AddRepeatedUint64(1001)
.AddRepeatedSint32(-1001)
.AddRepeatedSint64(-1001)
.AddRepeatedFixed32(1001)
.AddRepeatedFixed64(1001)
.AddRepeatedSfixed32(-1001)
.AddRepeatedSfixed64(-1001)
.AddRepeatedFloat(1001.1001f)
.AddRepeatedDouble(1001.1001)
.AddRepeatedBool(true)
.AddRepeatedString("this is a string value")
.AddRepeatedBytes(ByteString.CopyFromUtf8("this is an array of bytes"))
.AddRepeatedGroup(new TestAllTypes.Types.RepeatedGroup.Builder().SetA(1001))
.AddRepeatedNestedMessage(new TestAllTypes.Types.NestedMessage.Builder().SetBb(1001))
.AddRepeatedNestedEnum(TestAllTypes.Types.NestedEnum.FOO)
;
return builder;
}
private static TestPackedTypes.Builder AddPackedTypes(TestPackedTypes.Builder builder, int size)
{
for(int i=0; i < size; i++ )
builder.AddPackedInt32(1001)
.AddPackedInt64(1001)
.AddPackedUint32(1001)
.AddPackedUint64(1001)
.AddPackedSint32(-1001)
.AddPackedSint64(-1001)
.AddPackedFixed32(1001)
.AddPackedFixed64(1001)
.AddPackedSfixed32(-1001)
.AddPackedSfixed64(-1001)
.AddPackedFloat(1001.1001f)
.AddPackedDouble(1001.1001)
.AddPackedBool(true)
.AddPackedEnum(ForeignEnum.FOREIGN_FOO)
;
return builder;
}
#endregion
[Test]
public void TestRoundTripAllTypes()
{
TestAllTypes msg = AddAllTypes(new TestAllTypes.Builder()).Build();
object content = SerializeMessage<TestAllTypes, TestAllTypes.Builder>(msg);
TestAllTypes copy = DeerializeMessage<TestAllTypes, TestAllTypes.Builder>(content, TestAllTypes.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
AssertOutputEquals(content, SerializeMessage<TestAllTypes, TestAllTypes.Builder>(copy));
Assert.AreEqual(msg.ToByteArray(), copy.ToByteArray());
}
[Test]
public void TestRoundTripRepeatedTypes()
{
TestAllTypes msg = AddRepeatedTypes(new TestAllTypes.Builder(), 5).Build();
object content = SerializeMessage<TestAllTypes, TestAllTypes.Builder>(msg);
TestAllTypes copy = DeerializeMessage<TestAllTypes, TestAllTypes.Builder>(content, TestAllTypes.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
AssertOutputEquals(content, SerializeMessage<TestAllTypes, TestAllTypes.Builder>(copy));
Assert.AreEqual(msg.ToByteArray(), copy.ToByteArray());
}
[Test]
public void TestRoundTripPackedTypes()
{
TestPackedTypes msg = AddPackedTypes(new TestPackedTypes.Builder(), 5).Build();
object content = SerializeMessage<TestPackedTypes, TestPackedTypes.Builder>(msg);
TestPackedTypes copy = DeerializeMessage<TestPackedTypes, TestPackedTypes.Builder>(content, TestPackedTypes.CreateBuilder(), ExtensionRegistry.Empty).Build();
Assert.AreEqual(msg, copy);
AssertOutputEquals(content, SerializeMessage<TestPackedTypes, TestPackedTypes.Builder>(copy));
Assert.AreEqual(msg.ToByteArray(), copy.ToByteArray());
}
}
}
......@@ -11,7 +11,7 @@ namespace Google.ProtocolBuffers.CompatTests
protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
{
StringWriter sw = new StringWriter();
new JsonFormatWriter(sw)
JsonFormatWriter.CreateInstance(sw)
.Formatted()
.WriteMessage(message);
return sw.ToString();
......@@ -19,7 +19,7 @@ namespace Google.ProtocolBuffers.CompatTests
protected override TBuilder DeerializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)
{
new JsonFormatReader((string)message).Merge(builder);
JsonFormatReader.CreateInstance((string)message).Merge(builder);
return builder;
}
}
......
......@@ -10,14 +10,14 @@ namespace Google.ProtocolBuffers.CompatTests
protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
{
StringWriter text = new StringWriter();
XmlFormatWriter writer = new XmlFormatWriter(text);
XmlFormatWriter writer = XmlFormatWriter.CreateInstance(text);
writer.WriteMessage("root", message);
return text.ToString();
}
protected override TBuilder DeerializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)
{
XmlFormatReader reader = new XmlFormatReader((string)message);
XmlFormatReader reader = XmlFormatReader.CreateInstance((string)message);
return reader.Merge("root", builder, registry);
}
}
......
......@@ -14,7 +14,7 @@ namespace Google.ProtocolBuffers
protected void FormatterAssert<TMessage>(TMessage message, params string[] expecting) where TMessage : IMessageLite
{
StringWriter sw = new StringWriter();
new JsonFormatWriter(sw).WriteMessage(message);
JsonFormatWriter.CreateInstance(sw).WriteMessage(message);
Content = sw.ToString();
......@@ -22,7 +22,7 @@ namespace Google.ProtocolBuffers
UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);
IMessageLite copy =
new JsonFormatReader(Content)
JsonFormatReader.CreateInstance(Content)
.Merge(message.WeakCreateBuilderForType(), registry).WeakBuild();
Assert.AreEqual(typeof(TMessage), copy.GetType());
......@@ -44,12 +44,12 @@ namespace Google.ProtocolBuffers
.Build();
StringWriter sw = new StringWriter();
new JsonFormatWriter(sw).Formatted()
JsonFormatWriter.CreateInstance(sw).Formatted()
.WriteMessage(message);
string json = sw.ToString();
TestXmlMessage copy = new JsonFormatReader(json)
TestXmlMessage copy = JsonFormatReader.CreateInstance(json)
.Merge(TestXmlMessage.CreateBuilder()).Build();
Assert.AreEqual(message, copy);
}
......@@ -240,11 +240,11 @@ namespace Google.ProtocolBuffers
.ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum)
.Build();
JsonFormatWriter writer = new JsonFormatWriter();
JsonFormatWriter writer = JsonFormatWriter.CreateInstance();
writer.WriteMessage(original);
Content = writer.ToString();
IMessageLite copy = new JsonFormatReader(Content)
IMessageLite copy = JsonFormatReader.CreateInstance(Content)
.Merge(message.CreateBuilderForType()).Build();
Assert.AreNotEqual(original, message);
......@@ -255,8 +255,8 @@ namespace Google.ProtocolBuffers
public void TestMergeFields()
{
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
builder.MergeFrom(new JsonFormatReader("\"valid\": true"));
builder.MergeFrom(new JsonFormatReader("\"text\": \"text\", \"number\": \"411\""));
builder.MergeFrom(JsonFormatReader.CreateInstance("\"valid\": true"));
builder.MergeFrom(JsonFormatReader.CreateInstance("\"text\": \"text\", \"number\": \"411\""));
Assert.AreEqual(true, builder.Valid);
Assert.AreEqual("text", builder.Text);
Assert.AreEqual(411, builder.Number);
......@@ -264,7 +264,7 @@ namespace Google.ProtocolBuffers
[Test]
public void TestMessageArray()
{
JsonFormatWriter writer = new JsonFormatWriter().Formatted();
JsonFormatWriter writer = JsonFormatWriter.CreateInstance().Formatted();
using (writer.StartArray())
{
writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(1).AddTextlines("a").Build());
......@@ -272,7 +272,7 @@ namespace Google.ProtocolBuffers
writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(3).AddTextlines("c").Build());
}
string json = writer.ToString();
JsonFormatReader reader = new JsonFormatReader(json);
JsonFormatReader reader = JsonFormatReader.CreateInstance(json);
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
int ordinal = 0;
......@@ -288,7 +288,7 @@ namespace Google.ProtocolBuffers
[Test]
public void TestNestedMessageArray()
{
JsonFormatWriter writer = new JsonFormatWriter();
JsonFormatWriter writer = JsonFormatWriter.CreateInstance();
using (writer.StartArray())
{
using (writer.StartArray())
......@@ -300,7 +300,7 @@ namespace Google.ProtocolBuffers
writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(3).AddTextlines("c").Build());
}
string json = writer.ToString();
JsonFormatReader reader = new JsonFormatReader(json);
JsonFormatReader reader = JsonFormatReader.CreateInstance(json);
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
int ordinal = 0;
......@@ -317,25 +317,25 @@ namespace Google.ProtocolBuffers
[Test, ExpectedException(typeof(FormatException))]
public void FailWithEmptyText()
{
new JsonFormatReader("")
JsonFormatReader.CreateInstance("")
.Merge(TestXmlMessage.CreateBuilder());
}
[Test, ExpectedException(typeof(FormatException))]
public void FailWithUnexpectedValue()
{
new JsonFormatReader("{{}}")
JsonFormatReader.CreateInstance("{{}}")
.Merge(TestXmlMessage.CreateBuilder());
}
[Test, ExpectedException(typeof(FormatException))]
public void FailWithUnQuotedName()
{
new JsonFormatReader("{name:{}}")
JsonFormatReader.CreateInstance("{name:{}}")
.Merge(TestXmlMessage.CreateBuilder());
}
[Test, ExpectedException(typeof(FormatException))]
public void FailWithUnexpectedType()
{
new JsonFormatReader("{\"valid\":{}}")
JsonFormatReader.CreateInstance("{\"valid\":{}}")
.Merge(TestXmlMessage.CreateBuilder());
}
}
......
......@@ -64,7 +64,7 @@ namespace Google.ProtocolBuffers.Serialization
try
{
if (obj is IConvertible)
value = (T)Convert.ChangeType(obj, typeof(T));
value = (T)Convert.ChangeType(obj, typeof(T), System.Globalization.CultureInfo.InvariantCulture);
else
value = (T)obj;
}
......@@ -186,8 +186,17 @@ namespace Google.ProtocolBuffers.Serialization
object[] array = null;
if (GetValue(ref array))
{
foreach (T item in array)
items.Add(item);
if (typeof(T) == typeof(ByteString))
{
ICollection<ByteString> output = (ICollection<ByteString>)items;
foreach (byte[] item in array)
output.Add(ByteString.CopyFrom(item));
}
else
{
foreach (T item in array)
items.Add(item);
}
return true;
}
return false;
......
......@@ -10,34 +10,50 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary>
public class JsonFormatReader : AbstractTextReader
{
private readonly JsonTextCursor _input;
private readonly JsonCursor _input;
private readonly Stack<int> _stopChar;
enum ReaderState { Start, BeginValue, EndValue, BeginObject, BeginArray }
string _current;
ReaderState _state;
/// <summary>
/// Constructs a JsonFormatReader to parse Json into a message, this method does not use text encoding, all bytes MUST
/// represent ASCII character values.
/// </summary>
public static JsonFormatReader CreateInstance(Stream stream) { return new JsonFormatReader(JsonCursor.CreateInstance(stream)); }
/// <summary>
/// Constructs a JsonFormatReader to parse Json into a message, this method does not use text encoding, all bytes MUST
/// represent ASCII character values.
/// </summary>
public static JsonFormatReader CreateInstance(byte[] bytes) { return new JsonFormatReader(JsonCursor.CreateInstance(bytes)); }
/// <summary>
/// Constructs a JsonFormatReader to parse Json into a message
/// </summary>
public JsonFormatReader(string jsonText)
{
_input = new JsonTextCursor(jsonText.ToCharArray());
_stopChar = new Stack<int>();
_stopChar.Push(-1);
_state = ReaderState.Start;
}
public static JsonFormatReader CreateInstance(string jsonText) { return new JsonFormatReader(JsonCursor.CreateInstance(jsonText)); }
/// <summary>
/// Constructs a JsonFormatReader to parse Json into a message
/// </summary>
public JsonFormatReader(TextReader input)
public static JsonFormatReader CreateInstance(TextReader input) { return new JsonFormatReader(JsonCursor.CreateInstance(input)); }
/// <summary>
/// Constructs a JsonFormatReader to parse Json into a message
/// </summary>
internal JsonFormatReader(JsonCursor input)
{
_input = new JsonTextCursor(input);
_input = input;
_stopChar = new Stack<int>();
_stopChar.Push(-1);
_state = ReaderState.Start;
}
/// <summary>
/// Constructs a JsonFormatReader to parse Json into a message
/// </summary>
protected JsonFormatReader(TextReader input)
: this(JsonCursor.CreateInstance(input))
{ }
/// <summary>
/// Returns true if the reader is currently on an array element
/// </summary>
......@@ -115,18 +131,18 @@ namespace Google.ProtocolBuffers.Serialization
protected override bool ReadAsText(ref string value, Type typeInfo)
{
object temp;
JsonTextCursor.JsType type = _input.ReadVariant(out temp);
JsonCursor.JsType type = _input.ReadVariant(out temp);
_state = ReaderState.EndValue;
_input.Assert(type != JsonTextCursor.JsType.Array && type != JsonTextCursor.JsType.Object, "Encountered {0} while expecting {1}", type, typeInfo);
if (type == JsonTextCursor.JsType.Null)
_input.Assert(type != JsonCursor.JsType.Array && type != JsonCursor.JsType.Object, "Encountered {0} while expecting {1}", type, typeInfo);
if (type == JsonCursor.JsType.Null)
return false;
if (type == JsonTextCursor.JsType.True) value = "1";
else if (type == JsonTextCursor.JsType.False) value = "0";
if (type == JsonCursor.JsType.True) value = "1";
else if (type == JsonCursor.JsType.False) value = "0";
else value = temp as string;
//exponent representation of integer number:
if (value != null && type == JsonTextCursor.JsType.Number &&
if (value != null && type == JsonCursor.JsType.Number &&
(typeInfo != typeof(double) && typeInfo != typeof(float)) &&
value.IndexOf("e", StringComparison.OrdinalIgnoreCase) > 0)
{
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.Serialization
......@@ -10,81 +11,178 @@ namespace Google.ProtocolBuffers.Serialization
/// you may also use the XmlFormatWriter with an XmlWriter created by the
/// <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory">JsonReaderWriterFactory</see>.
/// </summary>
public class JsonFormatWriter : AbstractTextWriter
public abstract class JsonFormatWriter : AbstractTextWriter
{
private readonly char[] _buffer;
private readonly TextWriter _output;
private readonly List<int> _counter;
private bool _isArray;
int _bufferPos;
/// <summary>
/// Constructs a JsonFormatWriter to output to a new instance of a StringWriter, use
/// the ToString() member to extract the final Json on completion.
/// </summary>
public JsonFormatWriter() : this(new StringWriter()) { }
/// <summary>
/// Constructs a JsonFormatWriter to output to the given text writer
/// </summary>
public JsonFormatWriter(TextWriter output)
#region buffering implementations
private class JsonTextWriter : JsonFormatWriter
{
_buffer = new char[4096];
_bufferPos = 0;
_output = output;
_counter = new List<int>();
_counter.Add(0);
}
private readonly char[] _buffer;
private TextWriter _output;
int _bufferPos;
public JsonTextWriter(TextWriter output)
{
_buffer = new char[4096];
_bufferPos = 0;
_output = output;
_counter.Add(0);
}
private void WriteToOutput(string format, params object[] args)
{ WriteToOutput(String.Format(format, args)); }
/// <summary>
/// Returns the output of TextWriter.ToString() where TextWriter is the ctor argument.
/// </summary>
public override string ToString()
{
Flush();
private void WriteToOutput(string text)
{ WriteToOutput(text.ToCharArray(), 0, text.Length); }
if (_output != null)
return _output.ToString();
private void WriteToOutput(char[] chars, int offset, int len)
{
if (_bufferPos + len >= _buffer.Length)
Flush();
if (len < _buffer.Length)
return new String(_buffer, 0, _bufferPos);
}
protected override void WriteToOutput(char[] chars, int offset, int len)
{
if (len <= 12)
if (_bufferPos + len >= _buffer.Length)
{
if (_output == null)
_output = new StringWriter(new System.Text.StringBuilder(_buffer.Length * 2 + len));
Flush();
}
if (len < _buffer.Length)
{
int stop = offset + len;
for (int i = offset; i < stop; i++)
_buffer[_bufferPos++] = chars[i];
if (len <= 12)
{
int stop = offset + len;
for (int i = offset; i < stop; i++)
_buffer[_bufferPos++] = chars[i];
}
else
{
Buffer.BlockCopy(chars, offset << 1, _buffer, _bufferPos << 1, len << 1);
_bufferPos += len;
}
}
else
_output.Write(chars, offset, len);
}
protected override void WriteToOutput(char ch)
{
if (_bufferPos >= _buffer.Length)
Flush();
_buffer[_bufferPos++] = ch;
}
public override void Flush()
{
if (_bufferPos > 0 && _output != null)
{
Buffer.BlockCopy(chars, offset << 1, _buffer, _bufferPos << 1, len << 1);
_bufferPos += len;
_output.Write(_buffer, 0, _bufferPos);
_bufferPos = 0;
}
base.Flush();
}
else
_output.Write(chars, offset, len);
}
private void WriteToOutput(char ch)
private class JsonStreamWriter : JsonFormatWriter
{
if (_bufferPos >= _buffer.Length)
Flush();
_buffer[_bufferPos++] = ch;
}
#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
static readonly Encoding Encoding = Encoding.UTF8;
#else
static readonly Encoding Encoding = Encoding.ASCII;
#endif
private readonly byte[] _buffer;
private Stream _output;
int _bufferPos;
public override void Flush()
{
if (_bufferPos > 0)
public JsonStreamWriter(Stream output)
{
_output.Write(_buffer, 0, _bufferPos);
_buffer = new byte[8192];
_bufferPos = 0;
_output = output;
_counter.Add(0);
}
protected override void WriteToOutput(char[] chars, int offset, int len)
{
if (_bufferPos + len >= _buffer.Length)
Flush();
if (len < _buffer.Length)
{
if (len <= 12)
{
int stop = offset + len;
for (int i = offset; i < stop; i++)
_buffer[_bufferPos++] = (byte)chars[i];
}
else
{
_bufferPos += Encoding.GetBytes(chars, offset, len, _buffer, _bufferPos);
}
}
else
{
byte[] temp = Encoding.GetBytes(chars, offset, len);
_output.Write(temp, 0, temp.Length);
}
}
protected override void WriteToOutput(char ch)
{
if (_bufferPos >= _buffer.Length)
Flush();
_buffer[_bufferPos++] = (byte)ch;
}
base.Flush();
public override void Flush()
{
if (_bufferPos > 0 && _output != null)
{
_output.Write(_buffer, 0, _bufferPos);
_bufferPos = 0;
}
base.Flush();
}
}
#endregion
private readonly List<int> _counter;
private bool _isArray;
/// <summary>
/// Constructs a JsonFormatWriter, use the ToString() member to extract the final Json on completion.
/// </summary>
protected JsonFormatWriter()
{
_counter = new List<int>();
}
/// <summary>
/// Returns the output of TextWriter.ToString() where TextWriter is the ctor argument.
/// Constructs a JsonFormatWriter, use ToString() to extract the final output
/// </summary>
public override string ToString()
{ Flush(); return _output.ToString(); }
public static JsonFormatWriter CreateInstance() { return new JsonTextWriter(null); }
/// <summary>
/// Constructs a JsonFormatWriter to output to the given text writer
/// </summary>
public static JsonFormatWriter CreateInstance(TextWriter output) { return new JsonTextWriter(output); }
/// <summary>
/// Constructs a JsonFormatWriter to output to the given stream
/// </summary>
public static JsonFormatWriter CreateInstance(Stream output) { return new JsonStreamWriter(output); }
/// <summary> Write to the output stream </summary>
protected void WriteToOutput(string format, params object[] args)
{ WriteToOutput(String.Format(format, args)); }
/// <summary> Write to the output stream </summary>
protected void WriteToOutput(string text)
{ WriteToOutput(text.ToCharArray(), 0, text.Length); }
/// <summary> Write to the output stream </summary>
protected abstract void WriteToOutput(char ch);
/// <summary> Write to the output stream </summary>
protected abstract void WriteToOutput(char[] chars, int offset, int len);
/// <summary> Sets the output formatting to use Environment.NewLine with 4-character indentions </summary>
public JsonFormatWriter Formatted()
......
......@@ -9,52 +9,115 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary>
/// JSon Tokenizer used by JsonFormatReader
/// </summary>
class JsonTextCursor
abstract class JsonCursor
{
public enum JsType { String, Number, Object, Array, True, False, Null }
private readonly char[] _buffer;
private int _bufferPos;
private readonly TextReader _input;
private int _lineNo, _linePos;
public JsonTextCursor(char[] input)
#region Buffering implementations
class JsonStreamCursor : JsonCursor
{
_input = null;
_buffer = input;
_bufferPos = 0;
_next = Peek();
_lineNo = 1;
}
private readonly byte[] _buffer;
private int _bufferPos;
private readonly Stream _input;
public JsonTextCursor(TextReader input)
{
_input = input;
_next = Peek();
_lineNo = 1;
public JsonStreamCursor(Stream input)
{
_input = input;
_next = _input.ReadByte();
}
public JsonStreamCursor(byte[] input)
{
_input = null;
_buffer = input;
_next = _buffer[_bufferPos];
}
protected override int Peek()
{
if (_input != null)
return _next;
else if (_bufferPos < _buffer.Length)
return _buffer[_bufferPos];
else
return -1;
}
protected override int Read()
{
if (_input != null)
{
int result = _next;
_next = _input.ReadByte();
return result;
}
else if (_bufferPos < _buffer.Length)
return _buffer[_bufferPos++];
else
return -1;
}
}
private int Peek()
class JsonTextCursor : JsonCursor
{
if (_input != null)
return _input.Peek();
else if (_bufferPos < _buffer.Length)
return _buffer[_bufferPos];
else
return -1;
private readonly char[] _buffer;
private int _bufferPos;
private readonly TextReader _input;
public JsonTextCursor(char[] input)
{
_input = null;
_buffer = input;
_bufferPos = 0;
_next = Peek();
}
public JsonTextCursor(TextReader input)
{
_input = input;
_next = Peek();
}
protected override int Peek()
{
if (_input != null)
return _input.Peek();
else if (_bufferPos < _buffer.Length)
return _buffer[_bufferPos];
else
return -1;
}
protected override int Read()
{
if (_input != null)
return _input.Read();
else if (_bufferPos < _buffer.Length)
return _buffer[_bufferPos++];
else
return -1;
}
}
#endregion
protected int _next;
private int _lineNo, _linePos;
private int Read()
public static JsonCursor CreateInstance(byte[] input) { return new JsonStreamCursor(input); }
public static JsonCursor CreateInstance(Stream input) { return new JsonStreamCursor(input); }
public static JsonCursor CreateInstance(string input) { return new JsonTextCursor(input.ToCharArray()); }
public static JsonCursor CreateInstance(TextReader input) { return new JsonTextCursor(input); }
protected JsonCursor()
{
if (_input != null)
return _input.Read();
else if (_bufferPos < _buffer.Length)
return _buffer[_bufferPos++];
else
return -1;
_lineNo = 1;
_linePos = 0;
}
/// <summary>Returns the next character without actually 'reading' it</summary>
protected abstract int Peek();
/// <summary>Reads the next character in the input</summary>
protected abstract int Read();
int _next;
public Char NextChar { get { SkipWhitespace(); return (char)_next; } }
#region Assert(...)
......@@ -62,8 +125,8 @@ namespace Google.ProtocolBuffers.Serialization
private string CharDisplay(int ch)
{
return ch == -1 ? "EOF" :
(ch > 32 && ch < 127) ? String.Format("'{0}'", (char)ch) :
String.Format("'\\u{0:x4}'", ch);
(ch > 32 && ch < 127) ? String.Format("'{0}'", (char)ch) :
String.Format("'\\u{0:x4}'", ch);
}
[System.Diagnostics.DebuggerNonUserCode]
private void Assert(bool cond, char expected)
......
......@@ -25,33 +25,41 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary>
/// Constructs the XmlFormatReader using the stream provided as the xml
/// </summary>
public XmlFormatReader(Stream input) : this(XmlReader.Create(input, DefaultSettings)) { }
public static XmlFormatReader CreateInstance(byte[] input) { return new XmlFormatReader(XmlReader.Create(new MemoryStream(input, false), DefaultSettings)); }
/// <summary>
/// Constructs the XmlFormatReader using the stream provided as the xml
/// </summary>
public static XmlFormatReader CreateInstance(Stream input) { return new XmlFormatReader(XmlReader.Create(input, DefaultSettings)); }
/// <summary>
/// Constructs the XmlFormatReader using the string provided as the xml to be read
/// </summary>
public XmlFormatReader(String input) : this(XmlReader.Create(new StringReader(input))) { }
public static XmlFormatReader CreateInstance(String input) { return new XmlFormatReader(XmlReader.Create(new StringReader(input), DefaultSettings)); }
/// <summary>
/// Constructs the XmlFormatReader using the xml in the TextReader
/// </summary>
public XmlFormatReader(TextReader input) : this(XmlReader.Create(input)) { }
public static XmlFormatReader CreateInstance(TextReader input) { return new XmlFormatReader(XmlReader.Create(input, DefaultSettings)); }
/// <summary>
/// Constructs the XmlFormatReader with the XmlReader
/// </summary>
public XmlFormatReader(XmlReader input) : this(input, XmlReaderOptions.None) { }
public static XmlFormatReader CreateInstance(XmlReader input) { return new XmlFormatReader(input); }
/// <summary>
/// Constructs the XmlFormatReader with the XmlReader and options
/// </summary>
public XmlFormatReader(XmlReader input, XmlReaderOptions options)
protected XmlFormatReader(XmlReader input)
{
_input = input;
_rootElementName = DefaultRootElementName;
Options = options;
Options = XmlReaderOptions.None;
}
/// <summary>
/// Gets or sets the options to use when reading the xml
/// </summary>
public XmlReaderOptions Options { get; set; }
/// <summary>
/// Sets the options to use while generating the XML
/// </summary>
public XmlFormatReader SetOptions(XmlReaderOptions options) { Options = options; return this; }
/// <summary>
/// Gets or sets the default element name to use when using the Merge&lt;TBuilder>()
......@@ -64,7 +72,7 @@ namespace Google.ProtocolBuffers.Serialization
private XmlFormatReader CloneWith(XmlReader rdr)
{
return new XmlFormatReader(rdr, Options);
return new XmlFormatReader(rdr).SetOptions(Options);
}
private void NextElement()
{
......
using System;
using System.IO;
using System.Text;
using System.Xml;
using Google.ProtocolBuffers.Descriptors;
......@@ -17,23 +18,29 @@ namespace Google.ProtocolBuffers.Serialization
private readonly XmlWriter _output;
private string _rootElementName;
static XmlWriterSettings DefaultSettings
static XmlWriterSettings DefaultSettings(Encoding encoding)
{
get { return new XmlWriterSettings() {CheckCharacters = false, NewLineHandling = NewLineHandling.Entitize}; }
return new XmlWriterSettings() { CheckCharacters = false, NewLineHandling = NewLineHandling.Entitize, Encoding = encoding };
}
/// <summary>
/// Constructs the XmlFormatWriter to write to the given TextWriter
/// </summary>
public XmlFormatWriter(TextWriter output) : this(XmlWriter.Create(output, DefaultSettings)) { }
public static XmlFormatWriter CreateInstance(TextWriter output) { return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(output.Encoding))); }
/// <summary>
/// Constructs the XmlFormatWriter to write to the given stream
/// </summary>
public XmlFormatWriter(Stream output) : this(XmlWriter.Create(output, DefaultSettings)) { }
public static XmlFormatWriter CreateInstance(Stream output) { return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(Encoding.UTF8))); }
/// <summary>
/// Constructs the XmlFormatWriter to write to the given stream
/// </summary>
public static XmlFormatWriter CreateInstance(Stream output, Encoding encoding) { return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(encoding))); }
/// <summary>
/// Constructs the XmlFormatWriter to write to the given XmlWriter
/// </summary>
public XmlFormatWriter(XmlWriter output)
public static XmlFormatWriter CreateInstance(XmlWriter output) { return new XmlFormatWriter(output); }
protected XmlFormatWriter(XmlWriter output)
{
_output = output;
_rootElementName = DefaultRootElementName;
......@@ -61,6 +68,10 @@ namespace Google.ProtocolBuffers.Serialization
/// Gets or sets the options to use while generating the XML
/// </summary>
public XmlWriterOptions Options { get; set; }
/// <summary>
/// Sets the options to use while generating the XML
/// </summary>
public XmlFormatWriter SetOptions(XmlWriterOptions options) { Options = options; return this; }
private bool TestOption(XmlWriterOptions option) { return (Options & option) != 0; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment