Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RemoveBackwardsCompatibility/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtocolBuffers/ExtensionRegistryLite.cs @ 13346

Last change on this file since 13346 was 8295, checked in by abeham, 12 years ago

#1897:

  • Removed protocol buffers 0.9.1
  • Added protocol buffers 2.4.1
  • Updated proto processing command
File size: 9.1 KB
Line 
1#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13//     * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//     * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19//     * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System;
38using System.Collections.Generic;
39using ExtensionByNameMap = System.Collections.Generic.Dictionary<object, System.Collections.Generic.Dictionary<string, Google.ProtocolBuffers.IGeneratedExtensionLite>>;
40using ExtensionByIdMap = System.Collections.Generic.Dictionary<Google.ProtocolBuffers.ExtensionRegistry.ExtensionIntPair, Google.ProtocolBuffers.IGeneratedExtensionLite>;
41
42namespace Google.ProtocolBuffers
43{
44    /// <summary>
45    /// A table of known extensions, searchable by name or field number.  When
46    /// parsing a protocol message that might have extensions, you must provide
47    /// an <see cref="ExtensionRegistry"/> in which you have registered any extensions
48    /// that you want to be able to parse.  Otherwise, those extensions will just
49    /// be treated like unknown fields.
50    /// </summary>
51    /// <example>
52    /// For example, if you had the <c>.proto</c> file:
53    /// <code>
54    /// option java_class = "MyProto";
55    ///
56    /// message Foo {
57    ///   extensions 1000 to max;
58    /// }
59    ///
60    /// extend Foo {
61    ///   optional int32 bar;
62    /// }
63    /// </code>
64    ///
65    /// Then you might write code like:
66    ///
67    /// <code>
68    /// extensionRegistry registry = extensionRegistry.CreateInstance();
69    /// registry.Add(MyProto.Bar);
70    /// MyProto.Foo message = MyProto.Foo.ParseFrom(input, registry);
71    /// </code>
72    /// </example>
73    ///
74    /// <remarks>
75    /// <para>You might wonder why this is necessary. Two alternatives might come to
76    /// mind. First, you might imagine a system where generated extensions are
77    /// automatically registered when their containing classes are loaded. This
78    /// is a popular technique, but is bad design; among other things, it creates a
79    /// situation where behavior can change depending on what classes happen to be
80    /// loaded. It also introduces a security vulnerability, because an
81    /// unprivileged class could cause its code to be called unexpectedly from a
82    /// privileged class by registering itself as an extension of the right type.
83    /// </para>
84    /// <para>Another option you might consider is lazy parsing: do not parse an
85    /// extension until it is first requested, at which point the caller must
86    /// provide a type to use. This introduces a different set of problems. First,
87    /// it would require a mutex lock any time an extension was accessed, which
88    /// would be slow. Second, corrupt data would not be detected until first
89    /// access, at which point it would be much harder to deal with it. Third, it
90    /// could violate the expectation that message objects are immutable, since the
91    /// type provided could be any arbitrary message class. An unprivileged user
92    /// could take advantage of this to inject a mutable object into a message
93    /// belonging to privileged code and create mischief.</para>
94    /// </remarks>
95    public sealed partial class ExtensionRegistry
96    {
97        private static readonly ExtensionRegistry empty = new ExtensionRegistry(
98            new ExtensionByNameMap(),
99            new ExtensionByIdMap(),
100            true);
101
102        private readonly ExtensionByNameMap extensionsByName;
103        private readonly ExtensionByIdMap extensionsByNumber;
104
105        private readonly bool readOnly;
106
107        private ExtensionRegistry(ExtensionByNameMap byName, ExtensionByIdMap byNumber, bool readOnly)
108        {
109            this.extensionsByName = byName;
110            this.extensionsByNumber = byNumber;
111            this.readOnly = readOnly;
112        }
113
114        /// <summary>
115        /// Construct a new, empty instance.
116        /// </summary>
117        public static ExtensionRegistry CreateInstance()
118        {
119            return new ExtensionRegistry(new ExtensionByNameMap(), new ExtensionByIdMap(), false);
120        }
121
122        public ExtensionRegistry AsReadOnly()
123        {
124            return new ExtensionRegistry(extensionsByName, extensionsByNumber, true);
125        }
126
127        /// <summary>
128        /// Get the unmodifiable singleton empty instance.
129        /// </summary>
130        public static ExtensionRegistry Empty
131        {
132            get { return empty; }
133        }
134
135        /// <summary>
136        /// Finds an extension by containing type and field number.
137        /// A null reference is returned if the extension can't be found.
138        /// </summary>
139        public IGeneratedExtensionLite this[IMessageLite containingType, int fieldNumber]
140        {
141            get
142            {
143                IGeneratedExtensionLite ret;
144                extensionsByNumber.TryGetValue(new ExtensionIntPair(containingType, fieldNumber), out ret);
145                return ret;
146            }
147        }
148
149        public IGeneratedExtensionLite FindByName(IMessageLite defaultInstanceOfType, string fieldName)
150        {
151            return FindExtensionByName(defaultInstanceOfType, fieldName);
152        }
153
154        private IGeneratedExtensionLite FindExtensionByName(object forwhat, string fieldName)
155        {
156            IGeneratedExtensionLite extension = null;
157            Dictionary<string, IGeneratedExtensionLite> map;
158            if (extensionsByName.TryGetValue(forwhat, out map) && map.TryGetValue(fieldName, out extension))
159            {
160                return extension;
161            }
162            return null;
163        }
164
165        /// <summary>
166        /// Add an extension from a generated file to the registry.
167        /// </summary>
168        public void Add(IGeneratedExtensionLite extension)
169        {
170            if (readOnly)
171            {
172                throw new InvalidOperationException("Cannot add entries to a read-only extension registry");
173            }
174            extensionsByNumber.Add(new ExtensionIntPair(extension.ContainingType, extension.Number), extension);
175
176            Dictionary<string, IGeneratedExtensionLite> map;
177            if (!extensionsByName.TryGetValue(extension.ContainingType, out map))
178            {
179                extensionsByName.Add(extension.ContainingType, map = new Dictionary<string, IGeneratedExtensionLite>());
180            }
181            map[extension.Descriptor.Name] = extension;
182            map[extension.Descriptor.FullName] = extension;
183        }
184
185        /// <summary>
186        /// Nested type just used to represent a pair of MessageDescriptor and int, as
187        /// the key into the "by number" map.
188        /// </summary>
189        internal struct ExtensionIntPair : IEquatable<ExtensionIntPair>
190        {
191            private readonly object msgType;
192            private readonly int number;
193
194            internal ExtensionIntPair(object msgType, int number)
195            {
196                this.msgType = msgType;
197                this.number = number;
198            }
199
200            public override int GetHashCode()
201            {
202                return msgType.GetHashCode()*((1 << 16) - 1) + number;
203            }
204
205            public override bool Equals(object obj)
206            {
207                if (!(obj is ExtensionIntPair))
208                {
209                    return false;
210                }
211                return Equals((ExtensionIntPair) obj);
212            }
213
214            public bool Equals(ExtensionIntPair other)
215            {
216                return msgType.Equals(other.msgType) && number == other.number;
217            }
218        }
219    }
220}
Note: See TracBrowser for help on using the repository browser.