From b49d3c7834c9448e137d88c510f30963661ff7d9 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Tue, 3 Nov 2009 16:51:01 +0000 Subject: Support Compact Framework 3.5 --- src/ProtocolBuffers/CodedInputStream.cs | 2 +- src/ProtocolBuffers/CodedOutputStream.cs | 4 +- src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs | 9 +- .../FieldAccess/RepeatedMessageAccessor.cs | 2 +- .../FieldAccess/RepeatedPrimitiveAccessor.cs | 12 +- .../FieldAccess/SingleMessageAccessor.cs | 2 +- .../FieldAccess/SinglePrimitiveAccessor.cs | 8 +- src/ProtocolBuffers/FieldSet.cs | 6 +- src/ProtocolBuffers/GeneratedMessage.cs | 4 +- src/ProtocolBuffers/MessageStreamIterator.cs | 7 +- src/ProtocolBuffers/Properties/AssemblyInfo.cs | 2 + src/ProtocolBuffers/ProtocolBuffers.csproj | 2 +- src/ProtocolBuffers/ProtocolBuffersCF.csproj | 143 ++++++++++++++++++ src/ProtocolBuffers/SortedDictionary.cs | 160 --------------------- src/ProtocolBuffers/SortedList.cs | 160 +++++++++++++++++++++ src/ProtocolBuffers/UnknownFieldSet.cs | 5 +- 16 files changed, 339 insertions(+), 189 deletions(-) create mode 100644 src/ProtocolBuffers/ProtocolBuffersCF.csproj delete mode 100644 src/ProtocolBuffers/SortedDictionary.cs create mode 100644 src/ProtocolBuffers/SortedList.cs (limited to 'src/ProtocolBuffers') diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs index 0295d19c..a929df23 100644 --- a/src/ProtocolBuffers/CodedInputStream.cs +++ b/src/ProtocolBuffers/CodedInputStream.cs @@ -163,7 +163,7 @@ namespace Google.ProtocolBuffers { /// Read a double field from the stream. /// public double ReadDouble() { -#if SILVERLIGHT2 +#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35 byte[] bytes = ReadRawBytes(8); return BitConverter.ToDouble(bytes, 0); #else diff --git a/src/ProtocolBuffers/CodedOutputStream.cs b/src/ProtocolBuffers/CodedOutputStream.cs index bb5e6a20..a7e1eca6 100644 --- a/src/ProtocolBuffers/CodedOutputStream.cs +++ b/src/ProtocolBuffers/CodedOutputStream.cs @@ -332,7 +332,7 @@ namespace Google.ProtocolBuffers { /// public void WriteDoubleNoTag(double value) { // TODO(jonskeet): Test this on different endiannesses -#if SILVERLIGHT2 +#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35 byte[] bytes = BitConverter.GetBytes(value); WriteRawBytes(bytes, 0, 8); #else @@ -1140,4 +1140,4 @@ namespace Google.ProtocolBuffers { } } } -} \ No newline at end of file +} diff --git a/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs b/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs index c1c3670d..43036f94 100644 --- a/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs +++ b/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs @@ -64,13 +64,12 @@ namespace Google.ProtocolBuffers.FieldAccess { public static Func CreateUpcastDelegateImpl(MethodInfo method) { // Convert the reflection call into an open delegate, i.e. instead of calling x.Method() // we'll call getter(x). - Func getter = (Func)Delegate.CreateDelegate(typeof(Func), method); + Func getter = (Func)Delegate.CreateDelegate(typeof(Func), null, method); // Implicit upcast to object (within the delegate) return delegate(TSource source) { return getter(source); }; } - /// /// Creates a delegate which will execute the given method after casting the parameter /// down from object to the required parameter type. @@ -84,7 +83,7 @@ namespace Google.ProtocolBuffers.FieldAccess { public static Action CreateDowncastDelegateImpl(MethodInfo method) { // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll // call Method(x, y) - Action call = (Action) Delegate.CreateDelegate(typeof(Action), method); + Action call = (Action) Delegate.CreateDelegate(typeof(Action), null, method); return delegate(TSource source, object parameter) { call(source, (TParam)parameter); }; } @@ -103,7 +102,7 @@ namespace Google.ProtocolBuffers.FieldAccess { // Convert the reflection call into an open delegate, i.e. instead of calling x.Method(y) we'll // call Method(x, y) Func call = (Func) - Delegate.CreateDelegate(typeof(Func), method); + Delegate.CreateDelegate(typeof(Func), null, method); return delegate(TSource source, object parameter) { call(source, (TParam)parameter); }; } @@ -118,7 +117,7 @@ namespace Google.ProtocolBuffers.FieldAccess { } public static Func CreateStaticUpcastDelegateImpl(MethodInfo method) { - Func call = (Func)Delegate.CreateDelegate(typeof(Func), method); + Func call = (Func)Delegate.CreateDelegate(typeof(Func), null, method); return delegate { return (IBuilder)call(); }; } } diff --git a/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs index 5cca9748..893b0285 100644 --- a/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs +++ b/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs @@ -52,7 +52,7 @@ namespace Google.ProtocolBuffers.FieldAccess { private readonly Func createBuilderDelegate; internal RepeatedMessageAccessor(string name) : base(name) { - MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", Type.EmptyTypes); + MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", EmptyTypes); if (createBuilderMethod == null) { throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name); } diff --git a/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs b/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs index e5bb411a..6bae59cb 100644 --- a/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs +++ b/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs @@ -35,7 +35,7 @@ using System.Reflection; namespace Google.ProtocolBuffers.FieldAccess { /// - /// Accesor for a repeated field of type int, ByteString etc. + /// Accessor for a repeated field of type int, ByteString etc. /// internal class RepeatedPrimitiveAccessor : IFieldAccessor where TMessage : IMessage @@ -49,7 +49,9 @@ namespace Google.ProtocolBuffers.FieldAccess { private readonly Func countDelegate; private readonly MethodInfo getElementMethod; private readonly MethodInfo setElementMethod; - + + // Replacement for Type.EmptyTypes which apparently isn't available on the compact framework + internal static readonly Type[] EmptyTypes = new Type[0]; /// /// The CLR type of the field (int, the enum type, ByteString, the message etc). @@ -64,7 +66,7 @@ namespace Google.ProtocolBuffers.FieldAccess { PropertyInfo messageProperty = typeof(TMessage).GetProperty(name + "List"); PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name + "List"); PropertyInfo countProperty = typeof(TMessage).GetProperty(name + "Count"); - MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, Type.EmptyTypes); + MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, EmptyTypes); getElementMethod = typeof(TMessage).GetMethod("Get" + name, new Type[] { typeof(int) }); clrType = getElementMethod.ReturnType; MethodInfo addMethod = typeof(TBuilder).GetMethod("Add" + name, new Type[] { ClrType }); @@ -78,9 +80,9 @@ namespace Google.ProtocolBuffers.FieldAccess { || setElementMethod == null) { throw new ArgumentException("Not all required properties/methods available"); } - clearDelegate = (Func)Delegate.CreateDelegate(typeof(Func), clearMethod); + clearDelegate = (Func)Delegate.CreateDelegate(typeof(Func), null, clearMethod); countDelegate = (Func)Delegate.CreateDelegate - (typeof(Func), countProperty.GetGetMethod()); + (typeof(Func), null, countProperty.GetGetMethod()); getValueDelegate = ReflectionUtil.CreateUpcastDelegate(messageProperty.GetGetMethod()); addValueDelegate = ReflectionUtil.CreateDowncastDelegateIgnoringReturn(addMethod); getRepeatedWrapperDelegate = ReflectionUtil.CreateUpcastDelegate(builderProperty.GetGetMethod()); diff --git a/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs index 9ce2cbb1..ea422c94 100644 --- a/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs +++ b/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs @@ -48,7 +48,7 @@ namespace Google.ProtocolBuffers.FieldAccess { private readonly Func createBuilderDelegate; internal SingleMessageAccessor(string name) : base(name) { - MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", Type.EmptyTypes); + MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", EmptyTypes); if (createBuilderMethod == null) { throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name); } diff --git a/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs index 8b3153a1..1bc1d8ee 100644 --- a/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs +++ b/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs @@ -46,6 +46,8 @@ namespace Google.ProtocolBuffers.FieldAccess { private readonly Func hasDelegate; private readonly Func clearDelegate; + internal static readonly Type[] EmptyTypes = new Type[0]; + /// /// The CLR type of the field (int, the enum type, ByteString, the message etc). /// As declared by the property. @@ -59,13 +61,13 @@ namespace Google.ProtocolBuffers.FieldAccess { PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name); if (builderProperty == null) builderProperty = typeof(TBuilder).GetProperty(name); PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name); - MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, Type.EmptyTypes); + MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, EmptyTypes); if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null) { throw new ArgumentException("Not all required properties/methods available"); } clrType = messageProperty.PropertyType; - hasDelegate = (Func)Delegate.CreateDelegate(typeof(Func), hasProperty.GetGetMethod()); - clearDelegate = (Func)Delegate.CreateDelegate(typeof(Func), clearMethod); + hasDelegate = (Func)Delegate.CreateDelegate(typeof(Func), null, hasProperty.GetGetMethod()); + clearDelegate = (Func)Delegate.CreateDelegate(typeof(Func), null ,clearMethod); getValueDelegate = ReflectionUtil.CreateUpcastDelegate(messageProperty.GetGetMethod()); setValueDelegate = ReflectionUtil.CreateDowncastDelegate(builderProperty.GetSetMethod()); } diff --git a/src/ProtocolBuffers/FieldSet.cs b/src/ProtocolBuffers/FieldSet.cs index 0c5c63d9..7c373b95 100644 --- a/src/ProtocolBuffers/FieldSet.cs +++ b/src/ProtocolBuffers/FieldSet.cs @@ -65,8 +65,8 @@ namespace Google.ProtocolBuffers { } public static FieldSet CreateInstance() { - // Use SortedDictionary to keep fields in the canonical order - return new FieldSet(new SortedDictionary()); + // Use SortedList to keep fields in the canonical order + return new FieldSet(new SortedList()); } /// @@ -85,7 +85,7 @@ namespace Google.ProtocolBuffers { } if (hasRepeats) { - var tmp = new SortedDictionary(); + var tmp = new SortedList(); foreach (KeyValuePair entry in fields) { IList list = entry.Value as IList; tmp[entry.Key] = list == null ? entry.Value : Lists.AsReadOnly(list); diff --git a/src/ProtocolBuffers/GeneratedMessage.cs b/src/ProtocolBuffers/GeneratedMessage.cs index 1e336740..d60f2b9c 100644 --- a/src/ProtocolBuffers/GeneratedMessage.cs +++ b/src/ProtocolBuffers/GeneratedMessage.cs @@ -69,8 +69,8 @@ namespace Google.ProtocolBuffers { internal IDictionary GetMutableFieldMap() { - // Use a SortedDictionary so we'll end up serializing fields in order - var ret = new SortedDictionary(); + // Use a SortedList so we'll end up serializing fields in order + var ret = new SortedList(); MessageDescriptor descriptor = DescriptorForType; foreach (FieldDescriptor field in descriptor.Fields) { IFieldAccessor accessor = InternalFieldAccessors[field]; diff --git a/src/ProtocolBuffers/MessageStreamIterator.cs b/src/ProtocolBuffers/MessageStreamIterator.cs index 68519e0f..0466262b 100644 --- a/src/ProtocolBuffers/MessageStreamIterator.cs +++ b/src/ProtocolBuffers/MessageStreamIterator.cs @@ -54,6 +54,9 @@ namespace Google.ProtocolBuffers { private readonly ExtensionRegistry extensionRegistry; private readonly int sizeLimit; + // Type.EmptyTypes isn't present on the compact framework + private static readonly Type[] EmptyTypes = new Type[0]; + /// /// Delegate created via reflection trickery (once per type) to create a builder /// and read a message from a CodedInputStream with it. Note that unlike in Java, @@ -77,7 +80,7 @@ namespace Google.ProtocolBuffers { Type builderType = FindBuilderType(); // Yes, it's redundant to find this again, but it's only the once... - MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes); + MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", EmptyTypes); Delegate builderBuilder = Delegate.CreateDelegate( typeof(Func<>).MakeGenericType(builderType), null, createBuilderMethod); @@ -102,7 +105,7 @@ namespace Google.ProtocolBuffers { /// Works out the builder type for TMessage, or throws an ArgumentException to explain why it can't. /// private static Type FindBuilderType() { - MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes); + MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", EmptyTypes); if (createBuilderMethod == null) { throw new ArgumentException("Message type " + typeof(TMessage).FullName + " has no CreateBuilder method."); } diff --git a/src/ProtocolBuffers/Properties/AssemblyInfo.cs b/src/ProtocolBuffers/Properties/AssemblyInfo.cs index 8d587d18..7438aac1 100644 --- a/src/ProtocolBuffers/Properties/AssemblyInfo.cs +++ b/src/ProtocolBuffers/Properties/AssemblyInfo.cs @@ -64,7 +64,9 @@ using System.Runtime.CompilerServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] +#if !COMPACT_FRAMEWORK_35 [assembly: AssemblyFileVersion("1.0.0.0")] +#endif [assembly:InternalsVisibleTo("Google.ProtocolBuffers.Test,PublicKey="+ "00240000048000009400000006020000002400005253413100040000010001008179f2dd31a648"+ diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj index c58ac125..703a8235 100644 --- a/src/ProtocolBuffers/ProtocolBuffers.csproj +++ b/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -114,7 +114,7 @@ - + diff --git a/src/ProtocolBuffers/ProtocolBuffersCF.csproj b/src/ProtocolBuffers/ProtocolBuffersCF.csproj new file mode 100644 index 00000000..78b83838 --- /dev/null +++ b/src/ProtocolBuffers/ProtocolBuffersCF.csproj @@ -0,0 +1,143 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {49B51802-9D09-4AD8-A0EE-0DA704EFA379} + Library + Properties + Google.ProtocolBuffers + Google.ProtocolBuffers + {4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + PocketPC + b2c48bd2-963d-4549-9169-1fa021dce484 + 5.2 + compactframework + v3.5 + Windows Mobile 6 Professional SDK + + + + + true + full + false + bin\Debug\ + COMPACT_FRAMEWORK_35;DEBUG;TRACE;$(PlatformFamilyName) + true + true + prompt + 512 + 4 + Off + + + pdbonly + true + bin\Release\ + COMPACT_FRAMEWORK_35;TRACE;$(PlatformFamilyName) + true + true + prompt + 512 + 4 + Off + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ProtocolBuffers/SortedDictionary.cs b/src/ProtocolBuffers/SortedDictionary.cs deleted file mode 100644 index be0975b5..00000000 --- a/src/ProtocolBuffers/SortedDictionary.cs +++ /dev/null @@ -1,160 +0,0 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -#if SILVERLIGHT2 -using System.Collections; -using System.Collections.Generic; - -namespace Google.ProtocolBuffers -{ - /// - /// Dictionary implementation which always yields keys in sorted order. - /// This is not particularly efficient: it wraps a normal dictionary - /// for most operations, but sorts by key when either iterating or - /// fetching the Keys/Values properties. - /// This is only used for Silverlight, which doesn't have the normal - /// sorted collections. - /// - internal sealed class SortedDictionary : IDictionary - { - private readonly IDictionary wrapped = new Dictionary(); - - public void Add(TKey key, TValue value) - { - wrapped.Add(key, value); - } - - public bool ContainsKey(TKey key) - { - return wrapped.ContainsKey(key); - } - - public ICollection Keys - { - get - { - List keys = new List(wrapped.Count); - foreach (var pair in this) - { - keys.Add(pair.Key); - } - return keys; - } - } - - public bool Remove(TKey key) - { - return wrapped.Remove(key); - } - - public bool TryGetValue(TKey key, out TValue value) - { - return wrapped.TryGetValue(key, out value); - } - - public ICollection Values - { - get - { - List values = new List(wrapped.Count); - foreach (var pair in this) - { - values.Add(pair.Value); - } - return values; - } - } - - public TValue this[TKey key] - { - get - { - return wrapped[key]; - } - set - { - wrapped[key] = value; - } - } - - public void Add(KeyValuePair item) - { - wrapped.Add(item); - } - - public void Clear() - { - wrapped.Clear(); - } - - public bool Contains(KeyValuePair item) - { - return wrapped.Contains(item); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - wrapped.CopyTo(array, arrayIndex); - } - - public int Count - { - get { return wrapped.Count; } - } - - public bool IsReadOnly - { - get { return wrapped.IsReadOnly; } - } - - public bool Remove(KeyValuePair item) - { - return wrapped.Remove(item); - } - - public IEnumerator> GetEnumerator() - { - IComparer comparer = Comparer.Default; - var list = new List>(wrapped); - list.Sort((x, y) => comparer.Compare(x.Key, y.Key)); - return list.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} -#endif \ No newline at end of file diff --git a/src/ProtocolBuffers/SortedList.cs b/src/ProtocolBuffers/SortedList.cs new file mode 100644 index 00000000..e9f4458e --- /dev/null +++ b/src/ProtocolBuffers/SortedList.cs @@ -0,0 +1,160 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://github.com/jskeet/dotnet-protobufs/ +// Original C++/Java/Python code: +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +#if SILVERLIGHT2 +using System.Collections; +using System.Collections.Generic; + +namespace Google.ProtocolBuffers +{ + /// + /// Dictionary implementation which always yields keys in sorted order. + /// This is not particularly efficient: it wraps a normal dictionary + /// for most operations, but sorts by key when either iterating or + /// fetching the Keys/Values properties. + /// This is only used for Silverlight, which doesn't have the normal + /// sorted collections. + /// + internal sealed class SortedList : IDictionary + { + private readonly IDictionary wrapped = new Dictionary(); + + public void Add(TKey key, TValue value) + { + wrapped.Add(key, value); + } + + public bool ContainsKey(TKey key) + { + return wrapped.ContainsKey(key); + } + + public ICollection Keys + { + get + { + List keys = new List(wrapped.Count); + foreach (var pair in this) + { + keys.Add(pair.Key); + } + return keys; + } + } + + public bool Remove(TKey key) + { + return wrapped.Remove(key); + } + + public bool TryGetValue(TKey key, out TValue value) + { + return wrapped.TryGetValue(key, out value); + } + + public ICollection Values + { + get + { + List values = new List(wrapped.Count); + foreach (var pair in this) + { + values.Add(pair.Value); + } + return values; + } + } + + public TValue this[TKey key] + { + get + { + return wrapped[key]; + } + set + { + wrapped[key] = value; + } + } + + public void Add(KeyValuePair item) + { + wrapped.Add(item); + } + + public void Clear() + { + wrapped.Clear(); + } + + public bool Contains(KeyValuePair item) + { + return wrapped.Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + wrapped.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return wrapped.Count; } + } + + public bool IsReadOnly + { + get { return wrapped.IsReadOnly; } + } + + public bool Remove(KeyValuePair item) + { + return wrapped.Remove(item); + } + + public IEnumerator> GetEnumerator() + { + IComparer comparer = Comparer.Default; + var list = new List>(wrapped); + list.Sort((x, y) => comparer.Compare(x.Key, y.Key)); + return list.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} +#endif \ No newline at end of file diff --git a/src/ProtocolBuffers/UnknownFieldSet.cs b/src/ProtocolBuffers/UnknownFieldSet.cs index 2a955fc6..49c1fa32 100644 --- a/src/ProtocolBuffers/UnknownFieldSet.cs +++ b/src/ProtocolBuffers/UnknownFieldSet.cs @@ -243,11 +243,10 @@ namespace Google.ProtocolBuffers { public sealed class Builder { /// - /// Mapping from number to field. Note that by using a SortedDictionary we ensure + /// Mapping from number to field. Note that by using a SortedList we ensure /// that the fields will be serialized in ascending order. /// - private IDictionary fields = new SortedDictionary(); - + private IDictionary fields = new SortedList(); // Optimization: We keep around a builder for the last field that was // modified so that we can efficiently add to it multiple times in a // row (important when parsing an unknown repeated field). -- cgit v1.2.3