// Protocol Buffers - Google's data interchange format // Copyright 2023 Google LLC. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ #define UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ #include #include #include #include #include "absl/strings/string_view.h" #include "protos/protos.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/array.h" #include "upb/message/copy.h" // Must be last: #include "upb/message/types.h" #include "upb/port/def.inc" namespace protos { namespace internal { // TODO: Implement std iterator for messages template class RepeatedFieldScalarProxy; template class RepeatedFieldStringProxy; struct IteratorTestPeer; template class Iterator; template class ReferenceProxy; template class InjectedRelationalsImpl { using RP = ReferenceProxy; using V = typename PolicyT::value_type; friend bool operator==(RP a, V b) { return static_cast(a) == b; } friend bool operator==(V a, RP b) { return a == static_cast(b); } friend bool operator==(RP a, RP b) { return static_cast(a) == static_cast(b); } friend bool operator!=(RP a, V b) { return static_cast(a) != b; } friend bool operator!=(V a, RP b) { return a != static_cast(b); } friend bool operator!=(RP a, RP b) { return static_cast(a) != static_cast(b); } friend bool operator<(RP a, V b) { return static_cast(a) < b; } friend bool operator<(V a, RP b) { return a < static_cast(b); } friend bool operator<(RP a, RP b) { return static_cast(a) < static_cast(b); } friend bool operator<=(RP a, V b) { return static_cast(a) <= b; } friend bool operator<=(V a, RP b) { return a <= static_cast(b); } friend bool operator<=(RP a, RP b) { return static_cast(a) <= static_cast(b); } friend bool operator>(RP a, V b) { return static_cast(a) > b; } friend bool operator>(V a, RP b) { return a > static_cast(b); } friend bool operator>(RP a, RP b) { return static_cast(a) > static_cast(b); } friend bool operator>=(RP a, V b) { return static_cast(a) >= b; } friend bool operator>=(V a, RP b) { return a >= static_cast(b); } friend bool operator>=(RP a, RP b) { return static_cast(a) >= static_cast(b); } }; class NoInjectedRelationalsImpl {}; // We need to inject relationals for the string references because the // relationals for string_view are templates and won't allow for implicit // conversions from ReferenceProxy to string_view before deduction. template using InjectedRelationals = std::conditional_t< std::is_same_v, absl::string_view>, InjectedRelationalsImpl, NoInjectedRelationalsImpl>; template class ReferenceProxy : InjectedRelationals { using value_type = typename PolicyT::value_type; public: ReferenceProxy(const ReferenceProxy&) = default; ReferenceProxy& operator=(const ReferenceProxy& other) { // Assign through the references // TODO: Make this better for strings to avoid the copy. it_.Set(other.it_.Get()); return *this; } friend void swap(ReferenceProxy a, ReferenceProxy b) { a.it_.swap(b.it_); } operator value_type() const { return it_.Get(); } void operator=(const value_type& value) const { it_.Set(value); } void operator=(value_type&& value) const { it_.Set(std::move(value)); } Iterator operator&() const { return Iterator(it_); } private: friend IteratorTestPeer; friend ReferenceProxy; friend Iterator; explicit ReferenceProxy(typename PolicyT::Payload elem) : it_(elem) {} typename PolicyT::Payload it_; }; template