1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2019 Alexey Edelev <semlanik@gmail.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QPROTOBUFSELFCHECKITERATOR_H
6#define QPROTOBUFSELFCHECKITERATOR_H
7
8#include <QtProtobuf/qtprotobufglobal.h>
9#include <QtCore/qnumeric.h>
10
11#include <QtCore/QByteArray>
12
13#include <iterator>
14
15QT_BEGIN_NAMESPACE
16
17namespace QtProtobufPrivate {
18class QProtobufSelfcheckIterator
19{
20public:
21 using difference_type = QByteArray::difference_type;
22 using iterator_category = std::random_access_iterator_tag;
23 using value_type = QByteArray::value_type;
24 using pointer = QByteArray::pointer;
25 using reference = QByteArray::reference;
26
27 static QProtobufSelfcheckIterator fromView(QByteArrayView container)
28 {
29 QProtobufSelfcheckIterator iter(container);
30 return iter;
31 }
32
33 QProtobufSelfcheckIterator(const QProtobufSelfcheckIterator &other) = default;
34 QProtobufSelfcheckIterator &operator=(const QProtobufSelfcheckIterator &other) = default;
35
36 explicit operator QByteArray::const_iterator &() { return m_it; }
37 explicit operator QByteArray::const_iterator() const { return m_it; }
38
39 char operator*()
40 {
41 Q_ASSERT(isValid());
42 return *m_it;
43 }
44
45 bool isValid() const noexcept { return m_containerBegin <= m_it && m_it <= m_containerEnd; }
46
47 QProtobufSelfcheckIterator &operator++() noexcept
48 {
49 if (!isValid()) {
50 qWarning(msg: "Deserialization failed: Unexpected end of data.");
51 return *this;
52 }
53 ++m_it;
54 return *this;
55 }
56
57 QProtobufSelfcheckIterator operator++(int) noexcept
58 {
59 QProtobufSelfcheckIterator old(*this);
60 operator++();
61 return old;
62 }
63
64 QProtobufSelfcheckIterator &operator--() noexcept
65 {
66 if (!isValid()) {
67 qWarning(msg: "Deserialization failed: Unexpected end of data.");
68 return *this;
69 }
70
71 --m_it;
72 return *this;
73 }
74
75 QProtobufSelfcheckIterator operator--(int) noexcept
76 {
77 QProtobufSelfcheckIterator old(*this);
78 operator--();
79 return old;
80 }
81
82 QProtobufSelfcheckIterator &operator+=(qsizetype count) noexcept
83 {
84 if (!isValid()) {
85 qWarning(msg: "Deserialization failed: Unexpected end of data.");
86 return *this;
87 }
88 m_it += count;
89 return *this;
90 }
91
92 QProtobufSelfcheckIterator &operator-=(qsizetype count) noexcept
93 {
94 if (!isValid()) {
95 qWarning(msg: "Deserialization failed: Unexpected end of data.");
96 return *this;
97 }
98 m_it -= count;
99 return *this;
100 }
101
102 const char *data() const { return m_it; }
103 qsizetype bytesLeft() const { return isValid() ? std::distance(first: m_it, last: m_containerEnd) : 0; }
104
105private:
106 explicit QProtobufSelfcheckIterator(QByteArrayView container)
107 : m_containerBegin(container.begin()),
108 m_containerEnd(container.end()),
109 m_it(container.begin())
110 {
111 }
112
113 friend bool operator==(const QProtobufSelfcheckIterator &lhs,
114 const QProtobufSelfcheckIterator &rhs) noexcept
115 {
116 Q_ASSERT(lhs.m_containerBegin == rhs.m_containerBegin);
117 Q_ASSERT(lhs.m_containerEnd == rhs.m_containerEnd);
118 return lhs.m_it == rhs.m_it;
119 }
120 friend bool operator!=(const QProtobufSelfcheckIterator &lhs,
121 const QProtobufSelfcheckIterator &rhs) noexcept
122 {
123 Q_ASSERT(lhs.m_containerBegin == rhs.m_containerBegin);
124 Q_ASSERT(lhs.m_containerEnd == rhs.m_containerEnd);
125 return lhs.m_it != rhs.m_it;
126 }
127 friend bool operator==(const QProtobufSelfcheckIterator &lhs,
128 const QByteArray::const_iterator &other) noexcept
129 {
130 Q_ASSERT(lhs.m_containerBegin <= other && other <= lhs.m_containerEnd);
131 return lhs.m_it == other;
132 }
133 friend bool operator!=(const QProtobufSelfcheckIterator &lhs,
134 const QByteArray::const_iterator &other) noexcept
135 {
136 Q_ASSERT(lhs.m_containerBegin <= other && other <= lhs.m_containerEnd);
137 return lhs.m_it != other;
138 }
139
140 friend qint64 operator-(const QProtobufSelfcheckIterator &lhs,
141 const QProtobufSelfcheckIterator &rhs) noexcept
142 {
143 Q_ASSERT(lhs.m_containerBegin == rhs.m_containerBegin);
144 return lhs.m_it - rhs.m_it;
145 }
146
147 QByteArrayView::const_iterator m_containerBegin;
148 QByteArrayView::const_iterator m_containerEnd;
149 QByteArrayView::const_iterator m_it;
150};
151
152inline QProtobufSelfcheckIterator operator+(const QProtobufSelfcheckIterator &it, qsizetype length)
153{
154 QProtobufSelfcheckIterator copy = it;
155 copy += length;
156 return copy;
157}
158
159inline QProtobufSelfcheckIterator operator-(const QProtobufSelfcheckIterator &it, qsizetype length)
160{
161 QProtobufSelfcheckIterator copy = it;
162 copy -= length;
163 return copy;
164}
165} // namespace QtProtobufPrivate
166
167QT_END_NAMESPACE
168
169#endif // QPROTOBUFSELFCHECKITERATOR_H
170

source code of qtgrpc/src/protobuf/qprotobufselfcheckiterator.h