/* * Copyright (c) 2009-2023, Google LLC * All rights reserved. * * 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 Google LLC 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/collections/array.h" #include "upb/mem/arena.h" #include "upb/message/copy.h" // Must be last: #include "upb/port/def.inc" namespace protos { namespace internal { // TODO(b/279086429): 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(sbenza): 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