BWAPI
|
00001 // Protocol Buffers - Google's data interchange format 00002 // Copyright 2008 Google Inc. All rights reserved. 00003 // http://code.google.com/p/protobuf/ 00004 // 00005 // Redistribution and use in source and binary forms, with or without 00006 // modification, are permitted provided that the following conditions are 00007 // met: 00008 // 00009 // * Redistributions of source code must retain the above copyright 00010 // notice, this list of conditions and the following disclaimer. 00011 // * Redistributions in binary form must reproduce the above 00012 // copyright notice, this list of conditions and the following disclaimer 00013 // in the documentation and/or other materials provided with the 00014 // distribution. 00015 // * Neither the name of Google Inc. nor the names of its 00016 // contributors may be used to endorse or promote products derived from 00017 // this software without specific prior written permission. 00018 // 00019 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00020 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00021 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00022 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00023 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00025 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00026 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00027 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00029 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 00031 // Author: kenton@google.com (Kenton Varda) 00032 // Based on original Protocol Buffers design by 00033 // Sanjay Ghemawat, Jeff Dean, and others. 00034 // 00035 // RepeatedField and RepeatedPtrField are used by generated protocol message 00036 // classes to manipulate repeated fields. These classes are very similar to 00037 // STL's vector, but include a number of optimizations found to be useful 00038 // specifically in the case of Protocol Buffers. RepeatedPtrField is 00039 // particularly different from STL vector as it manages ownership of the 00040 // pointers that it contains. 00041 // 00042 // Typically, clients should not need to access RepeatedField objects directly, 00043 // but should instead use the accessor functions generated automatically by the 00044 // protocol compiler. 00045 00046 #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ 00047 #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ 00048 00049 #include <string> 00050 #include <iterator> 00051 #include <google/protobuf/stubs/common.h> 00052 #include <google/protobuf/message_lite.h> 00053 00054 namespace google { 00055 00056 namespace protobuf { 00057 00058 class Message; 00059 00060 namespace internal { 00061 00062 // We need this (from generated_message_reflection.cc). 00063 LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); 00064 00065 } // namespace internal 00066 00067 // RepeatedField is used to represent repeated fields of a primitive type (in 00068 // other words, everything except strings and nested Messages). Most users will 00069 // not ever use a RepeatedField directly; they will use the get-by-index, 00070 // set-by-index, and add accessors that are generated for all repeated fields. 00071 template <typename Element> 00072 class RepeatedField { 00073 public: 00074 RepeatedField(); 00075 ~RepeatedField(); 00076 00077 int size() const; 00078 00079 const Element& Get(int index) const; 00080 Element* Mutable(int index); 00081 void Set(int index, const Element& value); 00082 void Add(const Element& value); 00083 Element* Add(); 00084 // Remove the last element in the array. 00085 // We don't provide a way to remove any element other than the last 00086 // because it invites inefficient use, such as O(n^2) filtering loops 00087 // that should have been O(n). If you want to remove an element other 00088 // than the last, the best way to do it is to re-arrange the elements 00089 // so that the one you want removed is at the end, then call RemoveLast(). 00090 void RemoveLast(); 00091 void Clear(); 00092 void MergeFrom(const RepeatedField& other); 00093 00094 // Reserve space to expand the field to at least the given size. If the 00095 // array is grown, it will always be at least doubled in size. 00096 void Reserve(int new_size); 00097 00098 // Resize the RepeatedField to a new, smaller size. This is O(1). 00099 void Truncate(int new_size); 00100 00101 void AddAlreadyReserved(const Element& value); 00102 Element* AddAlreadyReserved(); 00103 int Capacity() const; 00104 00105 // Gets the underlying array. This pointer is possibly invalidated by 00106 // any add or remove operation. 00107 Element* mutable_data(); 00108 const Element* data() const; 00109 00110 // Swap entire contents with "other". 00111 void Swap(RepeatedField* other); 00112 00113 // Swap two elements. 00114 void SwapElements(int index1, int index2); 00115 00116 // STL-like iterator support 00117 typedef Element* iterator; 00118 typedef const Element* const_iterator; 00119 00120 iterator begin(); 00121 const_iterator begin() const; 00122 iterator end(); 00123 const_iterator end() const; 00124 00125 // Returns the number of bytes used by the repeated field, excluding 00126 // sizeof(*this) 00127 int SpaceUsedExcludingSelf() const; 00128 00129 private: 00130 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField); 00131 00132 static const int kInitialSize = 4; 00133 00134 Element* elements_; 00135 int current_size_; 00136 int total_size_; 00137 00138 Element initial_space_[kInitialSize]; 00139 00140 // Move the contents of |from| into |to|, possibly clobbering |from| in the 00141 // process. For primitive types this is just a memcpy(), but it could be 00142 // specialized for non-primitive types to, say, swap each element instead. 00143 void MoveArray(Element to[], Element from[], int size); 00144 00145 // Copy the elements of |from| into |to|. 00146 void CopyArray(Element to[], const Element from[], int size); 00147 }; 00148 00149 namespace internal { 00150 template <typename It> class RepeatedPtrIterator; 00151 template <typename It> class RepeatedPtrOverPtrsIterator; 00152 } // namespace internal 00153 00154 namespace internal { 00155 00156 // This is the common base class for RepeatedPtrFields. It deals only in void* 00157 // pointers. Users should not use this interface directly. 00158 // 00159 // The methods of this interface correspond to the methods of RepeatedPtrField, 00160 // but may have a template argument called TypeHandler. Its signature is: 00161 // class TypeHandler { 00162 // public: 00163 // typedef MyType Type; 00164 // static Type* New(); 00165 // static void Delete(Type*); 00166 // static void Clear(Type*); 00167 // static void Merge(const Type& from, Type* to); 00168 // 00169 // // Only needs to be implemented if SpaceUsedExcludingSelf() is called. 00170 // static int SpaceUsed(const Type&); 00171 // }; 00172 class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { 00173 protected: 00174 // The reflection implementation needs to call protected methods directly, 00175 // reinterpreting pointers as being to Message instead of a specific Message 00176 // subclass. 00177 friend class GeneratedMessageReflection; 00178 00179 // ExtensionSet stores repeated message extensions as 00180 // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to 00181 // implement SpaceUsed(), and thus need to call SpaceUsedExcludingSelf() 00182 // reinterpreting MessageLite as Message. ExtensionSet also needs to make 00183 // use of AddFromCleared(), which is not part of the public interface. 00184 friend class ExtensionSet; 00185 00186 RepeatedPtrFieldBase(); 00187 00188 // Must be called from destructor. 00189 template <typename TypeHandler> 00190 void Destroy(); 00191 00192 int size() const; 00193 00194 template <typename TypeHandler> 00195 const typename TypeHandler::Type& Get(int index) const; 00196 template <typename TypeHandler> 00197 typename TypeHandler::Type* Mutable(int index); 00198 template <typename TypeHandler> 00199 typename TypeHandler::Type* Add(); 00200 template <typename TypeHandler> 00201 void RemoveLast(); 00202 template <typename TypeHandler> 00203 void Clear(); 00204 template <typename TypeHandler> 00205 void MergeFrom(const RepeatedPtrFieldBase& other); 00206 00207 void Reserve(int new_size); 00208 00209 int Capacity() const; 00210 00211 // Used for constructing iterators. 00212 void* const* raw_data() const; 00213 void** raw_mutable_data() const; 00214 00215 template <typename TypeHandler> 00216 typename TypeHandler::Type** mutable_data(); 00217 template <typename TypeHandler> 00218 const typename TypeHandler::Type* const* data() const; 00219 00220 void Swap(RepeatedPtrFieldBase* other); 00221 00222 void SwapElements(int index1, int index2); 00223 00224 template <typename TypeHandler> 00225 int SpaceUsedExcludingSelf() const; 00226 00227 00228 // Advanced memory management -------------------------------------- 00229 00230 // Like Add(), but if there are no cleared objects to use, returns NULL. 00231 template <typename TypeHandler> 00232 typename TypeHandler::Type* AddFromCleared(); 00233 00234 template <typename TypeHandler> 00235 void AddAllocated(typename TypeHandler::Type* value); 00236 template <typename TypeHandler> 00237 typename TypeHandler::Type* ReleaseLast(); 00238 00239 int ClearedCount() const; 00240 template <typename TypeHandler> 00241 void AddCleared(typename TypeHandler::Type* value); 00242 template <typename TypeHandler> 00243 typename TypeHandler::Type* ReleaseCleared(); 00244 00245 private: 00246 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); 00247 00248 static const int kInitialSize = 4; 00249 00250 void** elements_; 00251 int current_size_; 00252 int allocated_size_; 00253 int total_size_; 00254 00255 void* initial_space_[kInitialSize]; 00256 00257 template <typename TypeHandler> 00258 static inline typename TypeHandler::Type* cast(void* element) { 00259 return reinterpret_cast<typename TypeHandler::Type*>(element); 00260 } 00261 template <typename TypeHandler> 00262 static inline const typename TypeHandler::Type* cast(const void* element) { 00263 return reinterpret_cast<const typename TypeHandler::Type*>(element); 00264 } 00265 }; 00266 00267 template <typename GenericType> 00268 class GenericTypeHandler { 00269 public: 00270 typedef GenericType Type; 00271 static GenericType* New() { return new GenericType; } 00272 static void Delete(GenericType* value) { delete value; } 00273 static void Clear(GenericType* value) { value->Clear(); } 00274 static void Merge(const GenericType& from, GenericType* to) { 00275 to->MergeFrom(from); 00276 } 00277 static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); } 00278 }; 00279 00280 template <> 00281 inline void GenericTypeHandler<MessageLite>::Merge( 00282 const MessageLite& from, MessageLite* to) { 00283 to->CheckTypeAndMergeFrom(from); 00284 } 00285 00286 // HACK: If a class is declared as DLL-exported in MSVC, it insists on 00287 // generating copies of all its methods -- even inline ones -- to include 00288 // in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which 00289 // isn't in the lite library, therefore the lite library cannot link if 00290 // StringTypeHandler is exported. So, we factor out StringTypeHandlerBase, 00291 // export that, then make StringTypeHandler be a subclass which is NOT 00292 // exported. 00293 // TODO(kenton): There has to be a better way. 00294 class LIBPROTOBUF_EXPORT StringTypeHandlerBase { 00295 public: 00296 typedef string Type; 00297 static string* New(); 00298 static void Delete(string* value); 00299 static void Clear(string* value) { value->clear(); } 00300 static void Merge(const string& from, string* to) { *to = from; } 00301 }; 00302 00303 class StringTypeHandler : public StringTypeHandlerBase { 00304 public: 00305 static int SpaceUsed(const string& value) { 00306 return sizeof(value) + StringSpaceUsedExcludingSelf(value); 00307 } 00308 }; 00309 00310 00311 } // namespace internal 00312 00313 // RepeatedPtrField is like RepeatedField, but used for repeated strings or 00314 // Messages. 00315 template <typename Element> 00316 class RepeatedPtrField : public internal::RepeatedPtrFieldBase { 00317 public: 00318 RepeatedPtrField(); 00319 00320 ~RepeatedPtrField(); 00321 00322 int size() const; 00323 00324 const Element& Get(int index) const; 00325 Element* Mutable(int index); 00326 Element* Add(); 00327 void RemoveLast(); // Remove the last element in the array. 00328 void Clear(); 00329 void MergeFrom(const RepeatedPtrField& other); 00330 00331 // Reserve space to expand the field to at least the given size. This only 00332 // resizes the pointer array; it doesn't allocate any objects. If the 00333 // array is grown, it will always be at least doubled in size. 00334 void Reserve(int new_size); 00335 00336 int Capacity() const; 00337 00338 // Gets the underlying array. This pointer is possibly invalidated by 00339 // any add or remove operation. 00340 Element** mutable_data(); 00341 const Element* const* data() const; 00342 00343 // Swap entire contents with "other". 00344 void Swap(RepeatedPtrField* other); 00345 00346 // Swap two elements. 00347 void SwapElements(int index1, int index2); 00348 00349 // STL-like iterator support 00350 typedef internal::RepeatedPtrIterator<Element> iterator; 00351 typedef internal::RepeatedPtrIterator<const Element> const_iterator; 00352 00353 iterator begin(); 00354 const_iterator begin() const; 00355 iterator end(); 00356 const_iterator end() const; 00357 00358 // Custom STL-like iterator that iterates over and returns the underlying 00359 // pointers to Element rather than Element itself. 00360 typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator; 00361 pointer_iterator pointer_begin(); 00362 pointer_iterator pointer_end(); 00363 00364 // Returns (an estimate of) the number of bytes used by the repeated field, 00365 // excluding sizeof(*this). 00366 int SpaceUsedExcludingSelf() const; 00367 00368 // The spaced used just by the pointer array, not counting the objects pointed 00369 // at. Returns zero if the array is inlined (i.e. initial_space_ is being 00370 // used). 00371 int SpaceUsedByArray() const; 00372 00373 // Advanced memory management -------------------------------------- 00374 // When hardcore memory management becomes necessary -- as it often 00375 // does here at Google -- the following methods may be useful. 00376 00377 // Add an already-allocated object, passing ownership to the 00378 // RepeatedPtrField. 00379 void AddAllocated(Element* value); 00380 // Remove the last element and return it, passing ownership to the 00381 // caller. 00382 // Requires: size() > 0 00383 Element* ReleaseLast(); 00384 00385 // When elements are removed by calls to RemoveLast() or Clear(), they 00386 // are not actually freed. Instead, they are cleared and kept so that 00387 // they can be reused later. This can save lots of CPU time when 00388 // repeatedly reusing a protocol message for similar purposes. 00389 // 00390 // Really, extremely hardcore programs may actually want to manipulate 00391 // these objects to better-optimize memory management. These methods 00392 // allow that. 00393 00394 // Get the number of cleared objects that are currently being kept 00395 // around for reuse. 00396 int ClearedCount() const; 00397 // Add an element to the pool of cleared objects, passing ownership to 00398 // the RepeatedPtrField. The element must be cleared prior to calling 00399 // this method. 00400 void AddCleared(Element* value); 00401 // Remove a single element from the cleared pool and return it, passing 00402 // ownership to the caller. The element is guaranteed to be cleared. 00403 // Requires: ClearedCount() > 0 00404 Element* ReleaseCleared(); 00405 00406 protected: 00407 // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only 00408 // subclass it in one place as a hack for compatibility with proto1. The 00409 // subclass needs to know about TypeHandler in order to call protected 00410 // methods on RepeatedPtrFieldBase. 00411 class TypeHandler; 00412 00413 00414 private: 00415 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField); 00416 }; 00417 00418 // implementation ==================================================== 00419 00420 template <typename Element> 00421 inline RepeatedField<Element>::RepeatedField() 00422 : elements_(initial_space_), 00423 current_size_(0), 00424 total_size_(kInitialSize) { 00425 } 00426 00427 template <typename Element> 00428 RepeatedField<Element>::~RepeatedField() { 00429 if (elements_ != initial_space_) { 00430 delete [] elements_; 00431 } 00432 } 00433 00434 template <typename Element> 00435 inline int RepeatedField<Element>::size() const { 00436 return current_size_; 00437 } 00438 00439 template <typename Element> 00440 inline int RepeatedField<Element>::Capacity() const { 00441 return total_size_; 00442 } 00443 00444 template<typename Element> 00445 inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) { 00446 GOOGLE_DCHECK_LT(size(), Capacity()); 00447 elements_[current_size_++] = value; 00448 } 00449 00450 template<typename Element> 00451 inline Element* RepeatedField<Element>::AddAlreadyReserved() { 00452 GOOGLE_DCHECK_LT(size(), Capacity()); 00453 return &elements_[current_size_++]; 00454 } 00455 00456 template <typename Element> 00457 inline const Element& RepeatedField<Element>::Get(int index) const { 00458 GOOGLE_DCHECK_LT(index, size()); 00459 return elements_[index]; 00460 } 00461 00462 template <typename Element> 00463 inline Element* RepeatedField<Element>::Mutable(int index) { 00464 GOOGLE_DCHECK_LT(index, size()); 00465 return elements_ + index; 00466 } 00467 00468 template <typename Element> 00469 inline void RepeatedField<Element>::Set(int index, const Element& value) { 00470 GOOGLE_DCHECK_LT(index, size()); 00471 elements_[index] = value; 00472 } 00473 00474 template <typename Element> 00475 inline void RepeatedField<Element>::Add(const Element& value) { 00476 if (current_size_ == total_size_) Reserve(total_size_ + 1); 00477 elements_[current_size_++] = value; 00478 } 00479 00480 template <typename Element> 00481 inline Element* RepeatedField<Element>::Add() { 00482 if (current_size_ == total_size_) Reserve(total_size_ + 1); 00483 return &elements_[current_size_++]; 00484 } 00485 00486 template <typename Element> 00487 inline void RepeatedField<Element>::RemoveLast() { 00488 GOOGLE_DCHECK_GT(current_size_, 0); 00489 --current_size_; 00490 } 00491 00492 template <typename Element> 00493 inline void RepeatedField<Element>::Clear() { 00494 current_size_ = 0; 00495 } 00496 00497 template <typename Element> 00498 inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { 00499 Reserve(current_size_ + other.current_size_); 00500 CopyArray(elements_ + current_size_, other.elements_, other.current_size_); 00501 current_size_ += other.current_size_; 00502 } 00503 00504 template <typename Element> 00505 inline Element* RepeatedField<Element>::mutable_data() { 00506 return elements_; 00507 } 00508 00509 template <typename Element> 00510 inline const Element* RepeatedField<Element>::data() const { 00511 return elements_; 00512 } 00513 00514 00515 template <typename Element> 00516 void RepeatedField<Element>::Swap(RepeatedField* other) { 00517 Element* swap_elements = elements_; 00518 int swap_current_size = current_size_; 00519 int swap_total_size = total_size_; 00520 // We may not be using initial_space_ but it's not worth checking. Just 00521 // copy it anyway. 00522 Element swap_initial_space[kInitialSize]; 00523 MoveArray(swap_initial_space, initial_space_, kInitialSize); 00524 00525 elements_ = other->elements_; 00526 current_size_ = other->current_size_; 00527 total_size_ = other->total_size_; 00528 MoveArray(initial_space_, other->initial_space_, kInitialSize); 00529 00530 other->elements_ = swap_elements; 00531 other->current_size_ = swap_current_size; 00532 other->total_size_ = swap_total_size; 00533 MoveArray(other->initial_space_, swap_initial_space, kInitialSize); 00534 00535 if (elements_ == other->initial_space_) { 00536 elements_ = initial_space_; 00537 } 00538 if (other->elements_ == initial_space_) { 00539 other->elements_ = other->initial_space_; 00540 } 00541 } 00542 00543 template <typename Element> 00544 void RepeatedField<Element>::SwapElements(int index1, int index2) { 00545 std::swap(elements_[index1], elements_[index2]); 00546 } 00547 00548 template <typename Element> 00549 inline typename RepeatedField<Element>::iterator 00550 RepeatedField<Element>::begin() { 00551 return elements_; 00552 } 00553 template <typename Element> 00554 inline typename RepeatedField<Element>::const_iterator 00555 RepeatedField<Element>::begin() const { 00556 return elements_; 00557 } 00558 template <typename Element> 00559 inline typename RepeatedField<Element>::iterator 00560 RepeatedField<Element>::end() { 00561 return elements_ + current_size_; 00562 } 00563 template <typename Element> 00564 inline typename RepeatedField<Element>::const_iterator 00565 RepeatedField<Element>::end() const { 00566 return elements_ + current_size_; 00567 } 00568 00569 template <typename Element> 00570 inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const { 00571 return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0; 00572 } 00573 00574 // Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant 00575 // amount of code bloat. 00576 template <typename Element> 00577 void RepeatedField<Element>::Reserve(int new_size) { 00578 if (total_size_ >= new_size) return; 00579 00580 Element* old_elements = elements_; 00581 total_size_ = max(total_size_ * 2, new_size); 00582 elements_ = new Element[total_size_]; 00583 MoveArray(elements_, old_elements, current_size_); 00584 if (old_elements != initial_space_) { 00585 delete [] old_elements; 00586 } 00587 } 00588 00589 template <typename Element> 00590 inline void RepeatedField<Element>::Truncate(int new_size) { 00591 GOOGLE_DCHECK_LE(new_size, current_size_); 00592 current_size_ = new_size; 00593 } 00594 00595 template <typename Element> 00596 inline void RepeatedField<Element>::MoveArray( 00597 Element to[], Element from[], int size) { 00598 memcpy(to, from, size * sizeof(Element)); 00599 } 00600 00601 template <typename Element> 00602 inline void RepeatedField<Element>::CopyArray( 00603 Element to[], const Element from[], int size) { 00604 memcpy(to, from, size * sizeof(Element)); 00605 } 00606 00607 00608 // ------------------------------------------------------------------- 00609 00610 namespace internal { 00611 00612 inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() 00613 : elements_(initial_space_), 00614 current_size_(0), 00615 allocated_size_(0), 00616 total_size_(kInitialSize) { 00617 } 00618 00619 template <typename TypeHandler> 00620 void RepeatedPtrFieldBase::Destroy() { 00621 for (int i = 0; i < allocated_size_; i++) { 00622 TypeHandler::Delete(cast<TypeHandler>(elements_[i])); 00623 } 00624 if (elements_ != initial_space_) { 00625 delete [] elements_; 00626 } 00627 } 00628 00629 inline int RepeatedPtrFieldBase::size() const { 00630 return current_size_; 00631 } 00632 00633 00634 template <typename TypeHandler> 00635 inline const typename TypeHandler::Type& 00636 RepeatedPtrFieldBase::Get(int index) const { 00637 GOOGLE_DCHECK_LT(index, size()); 00638 return *cast<TypeHandler>(elements_[index]); 00639 } 00640 00641 template <typename TypeHandler> 00642 inline typename TypeHandler::Type* 00643 RepeatedPtrFieldBase::Mutable(int index) { 00644 GOOGLE_DCHECK_LT(index, size()); 00645 return cast<TypeHandler>(elements_[index]); 00646 } 00647 00648 template <typename TypeHandler> 00649 inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() { 00650 if (current_size_ < allocated_size_) { 00651 return cast<TypeHandler>(elements_[current_size_++]); 00652 } 00653 if (allocated_size_ == total_size_) Reserve(total_size_ + 1); 00654 ++allocated_size_; 00655 typename TypeHandler::Type* result = TypeHandler::New(); 00656 elements_[current_size_++] = result; 00657 return result; 00658 } 00659 00660 template <typename TypeHandler> 00661 inline void RepeatedPtrFieldBase::RemoveLast() { 00662 GOOGLE_DCHECK_GT(current_size_, 0); 00663 TypeHandler::Clear(cast<TypeHandler>(elements_[--current_size_])); 00664 } 00665 00666 template <typename TypeHandler> 00667 void RepeatedPtrFieldBase::Clear() { 00668 for (int i = 0; i < current_size_; i++) { 00669 TypeHandler::Clear(cast<TypeHandler>(elements_[i])); 00670 } 00671 current_size_ = 0; 00672 } 00673 00674 template <typename TypeHandler> 00675 inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { 00676 Reserve(current_size_ + other.current_size_); 00677 for (int i = 0; i < other.current_size_; i++) { 00678 TypeHandler::Merge(other.Get<TypeHandler>(i), Add<TypeHandler>()); 00679 } 00680 } 00681 00682 inline int RepeatedPtrFieldBase::Capacity() const { 00683 return total_size_; 00684 } 00685 00686 inline void* const* RepeatedPtrFieldBase::raw_data() const { 00687 return elements_; 00688 } 00689 00690 inline void** RepeatedPtrFieldBase::raw_mutable_data() const { 00691 return elements_; 00692 } 00693 00694 template <typename TypeHandler> 00695 inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() { 00696 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this 00697 // method entirely. 00698 return reinterpret_cast<typename TypeHandler::Type**>(elements_); 00699 } 00700 00701 template <typename TypeHandler> 00702 inline const typename TypeHandler::Type* const* 00703 RepeatedPtrFieldBase::data() const { 00704 // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this 00705 // method entirely. 00706 return reinterpret_cast<const typename TypeHandler::Type* const*>(elements_); 00707 } 00708 00709 inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { 00710 std::swap(elements_[index1], elements_[index2]); 00711 } 00712 00713 template <typename TypeHandler> 00714 inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const { 00715 int allocated_bytes = 00716 (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0; 00717 for (int i = 0; i < allocated_size_; ++i) { 00718 allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i])); 00719 } 00720 return allocated_bytes; 00721 } 00722 00723 template <typename TypeHandler> 00724 inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() { 00725 if (current_size_ < allocated_size_) { 00726 return cast<TypeHandler>(elements_[current_size_++]); 00727 } else { 00728 return NULL; 00729 } 00730 } 00731 00732 template <typename TypeHandler> 00733 void RepeatedPtrFieldBase::AddAllocated( 00734 typename TypeHandler::Type* value) { 00735 // Make room for the new pointer. 00736 if (current_size_ == total_size_) { 00737 // The array is completely full with no cleared objects, so grow it. 00738 Reserve(total_size_ + 1); 00739 ++allocated_size_; 00740 } else if (allocated_size_ == total_size_) { 00741 // There is no more space in the pointer array because it contains some 00742 // cleared objects awaiting reuse. We don't want to grow the array in this 00743 // case because otherwise a loop calling AddAllocated() followed by Clear() 00744 // would leak memory. 00745 TypeHandler::Delete(cast<TypeHandler>(elements_[current_size_])); 00746 } else if (current_size_ < allocated_size_) { 00747 // We have some cleared objects. We don't care about their order, so we 00748 // can just move the first one to the end to make space. 00749 elements_[allocated_size_] = elements_[current_size_]; 00750 ++allocated_size_; 00751 } else { 00752 // There are no cleared objects. 00753 ++allocated_size_; 00754 } 00755 00756 elements_[current_size_++] = value; 00757 } 00758 00759 template <typename TypeHandler> 00760 inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() { 00761 GOOGLE_DCHECK_GT(current_size_, 0); 00762 typename TypeHandler::Type* result = 00763 cast<TypeHandler>(elements_[--current_size_]); 00764 --allocated_size_; 00765 if (current_size_ < allocated_size_) { 00766 // There are cleared elements on the end; replace the removed element 00767 // with the last allocated element. 00768 elements_[current_size_] = elements_[allocated_size_]; 00769 } 00770 return result; 00771 } 00772 00773 00774 inline int RepeatedPtrFieldBase::ClearedCount() const { 00775 return allocated_size_ - current_size_; 00776 } 00777 00778 template <typename TypeHandler> 00779 inline void RepeatedPtrFieldBase::AddCleared( 00780 typename TypeHandler::Type* value) { 00781 if (allocated_size_ == total_size_) Reserve(total_size_ + 1); 00782 elements_[allocated_size_++] = value; 00783 } 00784 00785 template <typename TypeHandler> 00786 inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { 00787 GOOGLE_DCHECK_GT(allocated_size_, current_size_); 00788 return cast<TypeHandler>(elements_[--allocated_size_]); 00789 } 00790 00791 } // namespace internal 00792 00793 // ------------------------------------------------------------------- 00794 00795 template <typename Element> 00796 class RepeatedPtrField<Element>::TypeHandler 00797 : public internal::GenericTypeHandler<Element> {}; 00798 00799 template <> 00800 class RepeatedPtrField<string>::TypeHandler 00801 : public internal::StringTypeHandler {}; 00802 00803 00804 template <typename Element> 00805 inline RepeatedPtrField<Element>::RepeatedPtrField() {} 00806 00807 template <typename Element> 00808 RepeatedPtrField<Element>::~RepeatedPtrField() { 00809 Destroy<TypeHandler>(); 00810 } 00811 00812 template <typename Element> 00813 inline int RepeatedPtrField<Element>::size() const { 00814 return RepeatedPtrFieldBase::size(); 00815 } 00816 00817 template <typename Element> 00818 inline const Element& RepeatedPtrField<Element>::Get(int index) const { 00819 return RepeatedPtrFieldBase::Get<TypeHandler>(index); 00820 } 00821 00822 template <typename Element> 00823 inline Element* RepeatedPtrField<Element>::Mutable(int index) { 00824 return RepeatedPtrFieldBase::Mutable<TypeHandler>(index); 00825 } 00826 00827 template <typename Element> 00828 inline Element* RepeatedPtrField<Element>::Add() { 00829 return RepeatedPtrFieldBase::Add<TypeHandler>(); 00830 } 00831 00832 template <typename Element> 00833 inline void RepeatedPtrField<Element>::RemoveLast() { 00834 RepeatedPtrFieldBase::RemoveLast<TypeHandler>(); 00835 } 00836 00837 template <typename Element> 00838 inline void RepeatedPtrField<Element>::Clear() { 00839 RepeatedPtrFieldBase::Clear<TypeHandler>(); 00840 } 00841 00842 template <typename Element> 00843 inline void RepeatedPtrField<Element>::MergeFrom( 00844 const RepeatedPtrField& other) { 00845 RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other); 00846 } 00847 00848 template <typename Element> 00849 inline Element** RepeatedPtrField<Element>::mutable_data() { 00850 return RepeatedPtrFieldBase::mutable_data<TypeHandler>(); 00851 } 00852 00853 template <typename Element> 00854 inline const Element* const* RepeatedPtrField<Element>::data() const { 00855 return RepeatedPtrFieldBase::data<TypeHandler>(); 00856 } 00857 00858 template <typename Element> 00859 void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) { 00860 RepeatedPtrFieldBase::Swap(other); 00861 } 00862 00863 template <typename Element> 00864 void RepeatedPtrField<Element>::SwapElements(int index1, int index2) { 00865 RepeatedPtrFieldBase::SwapElements(index1, index2); 00866 } 00867 00868 template <typename Element> 00869 inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const { 00870 return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>(); 00871 } 00872 00873 template <typename Element> 00874 inline void RepeatedPtrField<Element>::AddAllocated(Element* value) { 00875 RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value); 00876 } 00877 00878 template <typename Element> 00879 inline Element* RepeatedPtrField<Element>::ReleaseLast() { 00880 return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>(); 00881 } 00882 00883 00884 template <typename Element> 00885 inline int RepeatedPtrField<Element>::ClearedCount() const { 00886 return RepeatedPtrFieldBase::ClearedCount(); 00887 } 00888 00889 template <typename Element> 00890 inline void RepeatedPtrField<Element>::AddCleared(Element* value) { 00891 return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value); 00892 } 00893 00894 template <typename Element> 00895 inline Element* RepeatedPtrField<Element>::ReleaseCleared() { 00896 return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>(); 00897 } 00898 00899 template <typename Element> 00900 inline void RepeatedPtrField<Element>::Reserve(int new_size) { 00901 return RepeatedPtrFieldBase::Reserve(new_size); 00902 } 00903 00904 template <typename Element> 00905 inline int RepeatedPtrField<Element>::Capacity() const { 00906 return RepeatedPtrFieldBase::Capacity(); 00907 } 00908 00909 // ------------------------------------------------------------------- 00910 00911 namespace internal { 00912 00913 // STL-like iterator implementation for RepeatedPtrField. You should not 00914 // refer to this class directly; use RepeatedPtrField<T>::iterator instead. 00915 // 00916 // The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is 00917 // very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors-inl.h, 00918 // but adds random-access operators and is modified to wrap a void** base 00919 // iterator (since RepeatedPtrField stores its array as a void* array and 00920 // casting void** to T** would violate C++ aliasing rules). 00921 // 00922 // This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin 00923 // (jyasskin@google.com). 00924 template<typename Element> 00925 class RepeatedPtrIterator 00926 : public std::iterator< 00927 std::random_access_iterator_tag, Element> { 00928 public: 00929 typedef RepeatedPtrIterator<Element> iterator; 00930 typedef std::iterator< 00931 std::random_access_iterator_tag, Element> superclass; 00932 00933 // Let the compiler know that these are type names, so we don't have to 00934 // write "typename" in front of them everywhere. 00935 typedef typename superclass::reference reference; 00936 typedef typename superclass::pointer pointer; 00937 typedef typename superclass::difference_type difference_type; 00938 00939 RepeatedPtrIterator() : it_(NULL) {} 00940 explicit RepeatedPtrIterator(void* const* it) : it_(it) {} 00941 00942 // Allow "upcasting" from RepeatedPtrIterator<T**> to 00943 // RepeatedPtrIterator<const T*const*>. 00944 template<typename OtherElement> 00945 RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other) 00946 : it_(other.it_) { 00947 // Force a compiler error if the other type is not convertable to ours. 00948 if (false) { 00949 implicit_cast<Element*, OtherElement*>(0); 00950 } 00951 } 00952 00953 // dereferenceable 00954 reference operator*() const { return *reinterpret_cast<Element*>(*it_); } 00955 pointer operator->() const { return &(operator*()); } 00956 00957 // {inc,dec}rementable 00958 iterator& operator++() { ++it_; return *this; } 00959 iterator operator++(int) { return iterator(it_++); } 00960 iterator& operator--() { --it_; return *this; } 00961 iterator operator--(int) { return iterator(it_--); } 00962 00963 // equality_comparable 00964 bool operator==(const iterator& x) const { return it_ == x.it_; } 00965 bool operator!=(const iterator& x) const { return it_ != x.it_; } 00966 00967 // less_than_comparable 00968 bool operator<(const iterator& x) const { return it_ < x.it_; } 00969 bool operator<=(const iterator& x) const { return it_ <= x.it_; } 00970 bool operator>(const iterator& x) const { return it_ > x.it_; } 00971 bool operator>=(const iterator& x) const { return it_ >= x.it_; } 00972 00973 // addable, subtractable 00974 iterator& operator+=(difference_type d) { 00975 it_ += d; 00976 return *this; 00977 } 00978 friend iterator operator+(iterator it, difference_type d) { 00979 it += d; 00980 return it; 00981 } 00982 friend iterator operator+(difference_type d, iterator it) { 00983 it += d; 00984 return it; 00985 } 00986 iterator& operator-=(difference_type d) { 00987 it_ -= d; 00988 return *this; 00989 } 00990 friend iterator operator-(iterator it, difference_type d) { 00991 it -= d; 00992 return it; 00993 } 00994 00995 // indexable 00996 reference operator[](difference_type d) const { return *(*this + d); } 00997 00998 // random access iterator 00999 difference_type operator-(const iterator& x) const { return it_ - x.it_; } 01000 01001 private: 01002 template<typename OtherElement> 01003 friend class RepeatedPtrIterator; 01004 01005 // The internal iterator. 01006 void* const* it_; 01007 }; 01008 01009 // Provide an iterator that operates on pointers to the underlying objects 01010 // rather than the objects themselves as RepeatedPtrIterator does. 01011 // Consider using this when working with stl algorithms that change 01012 // the array. 01013 template<typename Element> 01014 class RepeatedPtrOverPtrsIterator 01015 : public std::iterator<std::random_access_iterator_tag, Element*> { 01016 public: 01017 typedef RepeatedPtrOverPtrsIterator<Element> iterator; 01018 typedef std::iterator< 01019 std::random_access_iterator_tag, Element*> superclass; 01020 01021 // Let the compiler know that these are type names, so we don't have to 01022 // write "typename" in front of them everywhere. 01023 typedef typename superclass::reference reference; 01024 typedef typename superclass::pointer pointer; 01025 typedef typename superclass::difference_type difference_type; 01026 01027 RepeatedPtrOverPtrsIterator() : it_(NULL) {} 01028 explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {} 01029 01030 // dereferenceable 01031 reference operator*() const { return *reinterpret_cast<Element**>(it_); } 01032 pointer operator->() const { return &(operator*()); } 01033 01034 // {inc,dec}rementable 01035 iterator& operator++() { ++it_; return *this; } 01036 iterator operator++(int) { return iterator(it_++); } 01037 iterator& operator--() { --it_; return *this; } 01038 iterator operator--(int) { return iterator(it_--); } 01039 01040 // equality_comparable 01041 bool operator==(const iterator& x) const { return it_ == x.it_; } 01042 bool operator!=(const iterator& x) const { return it_ != x.it_; } 01043 01044 // less_than_comparable 01045 bool operator<(const iterator& x) const { return it_ < x.it_; } 01046 bool operator<=(const iterator& x) const { return it_ <= x.it_; } 01047 bool operator>(const iterator& x) const { return it_ > x.it_; } 01048 bool operator>=(const iterator& x) const { return it_ >= x.it_; } 01049 01050 // addable, subtractable 01051 iterator& operator+=(difference_type d) { 01052 it_ += d; 01053 return *this; 01054 } 01055 friend iterator operator+(iterator it, difference_type d) { 01056 it += d; 01057 return it; 01058 } 01059 friend iterator operator+(difference_type d, iterator it) { 01060 it += d; 01061 return it; 01062 } 01063 iterator& operator-=(difference_type d) { 01064 it_ -= d; 01065 return *this; 01066 } 01067 friend iterator operator-(iterator it, difference_type d) { 01068 it -= d; 01069 return it; 01070 } 01071 01072 // indexable 01073 reference operator[](difference_type d) const { return *(*this + d); } 01074 01075 // random access iterator 01076 difference_type operator-(const iterator& x) const { return it_ - x.it_; } 01077 01078 private: 01079 template<typename OtherElement> 01080 friend class RepeatedPtrIterator; 01081 01082 // The internal iterator. 01083 void** it_; 01084 }; 01085 01086 01087 } // namespace internal 01088 01089 template <typename Element> 01090 inline typename RepeatedPtrField<Element>::iterator 01091 RepeatedPtrField<Element>::begin() { 01092 return iterator(raw_data()); 01093 } 01094 template <typename Element> 01095 inline typename RepeatedPtrField<Element>::const_iterator 01096 RepeatedPtrField<Element>::begin() const { 01097 return iterator(raw_data()); 01098 } 01099 template <typename Element> 01100 inline typename RepeatedPtrField<Element>::iterator 01101 RepeatedPtrField<Element>::end() { 01102 return iterator(raw_data() + size()); 01103 } 01104 template <typename Element> 01105 inline typename RepeatedPtrField<Element>::const_iterator 01106 RepeatedPtrField<Element>::end() const { 01107 return iterator(raw_data() + size()); 01108 } 01109 01110 template <typename Element> 01111 inline typename RepeatedPtrField<Element>::pointer_iterator 01112 RepeatedPtrField<Element>::pointer_begin() { 01113 return pointer_iterator(raw_mutable_data()); 01114 } 01115 template <typename Element> 01116 inline typename RepeatedPtrField<Element>::pointer_iterator 01117 RepeatedPtrField<Element>::pointer_end() { 01118 return pointer_iterator(raw_mutable_data() + size()); 01119 } 01120 01121 01122 // Iterators and helper functions that follow the spirit of the STL 01123 // std::back_insert_iterator and std::back_inserter but are tailor-made 01124 // for RepeatedField and RepatedPtrField. Typical usage would be: 01125 // 01126 // std::copy(some_sequence.begin(), some_sequence.end(), 01127 // google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence())); 01128 // 01129 // Ported by johannes from util/gtl/proto-array-iterators-inl.h 01130 01131 namespace internal { 01132 // A back inserter for RepeatedField objects. 01133 template<typename T> class RepeatedFieldBackInsertIterator 01134 : public std::iterator<std::output_iterator_tag, T> { 01135 public: 01136 explicit RepeatedFieldBackInsertIterator( 01137 RepeatedField<T>* const mutable_field) 01138 : field_(mutable_field) { 01139 } 01140 RepeatedFieldBackInsertIterator<T>& operator=(const T& value) { 01141 field_->Add(value); 01142 return *this; 01143 } 01144 RepeatedFieldBackInsertIterator<T>& operator*() { 01145 return *this; 01146 } 01147 RepeatedFieldBackInsertIterator<T>& operator++() { 01148 return *this; 01149 } 01150 RepeatedFieldBackInsertIterator<T>& operator++(int ignores_parameter) { 01151 return *this; 01152 } 01153 01154 private: 01155 RepeatedField<T>* const field_; 01156 }; 01157 01158 // A back inserter for RepeatedPtrField objects. 01159 template<typename T> class RepeatedPtrFieldBackInsertIterator 01160 : public std::iterator<std::output_iterator_tag, T> { 01161 public: 01162 RepeatedPtrFieldBackInsertIterator( 01163 RepeatedPtrField<T>* const mutable_field) 01164 : field_(mutable_field) { 01165 } 01166 RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) { 01167 *field_->Add() = value; 01168 return *this; 01169 } 01170 RepeatedPtrFieldBackInsertIterator<T>& operator=( 01171 const T* const ptr_to_value) { 01172 *field_->Add() = *ptr_to_value; 01173 return *this; 01174 } 01175 RepeatedPtrFieldBackInsertIterator<T>& operator*() { 01176 return *this; 01177 } 01178 RepeatedPtrFieldBackInsertIterator<T>& operator++() { 01179 return *this; 01180 } 01181 RepeatedPtrFieldBackInsertIterator<T>& operator++(int ignores_parameter) { 01182 return *this; 01183 } 01184 01185 private: 01186 RepeatedPtrField<T>* const field_; 01187 }; 01188 01189 // A back inserter for RepeatedPtrFields that inserts by transfering ownership 01190 // of a pointer. 01191 template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator 01192 : public std::iterator<std::output_iterator_tag, T> { 01193 public: 01194 explicit AllocatedRepeatedPtrFieldBackInsertIterator( 01195 RepeatedPtrField<T>* const mutable_field) 01196 : field_(mutable_field) { 01197 } 01198 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=( 01199 T* const ptr_to_value) { 01200 field_->AddAllocated(ptr_to_value); 01201 return *this; 01202 } 01203 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() { 01204 return *this; 01205 } 01206 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() { 01207 return *this; 01208 } 01209 AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++( 01210 int ignores_parameter) { 01211 return *this; 01212 } 01213 01214 private: 01215 RepeatedPtrField<T>* const field_; 01216 }; 01217 } // namespace internal 01218 01219 // Provides a back insert iterator for RepeatedField instances, 01220 // similar to std::back_inserter(). Note the identically named 01221 // function for RepeatedPtrField instances. 01222 template<typename T> internal::RepeatedFieldBackInsertIterator<T> 01223 RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) { 01224 return internal::RepeatedFieldBackInsertIterator<T>(mutable_field); 01225 } 01226 01227 // Provides a back insert iterator for RepeatedPtrField instances, 01228 // similar to std::back_inserter(). Note the identically named 01229 // function for RepeatedField instances. 01230 template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T> 01231 RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) { 01232 return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field); 01233 } 01234 01235 // Provides a back insert iterator for RepeatedPtrField instances 01236 // similar to std::back_inserter() which transfers the ownership while 01237 // copying elements. 01238 template<typename T> internal::AllocatedRepeatedPtrFieldBackInsertIterator<T> 01239 AllocatedRepeatedPtrFieldBackInserter( 01240 RepeatedPtrField<T>* const mutable_field) { 01241 return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>( 01242 mutable_field); 01243 } 01244 01245 } // namespace protobuf 01246 01247 } // namespace google 01248 #endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__