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_LITE_H__
32#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
33
34#include <google/protobuf/map.h>
35#include <google/protobuf/map_entry_lite.h>
36
37namespace google {
38namespace protobuf {
39namespace internal {
40
41// This class provides accesss to map field using generated api. It is used for
42// internal generated message implentation only. Users should never use this
43// directly.
44template <typename Key, typename T,
45          WireFormatLite::FieldType key_wire_type,
46          WireFormatLite::FieldType value_wire_type,
47          int default_enum_value = 0>
48class MapFieldLite {
49  // Define message type for internal repeated field.
50  typedef MapEntryLite<Key, T, key_wire_type, value_wire_type,
51                       default_enum_value> EntryType;
52
53 public:
54  MapFieldLite();
55  explicit MapFieldLite(Arena* arena);
56  virtual ~MapFieldLite();
57
58  // Accessors
59  virtual const Map<Key, T>& GetMap() const;
60  virtual Map<Key, T>* MutableMap();
61
62  // Convenient methods for generated message implementation.
63  virtual int size() const;
64  virtual void Clear();
65  virtual void MergeFrom(const MapFieldLite& other);
66  virtual void Swap(MapFieldLite* other);
67
68  // Set default enum value only for proto2 map field whose value is enum type.
69  void SetDefaultEnumValue();
70
71  // Used in the implementation of parsing. Caller should take the ownership.
72  EntryType* NewEntry() const;
73  // Used in the implementation of serializing enum value type. Caller should
74  // take the ownership.
75  EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
76  // Used in the implementation of serializing other value types. Caller should
77  // take the ownership.
78  EntryType* NewEntryWrapper(const Key& key, const T& t) const;
79
80 protected:
81  // Convenient methods to get internal google::protobuf::Map
82  virtual const Map<Key, T>& GetInternalMap() const;
83  virtual Map<Key, T>* MutableInternalMap();
84
85 private:
86  typedef void DestructorSkippable_;
87
88  Arena* arena_;
89  Map<Key, T>* map_;
90
91  friend class ::google::protobuf::Arena;
92};
93
94template <typename Key, typename T,
95          WireFormatLite::FieldType key_wire_type,
96          WireFormatLite::FieldType value_wire_type,
97          int default_enum_value>
98MapFieldLite<Key, T, key_wire_type, value_wire_type,
99             default_enum_value>::MapFieldLite()
100    : arena_(NULL) {
101  map_ = new Map<Key, T>;
102  SetDefaultEnumValue();
103}
104
105template <typename Key, typename T,
106          WireFormatLite::FieldType key_wire_type,
107          WireFormatLite::FieldType value_wire_type,
108          int default_enum_value>
109MapFieldLite<Key, T, key_wire_type, value_wire_type,
110             default_enum_value>::MapFieldLite(Arena* arena)
111  : arena_(arena) {
112  map_ = Arena::CreateMessage<Map<Key, T> >(arena);
113  SetDefaultEnumValue();
114}
115
116template <typename Key, typename T,
117          WireFormatLite::FieldType key_wire_type,
118          WireFormatLite::FieldType value_wire_type,
119          int default_enum_value>
120MapFieldLite<Key, T, key_wire_type, value_wire_type,
121             default_enum_value>::~MapFieldLite() {
122  delete map_;
123}
124
125template <typename Key, typename T,
126          WireFormatLite::FieldType key_wire_type,
127          WireFormatLite::FieldType value_wire_type,
128          int default_enum_value>
129const Map<Key, T>&
130MapFieldLite<Key, T, key_wire_type, value_wire_type,
131             default_enum_value>::GetMap() const {
132  return *map_;
133}
134
135template <typename Key, typename T,
136          WireFormatLite::FieldType key_wire_type,
137          WireFormatLite::FieldType value_wire_type,
138          int default_enum_value>
139Map<Key, T>*
140MapFieldLite<Key, T, key_wire_type, value_wire_type,
141             default_enum_value>::MutableMap() {
142  return map_;
143}
144
145template <typename Key, typename T,
146          WireFormatLite::FieldType key_wire_type,
147          WireFormatLite::FieldType value_wire_type,
148          int default_enum_value>
149int
150MapFieldLite<Key, T, key_wire_type, value_wire_type,
151             default_enum_value>::size() const {
152  return map_->size();
153}
154
155template <typename Key, typename T,
156          WireFormatLite::FieldType key_wire_type,
157          WireFormatLite::FieldType value_wire_type,
158          int default_enum_value>
159void
160MapFieldLite<Key, T, key_wire_type, value_wire_type,
161             default_enum_value>::Clear() {
162  map_->clear();
163}
164
165template <typename Key, typename T,
166          WireFormatLite::FieldType key_wire_type,
167          WireFormatLite::FieldType value_wire_type,
168          int default_enum_value>
169void
170MapFieldLite<Key, T, key_wire_type, value_wire_type,
171             default_enum_value>::MergeFrom(
172    const MapFieldLite& other) {
173  for (typename Map<Key, T>::const_iterator it = other.map_->begin();
174       it != other.map_->end(); ++it) {
175    (*map_)[it->first] = it->second;
176  }
177}
178
179template <typename Key, typename T,
180          WireFormatLite::FieldType key_wire_type,
181          WireFormatLite::FieldType value_wire_type,
182          int default_enum_value>
183void
184MapFieldLite<Key, T, key_wire_type, value_wire_type,
185             default_enum_value>::Swap(
186    MapFieldLite* other) {
187  std::swap(map_, other->map_);
188}
189
190template <typename Key, typename T,
191          WireFormatLite::FieldType key_wire_type,
192          WireFormatLite::FieldType value_wire_type,
193          int default_enum_value>
194void
195MapFieldLite<Key, T, key_wire_type, value_wire_type,
196             default_enum_value>::SetDefaultEnumValue() {
197  MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
198}
199
200template <typename Key, typename T,
201          WireFormatLite::FieldType key_wire_type,
202          WireFormatLite::FieldType value_wire_type,
203          int default_enum_value>
204const Map<Key, T>&
205MapFieldLite<Key, T, key_wire_type, value_wire_type,
206             default_enum_value>::GetInternalMap() const {
207  return *map_;
208}
209
210template <typename Key, typename T,
211          WireFormatLite::FieldType key_wire_type,
212          WireFormatLite::FieldType value_wire_type,
213          int default_enum_value>
214Map<Key, T>*
215MapFieldLite<Key, T, key_wire_type, value_wire_type,
216             default_enum_value>::MutableInternalMap() {
217  return map_;
218}
219
220#define EntryType \
221  MapEntryLite<Key, T, key_wire_type, value_wire_type, default_enum_value>
222
223template <typename Key, typename T,
224          WireFormatLite::FieldType key_wire_type,
225          WireFormatLite::FieldType value_wire_type,
226          int default_enum_value>
227EntryType*
228MapFieldLite<Key, T, key_wire_type, value_wire_type,
229             default_enum_value>::NewEntry() const {
230  if (arena_ == NULL) {
231    return new EntryType();
232  } else {
233    return Arena::CreateMessage<EntryType>(arena_);
234  }
235}
236
237template <typename Key, typename T,
238          WireFormatLite::FieldType key_wire_type,
239          WireFormatLite::FieldType value_wire_type,
240          int default_enum_value>
241EntryType*
242MapFieldLite<Key, T, key_wire_type, value_wire_type,
243             default_enum_value>::NewEnumEntryWrapper(const Key& key,
244                                                      const T t) const {
245  return EntryType::EnumWrap(key, t, arena_);
246}
247
248template <typename Key, typename T,
249          WireFormatLite::FieldType key_wire_type,
250          WireFormatLite::FieldType value_wire_type,
251          int default_enum_value>
252EntryType*
253MapFieldLite<Key, T, key_wire_type, value_wire_type,
254             default_enum_value>::NewEntryWrapper(const Key& key,
255                                                  const T& t) const {
256  return EntryType::Wrap(key, t, arena_);
257}
258
259#undef EntryType
260
261// True if IsInitialized() is true for value field in all elements of t. T is
262// expected to be message.  It's useful to have this helper here to keep the
263// protobuf compiler from ever having to emit loops in IsInitialized() methods.
264// We want the C++ compiler to inline this or not as it sees fit.
265template <typename Key, typename T>
266bool AllAreInitialized(const Map<Key, T>& t) {
267  for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
268       ++it) {
269    if (!it->second.IsInitialized()) return false;
270  }
271  return true;
272}
273
274}  // namespace internal
275}  // namespace protobuf
276
277}  // namespace google
278#endif  // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
279