blob: 902ec7364f11fcc5c8865f6b41fec4edc4091b62 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.
3// http://code.google.com/p/protobuf/
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17// Author: kenton@google.com (Kenton Varda)
18// Based on original Protocol Buffers design by
19// Sanjay Ghemawat, Jeff Dean, and others.
20//
21// This header is logically internal, but is made public because it is used
22// from protocol-compiler-generated code, which may reside in other components.
23
24#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__
25#define GOOGLE_PROTOBUF_EXTENSION_SET_H__
26
27#include <vector>
28#include <stack>
29#include <map>
30#include <utility>
31#include <string>
32
33#include <google/protobuf/message.h>
34
35namespace google {
36namespace protobuf {
37 class Descriptor; // descriptor.h
38 class FieldDescriptor; // descriptor.h
39 class DescriptorPool; // descriptor.h
40 class Message; // message.h
41 class MessageFactory; // message.h
42 namespace io {
43 class CodedInputStream; // coded_stream.h
44 class CodedOutputStream; // coded_stream.h
45 }
46 template <typename Element> class RepeatedField; // repeated_field.h
47 template <typename Element> class RepeatedPtrField; // repeated_field.h
48}
49
50namespace protobuf {
51namespace internal {
52
53// This is an internal helper class intended for use within the protocol buffer
54// library and generated classes. Clients should not use it directly. Instead,
55// use the generated accessors such as GetExtension() of the class being
56// extended.
57//
58// This class manages extensions for a protocol message object. The
59// message's HasExtension(), GetExtension(), MutableExtension(), and
60// ClearExtension() methods are just thin wrappers around the embedded
61// ExtensionSet. When parsing, if a tag number is encountered which is
62// inside one of the message type's extension ranges, the tag is passed
63// off to the ExtensionSet for parsing. Etc.
64class LIBPROTOBUF_EXPORT ExtensionSet {
65 public:
66 // Construct an ExtensionSet.
67 // extendee: Descriptor for the type being extended.
68 // pool: DescriptorPool to search for extension definitions.
69 // factory: MessageFactory used to construct implementations of messages
70 // for extensions with message type. This factory must be able
71 // to construct any message type found in "pool".
72 // All three objects remain property of the caller and must outlive the
73 // ExtensionSet.
74 ExtensionSet(const Descriptor* extendee,
75 const DescriptorPool* pool,
76 MessageFactory* factory);
77
78 ~ExtensionSet();
79
80 // Search for a known (compiled-in) extension of this type by name or number.
81 // Returns NULL if no extension is known.
82 const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
83 const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
84
85 // Add all fields which are currently present to the given vector. This
86 // is useful to implement Message::Reflection::ListFields().
87 void AppendToList(vector<const FieldDescriptor*>* output) const;
88
89 // =================================================================
90 // Accessors
91 //
92 // Generated message classes include type-safe templated wrappers around
93 // these methods. Generally you should use those rather than call these
94 // directly, unless you are doing low-level memory management.
95 //
96 // When calling any of these accessors, the extension number requested
97 // MUST exist in the DescriptorPool provided to the constructor. Otheriwse,
98 // the method will fail an assert. Normally, though, you would not call
99 // these directly; you would either call the generated accessors of your
100 // message class (e.g. GetExtension()) or you would call the accessors
101 // of the reflection interface. In both cases, it is impossible to
102 // trigger this assert failure: the generated accessors only accept
103 // linked-in extension types as parameters, while the Reflection interface
104 // requires you to provide the FieldDescriptor describing the extension.
105 //
106 // When calling any of these accessors, a protocol-compiler-generated
107 // implementation of the extension corresponding to the number MUST
108 // be linked in, and the FieldDescriptor used to refer to it MUST be
109 // the one generated by that linked-in code. Otherwise, the method will
110 // die on an assert failure. The message objects returned by the message
111 // accessors are guaranteed to be of the correct linked-in type.
112 //
113 // These methods pretty much match Message::Reflection except that:
114 // - They're not virtual.
115 // - They identify fields by number rather than FieldDescriptors.
116 // - They identify enum values using integers rather than descriptors.
117 // - Strings provide Mutable() in addition to Set() accessors.
118
119 bool Has(int number) const;
120 int ExtensionSize(int number) const; // Size of a repeated extension.
121 void ClearExtension(int number);
122
123 // singular fields -------------------------------------------------
124
125 int32 GetInt32 (int number) const;
126 int64 GetInt64 (int number) const;
127 uint32 GetUInt32(int number) const;
128 uint64 GetUInt64(int number) const;
129 float GetFloat (int number) const;
130 double GetDouble(int number) const;
131 bool GetBool (int number) const;
132 int GetEnum (int number) const;
133 const string & GetString (int number) const;
134 const Message& GetMessage(int number) const;
135
136 void SetInt32 (int number, int32 value);
137 void SetInt64 (int number, int64 value);
138 void SetUInt32(int number, uint32 value);
139 void SetUInt64(int number, uint64 value);
140 void SetFloat (int number, float value);
141 void SetDouble(int number, double value);
142 void SetBool (int number, bool value);
143 void SetEnum (int number, int value);
144 void SetString(int number, const string& value);
145 string * MutableString (int number);
146 Message* MutableMessage(int number);
147
148 // repeated fields -------------------------------------------------
149
150 int32 GetRepeatedInt32 (int number, int index) const;
151 int64 GetRepeatedInt64 (int number, int index) const;
152 uint32 GetRepeatedUInt32(int number, int index) const;
153 uint64 GetRepeatedUInt64(int number, int index) const;
154 float GetRepeatedFloat (int number, int index) const;
155 double GetRepeatedDouble(int number, int index) const;
156 bool GetRepeatedBool (int number, int index) const;
157 int GetRepeatedEnum (int number, int index) const;
158 const string & GetRepeatedString (int number, int index) const;
159 const Message& GetRepeatedMessage(int number, int index) const;
160
161 void SetRepeatedInt32 (int number, int index, int32 value);
162 void SetRepeatedInt64 (int number, int index, int64 value);
163 void SetRepeatedUInt32(int number, int index, uint32 value);
164 void SetRepeatedUInt64(int number, int index, uint64 value);
165 void SetRepeatedFloat (int number, int index, float value);
166 void SetRepeatedDouble(int number, int index, double value);
167 void SetRepeatedBool (int number, int index, bool value);
168 void SetRepeatedEnum (int number, int index, int value);
169 void SetRepeatedString(int number, int index, const string& value);
170 string * MutableRepeatedString (int number, int index);
171 Message* MutableRepeatedMessage(int number, int index);
172
173 void AddInt32 (int number, int32 value);
174 void AddInt64 (int number, int64 value);
175 void AddUInt32(int number, uint32 value);
176 void AddUInt64(int number, uint64 value);
177 void AddFloat (int number, float value);
178 void AddDouble(int number, double value);
179 void AddBool (int number, bool value);
180 void AddEnum (int number, int value);
181 void AddString(int number, const string& value);
182 string * AddString (int number);
183 Message* AddMessage(int number);
184
185 // -----------------------------------------------------------------
186 // TODO(kenton): Hardcore memory management accessors
187
188 // =================================================================
189 // convenience methods for implementing methods of Message
190 //
191 // These could all be implemented in terms of the other methods of this
192 // class, but providing them here helps keep the generated code size down.
193
194 void Clear();
195 void MergeFrom(const ExtensionSet& other);
196 bool IsInitialized() const;
197
198 // These parsing and serialization functions all want a pointer to the
199 // reflection interface because they hand off the actual work to WireFormat,
200 // which works in terms of a reflection interface. Yes, this means there
201 // are some redundant virtual function calls that end up being made, but
202 // it probably doesn't matter much in practice, and the alternative would
203 // involve reproducing a lot of WireFormat's functionality.
204
205 // Parses a single extension from the input. The input should start out
206 // positioned immediately after the tag.
207 bool ParseField(uint32 tag, io::CodedInputStream* input,
208 Message::Reflection* reflection);
209
210 // Write all extension fields with field numbers in the range
211 // [start_field_number, end_field_number)
212 // to the output stream, using the cached sizes computed when ByteSize() was
213 // last called. Note that the range bounds are inclusive-exclusive.
214 bool SerializeWithCachedSizes(int start_field_number,
215 int end_field_number,
216 const Message::Reflection* reflection,
217 io::CodedOutputStream* output) const;
218
219 // Returns the total serialized size of all the extensions.
220 int ByteSize(const Message::Reflection* reflection) const;
221
222 private:
223 // Like FindKnownExtension(), but GOOGLE_CHECK-fail if not found.
224 const FieldDescriptor* FindKnownExtensionOrDie(int number) const;
225
226 // Get the prototype for the message.
227 const Message* GetPrototype(const Descriptor* message_type) const;
228
229 struct Extension {
230 union {
231 int32 int32_value;
232 int64 int64_value;
233 uint32 uint32_value;
234 uint64 uint64_value;
235 float float_value;
236 double double_value;
237 bool bool_value;
238 int enum_value;
239 string* string_value;
240 Message* message_value;
241
242 RepeatedField <int32 >* repeated_int32_value;
243 RepeatedField <int64 >* repeated_int64_value;
244 RepeatedField <uint32 >* repeated_uint32_value;
245 RepeatedField <uint64 >* repeated_uint64_value;
246 RepeatedField <float >* repeated_float_value;
247 RepeatedField <double >* repeated_double_value;
248 RepeatedField <bool >* repeated_bool_value;
249 RepeatedField <int >* repeated_enum_value;
250 RepeatedPtrField<string >* repeated_string_value;
251 RepeatedPtrField<Message>* repeated_message_value;
252 };
253
254 const FieldDescriptor* descriptor;
255
256 // For singular types, indicates if the extension is "cleared". This
257 // happens when an extension is set and then later cleared by the caller.
258 // We want to keep the Extension object around for reuse, so instead of
259 // removing it from the map, we just set is_cleared = true. This has no
260 // meaning for repeated types; for those, the size of the RepeatedField
261 // simply becomes zero when cleared.
262 bool is_cleared;
263
264 Extension(): descriptor(NULL), is_cleared(false) {}
265
266 // Some helper methods for operations on a single Extension.
267 bool SerializeFieldWithCachedSizes(
268 const Message::Reflection* reflection,
269 io::CodedOutputStream* output) const;
270 int64 ByteSize(const Message::Reflection* reflection) const;
271 void Clear();
272 int GetSize() const;
273 void Free();
274 };
275
276 // The Extension struct is small enough to be passed by value, so we use it
277 // directly as the value type in the map rather than use pointers. We use
278 // a map rather than hash_map here because we expect most ExtensionSets will
279 // only contain a small number of extensions whereas hash_map is optimized
280 // for 100 elements or more. Also, we want AppendToList() to order fields
281 // by field number.
282 map<int, Extension> extensions_;
283 const Descriptor* extendee_;
284 const DescriptorPool* descriptor_pool_;
285 MessageFactory* message_factory_;
286
287 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
288};
289
290// These are just for convenience...
291inline void ExtensionSet::SetString(int number, const string& value) {
292 MutableString(number)->assign(value);
293}
294inline void ExtensionSet::SetRepeatedString(int number, int index,
295 const string& value) {
296 MutableRepeatedString(number, index)->assign(value);
297}
298inline void ExtensionSet::AddString(int number, const string& value) {
299 AddString(number)->assign(value);
300}
301
302// ===================================================================
303// Implementation details
304//
305// DO NOT DEPEND ON ANYTHING BELOW THIS POINT. This is for use from
306// generated code only.
307
308// -------------------------------------------------------------------
309// Template magic
310
311// First we have a set of classes representing "type traits" for different
312// field types. A type traits class knows how to implement basic accessors
313// for extensions of a particular type given an ExtensionSet. The signature
314// for a type traits class looks like this:
315//
316// class TypeTraits {
317// public:
318// typedef ? ConstType;
319// typedef ? MutableType;
320//
321// static inline ConstType Get(int number, const ExtensionSet& set);
322// static inline void Set(int number, ConstType value, ExtensionSet* set);
323// static inline MutableType Mutable(int number, ExtensionSet* set);
324//
325// // Variants for repeated fields.
326// static inline ConstType Get(int number, const ExtensionSet& set,
327// int index);
328// static inline void Set(int number, int index,
329// ConstType value, ExtensionSet* set);
330// static inline MutableType Mutable(int number, int index,
331// ExtensionSet* set);
332// static inline void Add(int number, ConstType value, ExtensionSet* set);
333// static inline MutableType Add(int number, ExtensionSet* set);
334// };
335//
336// Not all of these methods make sense for all field types. For example, the
337// "Mutable" methods only make sense for strings and messages, and the
338// repeated methods only make sense for repeated types. So, each type
339// traits class implements only the set of methods from this signature that it
340// actually supports. This will cause a compiler error if the user tries to
341// access an extension using a method that doesn't make sense for its type.
342// For example, if "foo" is an extension of type "optional int32", then if you
343// try to write code like:
344// my_message.MutableExtension(foo)
345// you will get a compile error because PrimitiveTypeTraits<int32> does not
346// have a "Mutable()" method.
347
348// -------------------------------------------------------------------
349// PrimitiveTypeTraits
350
351// Since the ExtensionSet has different methods for each primitive type,
352// we must explicitly define the methods of the type traits class for each
353// known type.
354template <typename Type>
355class PrimitiveTypeTraits {
356 public:
357 typedef Type ConstType;
358
359 static inline ConstType Get(int number, const ExtensionSet& set);
360 static inline void Set(int number, ConstType value, ExtensionSet* set);
361};
362
363template <typename Type>
364class RepeatedPrimitiveTypeTraits {
365 public:
366 typedef Type ConstType;
367
368 static inline Type Get(int number, const ExtensionSet& set, int index);
369 static inline void Set(int number, int index, Type value, ExtensionSet* set);
370 static inline void Add(int number, Type value, ExtensionSet* set);
371};
372
373#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \
374template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \
375 int number, const ExtensionSet& set) { \
376 return set.Get##METHOD(number); \
377} \
378template<> inline void PrimitiveTypeTraits<TYPE>::Set( \
379 int number, ConstType value, ExtensionSet* set) { \
380 set->Set##METHOD(number, value); \
381} \
382 \
383template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
384 int number, const ExtensionSet& set, int index) { \
385 return set.GetRepeated##METHOD(number, index); \
386} \
387template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \
388 int number, int index, ConstType value, ExtensionSet* set) { \
389 set->SetRepeated##METHOD(number, index, value); \
390} \
391template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
392 int number, ConstType value, ExtensionSet* set) { \
393 set->Add##METHOD(number, value); \
394}
395
396PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
397PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64, Int64)
398PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32)
399PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64)
400PROTOBUF_DEFINE_PRIMITIVE_TYPE( float, Float)
401PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double)
402PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool)
403
404#undef PROTOBUF_DEFINE_PRIMITIVE_TYPE
405
406// -------------------------------------------------------------------
407// StringTypeTraits
408
409// Strings support both Set() and Mutable().
410class LIBPROTOBUF_EXPORT StringTypeTraits {
411 public:
412 typedef const string& ConstType;
413 typedef string* MutableType;
414
415 static inline const string& Get(int number, const ExtensionSet& set) {
416 return set.GetString(number);
417 }
418 static inline void Set(int number, const string& value, ExtensionSet* set) {
419 set->SetString(number, value);
420 }
421 static inline string* Mutable(int number, ExtensionSet* set) {
422 return set->MutableString(number);
423 }
424};
425
426class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
427 public:
428 typedef const string& ConstType;
429 typedef string* MutableType;
430
431 static inline const string& Get(int number, const ExtensionSet& set,
432 int index) {
433 return set.GetRepeatedString(number, index);
434 }
435 static inline void Set(int number, int index,
436 const string& value, ExtensionSet* set) {
437 set->SetRepeatedString(number, index, value);
438 }
439 static inline string* Mutable(int number, int index, ExtensionSet* set) {
440 return set->MutableRepeatedString(number, index);
441 }
442 static inline void Add(int number, const string& value, ExtensionSet* set) {
443 set->AddString(number, value);
444 }
445 static inline string* Add(int number, ExtensionSet* set) {
446 return set->AddString(number);
447 }
448};
449
450// -------------------------------------------------------------------
451// EnumTypeTraits
452
453// ExtensionSet represents enums using integers internally, so we have to
454// static_cast around.
455template <typename Type>
456class EnumTypeTraits {
457 public:
458 typedef Type ConstType;
459
460 static inline ConstType Get(int number, const ExtensionSet& set) {
461 return static_cast<Type>(set.GetEnum(number));
462 }
463 static inline void Set(int number, ConstType value, ExtensionSet* set) {
464 set->SetEnum(number, value);
465 }
466};
467
468template <typename Type>
469class RepeatedEnumTypeTraits {
470 public:
471 typedef Type ConstType;
472
473 static inline ConstType Get(int number, const ExtensionSet& set, int index) {
474 return static_cast<Type>(set.GetRepeatedEnum(number, index));
475 }
476 static inline void Set(int number, int index,
477 ConstType value, ExtensionSet* set) {
478 set->SetRepeatedEnum(number, index, value);
479 }
480 static inline void Add(int number, ConstType value, ExtensionSet* set) {
481 set->AddEnum(number, value);
482 }
483};
484
485// -------------------------------------------------------------------
486// MessageTypeTraits
487
488// ExtensionSet guarantees that when manipulating extensions with message
489// types, the implementation used will be the compiled-in class representing
490// that type. So, we can static_cast down to the exact type we expect.
491template <typename Type>
492class MessageTypeTraits {
493 public:
494 typedef const Type& ConstType;
495 typedef Type* MutableType;
496
497 static inline ConstType Get(int number, const ExtensionSet& set) {
498 return static_cast<const Type&>(set.GetMessage(number));
499 }
500 static inline MutableType Mutable(int number, ExtensionSet* set) {
501 return static_cast<Type*>(set->MutableMessage(number));
502 }
503};
504
505template <typename Type>
506class RepeatedMessageTypeTraits {
507 public:
508 typedef const Type& ConstType;
509 typedef Type* MutableType;
510
511 static inline ConstType Get(int number, const ExtensionSet& set, int index) {
512 return static_cast<const Type&>(set.GetRepeatedMessage(number, index));
513 }
514 static inline MutableType Mutable(int number, int index, ExtensionSet* set) {
515 return static_cast<Type*>(set->MutableRepeatedMessage(number, index));
516 }
517 static inline MutableType Add(int number, ExtensionSet* set) {
518 return static_cast<Type*>(set->AddMessage(number));
519 }
520};
521
522// -------------------------------------------------------------------
523// ExtensionIdentifier
524
525// This is the type of actual extension objects. E.g. if you have:
526// extends Foo with optional int32 bar = 1234;
527// then "bar" will be defined in C++ as:
528// ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>> bar(1234);
529//
530// Note that we could, in theory, supply the field number as a template
531// parameter, and thus make an instance of ExtensionIdentifier have no
532// actual contents. However, if we did that, then using at extension
533// identifier would not necessarily cause the compiler to output any sort
534// of reference to any simple defined in the extension's .pb.o file. Some
535// linkers will actually drop object files that are not explicitly referenced,
536// but that would be bad because it would cause this extension to not be
537// registered at static initialization, and therefore using it would crash.
538
539template <typename ExtendeeType, typename TypeTraitsType>
540class ExtensionIdentifier {
541 public:
542 typedef TypeTraitsType TypeTraits;
543 typedef ExtendeeType Extendee;
544
545 ExtensionIdentifier(int number): number_(number) {}
546 inline int number() const { return number_; }
547 private:
548 const int number_;
549};
550
551} // namespace internal
552} // namespace protobuf
553
554} // namespace google
555#endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__