Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
| 2 | // Copyright 2008 Google Inc. All rights reserved. |
| 3 | // https://developers.google.com/protocol-buffers/ |
| 4 | // |
| 5 | // Redistribution and use in source and binary forms, with or without |
| 6 | // modification, are permitted provided that the following conditions are |
| 7 | // met: |
| 8 | // |
| 9 | // * Redistributions of source code must retain the above copyright |
| 10 | // notice, this list of conditions and the following disclaimer. |
| 11 | // * Redistributions in binary form must reproduce the above |
| 12 | // copyright notice, this list of conditions and the following disclaimer |
| 13 | // in the documentation and/or other materials provided with the |
| 14 | // distribution. |
| 15 | // * Neither the name of Google Inc. nor the names of its |
| 16 | // contributors may be used to endorse or promote products derived from |
| 17 | // this software without specific prior written permission. |
| 18 | // |
| 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | |
| 31 | #ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__ |
| 32 | #define GOOGLE_PROTOBUF_MAP_FIELD_H__ |
| 33 | |
| 34 | #include <google/protobuf/stubs/atomicops.h> |
| 35 | #include <google/protobuf/stubs/common.h> |
| 36 | #include <google/protobuf/generated_message_reflection.h> |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 37 | #include <google/protobuf/arena.h> |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 38 | #include <google/protobuf/map_entry.h> |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 39 | #include <google/protobuf/map_field_lite.h> |
| 40 | #include <google/protobuf/map_type_handler.h> |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 41 | #include <google/protobuf/message.h> |
| 42 | #include <google/protobuf/repeated_field.h> |
| 43 | #include <google/protobuf/unknown_field_set.h> |
| 44 | |
| 45 | |
| 46 | namespace google { |
| 47 | namespace protobuf { |
| 48 | |
| 49 | namespace internal { |
| 50 | |
| 51 | class ContendedMapCleanTest; |
| 52 | class GeneratedMessageReflection; |
| 53 | class MapFieldAccessor; |
| 54 | |
| 55 | // This class provides accesss to map field using reflection, which is the same |
| 56 | // as those provided for RepeatedPtrField<Message>. It is used for internal |
| 57 | // reflection implentation only. Users should never use this directly. |
| 58 | class LIBPROTOBUF_EXPORT MapFieldBase { |
| 59 | public: |
| 60 | MapFieldBase() |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 61 | : arena_(NULL), |
| 62 | repeated_field_(NULL), |
| 63 | entry_descriptor_(NULL), |
| 64 | assign_descriptor_callback_(NULL), |
| 65 | state_(STATE_MODIFIED_MAP) {} |
| 66 | explicit MapFieldBase(Arena* arena) |
| 67 | : arena_(arena), |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 68 | repeated_field_(NULL), |
| 69 | entry_descriptor_(NULL), |
| 70 | assign_descriptor_callback_(NULL), |
| 71 | state_(STATE_MODIFIED_MAP) {} |
| 72 | virtual ~MapFieldBase(); |
| 73 | |
| 74 | // Returns reference to internal repeated field. Data written using |
| 75 | // google::protobuf::Map's api prior to calling this function is guarantted to be |
| 76 | // included in repeated field. |
| 77 | const RepeatedPtrFieldBase& GetRepeatedField() const; |
| 78 | |
| 79 | // Like above. Returns mutable pointer to the internal repeated field. |
| 80 | RepeatedPtrFieldBase* MutableRepeatedField(); |
| 81 | |
| 82 | // Returns the number of bytes used by the repeated field, excluding |
| 83 | // sizeof(*this) |
| 84 | int SpaceUsedExcludingSelf() const; |
| 85 | |
| 86 | protected: |
| 87 | // Gets the size of space used by map field. |
| 88 | virtual int SpaceUsedExcludingSelfNoLock() const; |
| 89 | |
| 90 | // Synchronizes the content in Map to RepeatedPtrField if there is any change |
| 91 | // to Map after last synchronization. |
| 92 | void SyncRepeatedFieldWithMap() const; |
| 93 | virtual void SyncRepeatedFieldWithMapNoLock() const; |
| 94 | |
| 95 | // Synchronizes the content in RepeatedPtrField to Map if there is any change |
| 96 | // to RepeatedPtrField after last synchronization. |
| 97 | void SyncMapWithRepeatedField() const; |
| 98 | virtual void SyncMapWithRepeatedFieldNoLock() const {} |
| 99 | |
| 100 | // Tells MapFieldBase that there is new change to Map. |
| 101 | void SetMapDirty(); |
| 102 | |
| 103 | // Tells MapFieldBase that there is new change to RepeatedPTrField. |
| 104 | void SetRepeatedDirty(); |
| 105 | |
| 106 | // Provides derived class the access to repeated field. |
| 107 | void* MutableRepeatedPtrField() const; |
| 108 | |
| 109 | // Creates descriptor for only one time. |
| 110 | void InitMetadataOnce() const; |
| 111 | |
| 112 | enum State { |
| 113 | STATE_MODIFIED_MAP = 0, // map has newly added data that has not been |
| 114 | // synchronized to repeated field |
| 115 | STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that |
| 116 | // has not been synchronized to map |
| 117 | CLEAN = 2, // data in map and repeated field are same |
| 118 | }; |
| 119 | |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 120 | Arena* arena_; |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 121 | mutable RepeatedPtrField<Message>* repeated_field_; |
| 122 | // MapEntry can only be created from MapField. To create MapEntry, MapField |
| 123 | // needs to know its descriptor, because MapEntry is not generated class which |
| 124 | // cannot initialize its own descriptor by calling generated |
| 125 | // descriptor-assign-function. Thus, we need to register a callback to |
| 126 | // initialize MapEntry's descriptor. |
| 127 | const Descriptor** entry_descriptor_; |
| 128 | void (*assign_descriptor_callback_)(); |
| 129 | |
| 130 | mutable Mutex mutex_; // The thread to synchronize map and repeated field |
| 131 | // needs to get lock first; |
| 132 | mutable volatile Atomic32 state_; // 0: STATE_MODIFIED_MAP |
| 133 | // 1: STATE_MODIFIED_REPEATED |
| 134 | // 2: CLEAN |
| 135 | |
| 136 | private: |
| 137 | friend class ContendedMapCleanTest; |
| 138 | friend class GeneratedMessageReflection; |
| 139 | friend class MapFieldAccessor; |
| 140 | }; |
| 141 | |
| 142 | // This class provides accesss to map field using generated api. It is used for |
| 143 | // internal generated message implentation only. Users should never use this |
| 144 | // directly. |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 145 | template <typename Key, typename T, |
| 146 | WireFormatLite::FieldType kKeyFieldType, |
| 147 | WireFormatLite::FieldType kValueFieldType, |
| 148 | int default_enum_value = 0> |
| 149 | class LIBPROTOBUF_EXPORT MapField : public MapFieldBase, |
| 150 | public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, |
| 151 | default_enum_value> { |
| 152 | // Handlers for key/value wire type. Provide utilities to parse/serialize |
| 153 | // key/value. |
| 154 | typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler; |
| 155 | typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler; |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 156 | |
| 157 | // Define key/value's internal stored type. |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 158 | static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; |
| 159 | static const bool kIsValMessage = ValueWireHandler::kIsMessage; |
| 160 | typedef typename KeyWireHandler::CppType KeyInternalType; |
| 161 | typedef typename ValueWireHandler::CppType ValueInternalType; |
| 162 | typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp; |
| 163 | typedef typename MapIf<kIsValMessage, T , ValueInternalType>::type ValCpp; |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 164 | |
| 165 | // Handlers for key/value's internal stored type. |
| 166 | typedef MapCppTypeHandler<KeyCpp> KeyHandler; |
| 167 | typedef MapCppTypeHandler<ValCpp> ValHandler; |
| 168 | |
| 169 | // Define message type for internal repeated field. |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 170 | typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value> |
| 171 | EntryType; |
| 172 | typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType, |
| 173 | default_enum_value> EntryLiteType; |
| 174 | |
| 175 | // Define abbreviation for parent MapFieldLite |
| 176 | typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, |
| 177 | default_enum_value> MapFieldLiteType; |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 178 | |
| 179 | // Enum needs to be handled differently from other types because it has |
| 180 | // different exposed type in google::protobuf::Map's api and repeated field's api. For |
| 181 | // details see the comment in the implementation of |
| 182 | // SyncMapWithRepeatedFieldNoLocki. |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 183 | static const bool kIsValueEnum = ValueWireHandler::kIsEnum; |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 184 | typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType; |
| 185 | |
| 186 | public: |
| 187 | MapField(); |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 188 | explicit MapField(Arena* arena); |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 189 | // MapField doesn't own the default_entry, which means default_entry must |
| 190 | // outlive the lifetime of MapField. |
| 191 | MapField(const Message* default_entry); |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 192 | // For tests only. |
| 193 | MapField(Arena* arena, const Message* default_entry); |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 194 | ~MapField(); |
| 195 | |
| 196 | // Accessors |
| 197 | const Map<Key, T>& GetMap() const; |
| 198 | Map<Key, T>* MutableMap(); |
| 199 | |
| 200 | // Convenient methods for generated message implementation. |
| 201 | int size() const; |
| 202 | void Clear(); |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 203 | void MergeFrom(const MapFieldLiteType& other); |
| 204 | void Swap(MapFieldLiteType* other); |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 205 | |
| 206 | // Allocates metadata only if this MapField is part of a generated message. |
| 207 | void SetEntryDescriptor(const Descriptor** descriptor); |
| 208 | void SetAssignDescriptorCallback(void (*callback)()); |
| 209 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 210 | private: |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 211 | typedef void DestructorSkippable_; |
| 212 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 213 | // MapField needs MapEntry's default instance to create new MapEntry. |
| 214 | void InitDefaultEntryOnce() const; |
| 215 | |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 216 | // Manually set default entry instance. For test only. |
| 217 | void SetDefaultEntryOnce(const EntryType* default_entry) const; |
| 218 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 219 | // Convenient methods to get internal google::protobuf::Map |
| 220 | const Map<Key, T>& GetInternalMap() const; |
| 221 | Map<Key, T>* MutableInternalMap(); |
| 222 | |
| 223 | // Implements MapFieldBase |
| 224 | void SyncRepeatedFieldWithMapNoLock() const; |
| 225 | void SyncMapWithRepeatedFieldNoLock() const; |
| 226 | int SpaceUsedExcludingSelfNoLock() const; |
| 227 | |
| 228 | mutable const EntryType* default_entry_; |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 229 | |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 230 | friend class ::google::protobuf::Arena; |
| 231 | }; |
Feng Xiao | 6ae3bde | 2014-11-25 14:01:44 -0800 | [diff] [blame] | 232 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 233 | } // namespace internal |
| 234 | } // namespace protobuf |
| 235 | |
| 236 | } // namespace google |
| 237 | #endif // GOOGLE_PROTOBUF_MAP_FIELD_H__ |