1ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format
2ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc.  All rights reserved.
3ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/
4ffe3c632Sopenharmony_ci//
5ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
6ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are
7ffe3c632Sopenharmony_ci// met:
8ffe3c632Sopenharmony_ci//
9ffe3c632Sopenharmony_ci//     * Redistributions of source code must retain the above copyright
10ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer.
11ffe3c632Sopenharmony_ci//     * Redistributions in binary form must reproduce the above
12ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer
13ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the
14ffe3c632Sopenharmony_ci// distribution.
15ffe3c632Sopenharmony_ci//     * Neither the name of Google Inc. nor the names of its
16ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from
17ffe3c632Sopenharmony_ci// this software without specific prior written permission.
18ffe3c632Sopenharmony_ci//
19ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30ffe3c632Sopenharmony_ci
31ffe3c632Sopenharmony_ci#import "GPBCodedInputStream_PackagePrivate.h"
32ffe3c632Sopenharmony_ci
33ffe3c632Sopenharmony_ci#import "GPBDictionary_PackagePrivate.h"
34ffe3c632Sopenharmony_ci#import "GPBMessage_PackagePrivate.h"
35ffe3c632Sopenharmony_ci#import "GPBUnknownFieldSet_PackagePrivate.h"
36ffe3c632Sopenharmony_ci#import "GPBUtilities_PackagePrivate.h"
37ffe3c632Sopenharmony_ci#import "GPBWireFormat.h"
38ffe3c632Sopenharmony_ci
39ffe3c632Sopenharmony_ciNSString *const GPBCodedInputStreamException =
40ffe3c632Sopenharmony_ci    GPBNSStringifySymbol(GPBCodedInputStreamException);
41ffe3c632Sopenharmony_ci
42ffe3c632Sopenharmony_ciNSString *const GPBCodedInputStreamUnderlyingErrorKey =
43ffe3c632Sopenharmony_ci    GPBNSStringifySymbol(GPBCodedInputStreamUnderlyingErrorKey);
44ffe3c632Sopenharmony_ci
45ffe3c632Sopenharmony_ciNSString *const GPBCodedInputStreamErrorDomain =
46ffe3c632Sopenharmony_ci    GPBNSStringifySymbol(GPBCodedInputStreamErrorDomain);
47ffe3c632Sopenharmony_ci
48ffe3c632Sopenharmony_ci// Matching:
49ffe3c632Sopenharmony_ci// https://github.com/protocolbuffers/protobuf/blob/master/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L62
50ffe3c632Sopenharmony_ci//  private static final int DEFAULT_RECURSION_LIMIT = 100;
51ffe3c632Sopenharmony_ci// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/io/coded_stream.cc#L86
52ffe3c632Sopenharmony_ci//  int CodedInputStream::default_recursion_limit_ = 100;
53ffe3c632Sopenharmony_cistatic const NSUInteger kDefaultRecursionLimit = 100;
54ffe3c632Sopenharmony_ci
55ffe3c632Sopenharmony_cistatic void RaiseException(NSInteger code, NSString *reason) {
56ffe3c632Sopenharmony_ci  NSDictionary *errorInfo = nil;
57ffe3c632Sopenharmony_ci  if ([reason length]) {
58ffe3c632Sopenharmony_ci    errorInfo = @{ GPBErrorReasonKey: reason };
59ffe3c632Sopenharmony_ci  }
60ffe3c632Sopenharmony_ci  NSError *error = [NSError errorWithDomain:GPBCodedInputStreamErrorDomain
61ffe3c632Sopenharmony_ci                                       code:code
62ffe3c632Sopenharmony_ci                                   userInfo:errorInfo];
63ffe3c632Sopenharmony_ci
64ffe3c632Sopenharmony_ci  NSDictionary *exceptionInfo =
65ffe3c632Sopenharmony_ci      @{ GPBCodedInputStreamUnderlyingErrorKey: error };
66ffe3c632Sopenharmony_ci  [[NSException exceptionWithName:GPBCodedInputStreamException
67ffe3c632Sopenharmony_ci                           reason:reason
68ffe3c632Sopenharmony_ci                         userInfo:exceptionInfo] raise];
69ffe3c632Sopenharmony_ci}
70ffe3c632Sopenharmony_ci
71ffe3c632Sopenharmony_cistatic void CheckRecursionLimit(GPBCodedInputStreamState *state) {
72ffe3c632Sopenharmony_ci  if (state->recursionDepth >= kDefaultRecursionLimit) {
73ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
74ffe3c632Sopenharmony_ci  }
75ffe3c632Sopenharmony_ci}
76ffe3c632Sopenharmony_ci
77ffe3c632Sopenharmony_cistatic void CheckSize(GPBCodedInputStreamState *state, size_t size) {
78ffe3c632Sopenharmony_ci  size_t newSize = state->bufferPos + size;
79ffe3c632Sopenharmony_ci  if (newSize > state->bufferSize) {
80ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorInvalidSize, nil);
81ffe3c632Sopenharmony_ci  }
82ffe3c632Sopenharmony_ci  if (newSize > state->currentLimit) {
83ffe3c632Sopenharmony_ci    // Fast forward to end of currentLimit;
84ffe3c632Sopenharmony_ci    state->bufferPos = state->currentLimit;
85ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil);
86ffe3c632Sopenharmony_ci  }
87ffe3c632Sopenharmony_ci}
88ffe3c632Sopenharmony_ci
89ffe3c632Sopenharmony_cistatic int8_t ReadRawByte(GPBCodedInputStreamState *state) {
90ffe3c632Sopenharmony_ci  CheckSize(state, sizeof(int8_t));
91ffe3c632Sopenharmony_ci  return ((int8_t *)state->bytes)[state->bufferPos++];
92ffe3c632Sopenharmony_ci}
93ffe3c632Sopenharmony_ci
94ffe3c632Sopenharmony_cistatic int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) {
95ffe3c632Sopenharmony_ci  CheckSize(state, sizeof(int32_t));
96ffe3c632Sopenharmony_ci  // Not using OSReadLittleInt32 because it has undocumented dependency
97ffe3c632Sopenharmony_ci  // on reads being aligned.
98ffe3c632Sopenharmony_ci  int32_t value;
99ffe3c632Sopenharmony_ci  memcpy(&value, state->bytes + state->bufferPos, sizeof(int32_t));
100ffe3c632Sopenharmony_ci  value = OSSwapLittleToHostInt32(value);
101ffe3c632Sopenharmony_ci  state->bufferPos += sizeof(int32_t);
102ffe3c632Sopenharmony_ci  return value;
103ffe3c632Sopenharmony_ci}
104ffe3c632Sopenharmony_ci
105ffe3c632Sopenharmony_cistatic int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
106ffe3c632Sopenharmony_ci  CheckSize(state, sizeof(int64_t));
107ffe3c632Sopenharmony_ci  // Not using OSReadLittleInt64 because it has undocumented dependency
108ffe3c632Sopenharmony_ci  // on reads being aligned.  
109ffe3c632Sopenharmony_ci  int64_t value;
110ffe3c632Sopenharmony_ci  memcpy(&value, state->bytes + state->bufferPos, sizeof(int64_t));
111ffe3c632Sopenharmony_ci  value = OSSwapLittleToHostInt64(value);
112ffe3c632Sopenharmony_ci  state->bufferPos += sizeof(int64_t);
113ffe3c632Sopenharmony_ci  return value;
114ffe3c632Sopenharmony_ci}
115ffe3c632Sopenharmony_ci
116ffe3c632Sopenharmony_cistatic int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
117ffe3c632Sopenharmony_ci  int32_t shift = 0;
118ffe3c632Sopenharmony_ci  int64_t result = 0;
119ffe3c632Sopenharmony_ci  while (shift < 64) {
120ffe3c632Sopenharmony_ci    int8_t b = ReadRawByte(state);
121ffe3c632Sopenharmony_ci    result |= (int64_t)((uint64_t)(b & 0x7F) << shift);
122ffe3c632Sopenharmony_ci    if ((b & 0x80) == 0) {
123ffe3c632Sopenharmony_ci      return result;
124ffe3c632Sopenharmony_ci    }
125ffe3c632Sopenharmony_ci    shift += 7;
126ffe3c632Sopenharmony_ci  }
127ffe3c632Sopenharmony_ci  RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64");
128ffe3c632Sopenharmony_ci  return 0;
129ffe3c632Sopenharmony_ci}
130ffe3c632Sopenharmony_ci
131ffe3c632Sopenharmony_cistatic int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
132ffe3c632Sopenharmony_ci  return (int32_t)ReadRawVarint64(state);
133ffe3c632Sopenharmony_ci}
134ffe3c632Sopenharmony_ci
135ffe3c632Sopenharmony_cistatic void SkipRawData(GPBCodedInputStreamState *state, size_t size) {
136ffe3c632Sopenharmony_ci  CheckSize(state, size);
137ffe3c632Sopenharmony_ci  state->bufferPos += size;
138ffe3c632Sopenharmony_ci}
139ffe3c632Sopenharmony_ci
140ffe3c632Sopenharmony_cidouble GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state) {
141ffe3c632Sopenharmony_ci  int64_t value = ReadRawLittleEndian64(state);
142ffe3c632Sopenharmony_ci  return GPBConvertInt64ToDouble(value);
143ffe3c632Sopenharmony_ci}
144ffe3c632Sopenharmony_ci
145ffe3c632Sopenharmony_cifloat GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state) {
146ffe3c632Sopenharmony_ci  int32_t value = ReadRawLittleEndian32(state);
147ffe3c632Sopenharmony_ci  return GPBConvertInt32ToFloat(value);
148ffe3c632Sopenharmony_ci}
149ffe3c632Sopenharmony_ci
150ffe3c632Sopenharmony_ciuint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state) {
151ffe3c632Sopenharmony_ci  uint64_t value = ReadRawVarint64(state);
152ffe3c632Sopenharmony_ci  return value;
153ffe3c632Sopenharmony_ci}
154ffe3c632Sopenharmony_ci
155ffe3c632Sopenharmony_ciuint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state) {
156ffe3c632Sopenharmony_ci  uint32_t value = ReadRawVarint32(state);
157ffe3c632Sopenharmony_ci  return value;
158ffe3c632Sopenharmony_ci}
159ffe3c632Sopenharmony_ci
160ffe3c632Sopenharmony_ciint64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state) {
161ffe3c632Sopenharmony_ci  int64_t value = ReadRawVarint64(state);
162ffe3c632Sopenharmony_ci  return value;
163ffe3c632Sopenharmony_ci}
164ffe3c632Sopenharmony_ci
165ffe3c632Sopenharmony_ciint32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state) {
166ffe3c632Sopenharmony_ci  int32_t value = ReadRawVarint32(state);
167ffe3c632Sopenharmony_ci  return value;
168ffe3c632Sopenharmony_ci}
169ffe3c632Sopenharmony_ci
170ffe3c632Sopenharmony_ciuint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state) {
171ffe3c632Sopenharmony_ci  uint64_t value = ReadRawLittleEndian64(state);
172ffe3c632Sopenharmony_ci  return value;
173ffe3c632Sopenharmony_ci}
174ffe3c632Sopenharmony_ci
175ffe3c632Sopenharmony_ciuint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state) {
176ffe3c632Sopenharmony_ci  uint32_t value = ReadRawLittleEndian32(state);
177ffe3c632Sopenharmony_ci  return value;
178ffe3c632Sopenharmony_ci}
179ffe3c632Sopenharmony_ci
180ffe3c632Sopenharmony_ciint32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state) {
181ffe3c632Sopenharmony_ci  int32_t value = ReadRawVarint32(state);
182ffe3c632Sopenharmony_ci  return value;
183ffe3c632Sopenharmony_ci}
184ffe3c632Sopenharmony_ci
185ffe3c632Sopenharmony_ciint32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state) {
186ffe3c632Sopenharmony_ci  int32_t value = ReadRawLittleEndian32(state);
187ffe3c632Sopenharmony_ci  return value;
188ffe3c632Sopenharmony_ci}
189ffe3c632Sopenharmony_ci
190ffe3c632Sopenharmony_ciint64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state) {
191ffe3c632Sopenharmony_ci  int64_t value = ReadRawLittleEndian64(state);
192ffe3c632Sopenharmony_ci  return value;
193ffe3c632Sopenharmony_ci}
194ffe3c632Sopenharmony_ci
195ffe3c632Sopenharmony_ciint32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state) {
196ffe3c632Sopenharmony_ci  int32_t value = GPBDecodeZigZag32(ReadRawVarint32(state));
197ffe3c632Sopenharmony_ci  return value;
198ffe3c632Sopenharmony_ci}
199ffe3c632Sopenharmony_ci
200ffe3c632Sopenharmony_ciint64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) {
201ffe3c632Sopenharmony_ci  int64_t value = GPBDecodeZigZag64(ReadRawVarint64(state));
202ffe3c632Sopenharmony_ci  return value;
203ffe3c632Sopenharmony_ci}
204ffe3c632Sopenharmony_ci
205ffe3c632Sopenharmony_ciBOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) {
206ffe3c632Sopenharmony_ci  return ReadRawVarint64(state) != 0;
207ffe3c632Sopenharmony_ci}
208ffe3c632Sopenharmony_ci
209ffe3c632Sopenharmony_ciint32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
210ffe3c632Sopenharmony_ci  if (GPBCodedInputStreamIsAtEnd(state)) {
211ffe3c632Sopenharmony_ci    state->lastTag = 0;
212ffe3c632Sopenharmony_ci    return 0;
213ffe3c632Sopenharmony_ci  }
214ffe3c632Sopenharmony_ci
215ffe3c632Sopenharmony_ci  state->lastTag = ReadRawVarint32(state);
216ffe3c632Sopenharmony_ci  // Tags have to include a valid wireformat.
217ffe3c632Sopenharmony_ci  if (!GPBWireFormatIsValidTag(state->lastTag)) {
218ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorInvalidTag,
219ffe3c632Sopenharmony_ci                   @"Invalid wireformat in tag.");
220ffe3c632Sopenharmony_ci  }
221ffe3c632Sopenharmony_ci  // Zero is not a valid field number.
222ffe3c632Sopenharmony_ci  if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) {
223ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorInvalidTag,
224ffe3c632Sopenharmony_ci                   @"A zero field number on the wire is invalid.");
225ffe3c632Sopenharmony_ci  }
226ffe3c632Sopenharmony_ci  return state->lastTag;
227ffe3c632Sopenharmony_ci}
228ffe3c632Sopenharmony_ci
229ffe3c632Sopenharmony_ciNSString *GPBCodedInputStreamReadRetainedString(
230ffe3c632Sopenharmony_ci    GPBCodedInputStreamState *state) {
231ffe3c632Sopenharmony_ci  int32_t size = ReadRawVarint32(state);
232ffe3c632Sopenharmony_ci  NSString *result;
233ffe3c632Sopenharmony_ci  if (size == 0) {
234ffe3c632Sopenharmony_ci    result = @"";
235ffe3c632Sopenharmony_ci  } else {
236ffe3c632Sopenharmony_ci    CheckSize(state, size);
237ffe3c632Sopenharmony_ci    result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos]
238ffe3c632Sopenharmony_ci                                      length:size
239ffe3c632Sopenharmony_ci                                    encoding:NSUTF8StringEncoding];
240ffe3c632Sopenharmony_ci    state->bufferPos += size;
241ffe3c632Sopenharmony_ci    if (!result) {
242ffe3c632Sopenharmony_ci#ifdef DEBUG
243ffe3c632Sopenharmony_ci      // https://developers.google.com/protocol-buffers/docs/proto#scalar
244ffe3c632Sopenharmony_ci      NSLog(@"UTF-8 failure, is some field type 'string' when it should be "
245ffe3c632Sopenharmony_ci            @"'bytes'?");
246ffe3c632Sopenharmony_ci#endif
247ffe3c632Sopenharmony_ci      RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil);
248ffe3c632Sopenharmony_ci    }
249ffe3c632Sopenharmony_ci  }
250ffe3c632Sopenharmony_ci  return result;
251ffe3c632Sopenharmony_ci}
252ffe3c632Sopenharmony_ci
253ffe3c632Sopenharmony_ciNSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) {
254ffe3c632Sopenharmony_ci  int32_t size = ReadRawVarint32(state);
255ffe3c632Sopenharmony_ci  if (size < 0) return nil;
256ffe3c632Sopenharmony_ci  CheckSize(state, size);
257ffe3c632Sopenharmony_ci  NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos
258ffe3c632Sopenharmony_ci                                          length:size];
259ffe3c632Sopenharmony_ci  state->bufferPos += size;
260ffe3c632Sopenharmony_ci  return result;
261ffe3c632Sopenharmony_ci}
262ffe3c632Sopenharmony_ci
263ffe3c632Sopenharmony_ciNSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
264ffe3c632Sopenharmony_ci    GPBCodedInputStreamState *state) {
265ffe3c632Sopenharmony_ci  int32_t size = ReadRawVarint32(state);
266ffe3c632Sopenharmony_ci  if (size < 0) return nil;
267ffe3c632Sopenharmony_ci  CheckSize(state, size);
268ffe3c632Sopenharmony_ci  // Cast is safe because freeWhenDone is NO.
269ffe3c632Sopenharmony_ci  NSData *result = [[NSData alloc]
270ffe3c632Sopenharmony_ci      initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos)
271ffe3c632Sopenharmony_ci                   length:size
272ffe3c632Sopenharmony_ci             freeWhenDone:NO];
273ffe3c632Sopenharmony_ci  state->bufferPos += size;
274ffe3c632Sopenharmony_ci  return result;
275ffe3c632Sopenharmony_ci}
276ffe3c632Sopenharmony_ci
277ffe3c632Sopenharmony_cisize_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
278ffe3c632Sopenharmony_ci                                    size_t byteLimit) {
279ffe3c632Sopenharmony_ci  byteLimit += state->bufferPos;
280ffe3c632Sopenharmony_ci  size_t oldLimit = state->currentLimit;
281ffe3c632Sopenharmony_ci  if (byteLimit > oldLimit) {
282ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil);
283ffe3c632Sopenharmony_ci  }
284ffe3c632Sopenharmony_ci  state->currentLimit = byteLimit;
285ffe3c632Sopenharmony_ci  return oldLimit;
286ffe3c632Sopenharmony_ci}
287ffe3c632Sopenharmony_ci
288ffe3c632Sopenharmony_civoid GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
289ffe3c632Sopenharmony_ci                                 size_t oldLimit) {
290ffe3c632Sopenharmony_ci  state->currentLimit = oldLimit;
291ffe3c632Sopenharmony_ci}
292ffe3c632Sopenharmony_ci
293ffe3c632Sopenharmony_cisize_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state) {
294ffe3c632Sopenharmony_ci  return state->currentLimit - state->bufferPos;
295ffe3c632Sopenharmony_ci}
296ffe3c632Sopenharmony_ci
297ffe3c632Sopenharmony_ciBOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) {
298ffe3c632Sopenharmony_ci  return (state->bufferPos == state->bufferSize) ||
299ffe3c632Sopenharmony_ci         (state->bufferPos == state->currentLimit);
300ffe3c632Sopenharmony_ci}
301ffe3c632Sopenharmony_ci
302ffe3c632Sopenharmony_civoid GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
303ffe3c632Sopenharmony_ci                                        int32_t value) {
304ffe3c632Sopenharmony_ci  if (state->lastTag != value) {
305ffe3c632Sopenharmony_ci    RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read");
306ffe3c632Sopenharmony_ci  }
307ffe3c632Sopenharmony_ci}
308ffe3c632Sopenharmony_ci
309ffe3c632Sopenharmony_ci@implementation GPBCodedInputStream
310ffe3c632Sopenharmony_ci
311ffe3c632Sopenharmony_ci+ (instancetype)streamWithData:(NSData *)data {
312ffe3c632Sopenharmony_ci  return [[[self alloc] initWithData:data] autorelease];
313ffe3c632Sopenharmony_ci}
314ffe3c632Sopenharmony_ci
315ffe3c632Sopenharmony_ci- (instancetype)initWithData:(NSData *)data {
316ffe3c632Sopenharmony_ci  if ((self = [super init])) {
317ffe3c632Sopenharmony_ci#ifdef DEBUG
318ffe3c632Sopenharmony_ci    NSCAssert([self class] == [GPBCodedInputStream class],
319ffe3c632Sopenharmony_ci              @"Subclassing of GPBCodedInputStream is not allowed.");
320ffe3c632Sopenharmony_ci#endif
321ffe3c632Sopenharmony_ci    buffer_ = [data retain];
322ffe3c632Sopenharmony_ci    state_.bytes = (const uint8_t *)[data bytes];
323ffe3c632Sopenharmony_ci    state_.bufferSize = [data length];
324ffe3c632Sopenharmony_ci    state_.currentLimit = state_.bufferSize;
325ffe3c632Sopenharmony_ci  }
326ffe3c632Sopenharmony_ci  return self;
327ffe3c632Sopenharmony_ci}
328ffe3c632Sopenharmony_ci
329ffe3c632Sopenharmony_ci- (void)dealloc {
330ffe3c632Sopenharmony_ci  [buffer_ release];
331ffe3c632Sopenharmony_ci  [super dealloc];
332ffe3c632Sopenharmony_ci}
333ffe3c632Sopenharmony_ci
334ffe3c632Sopenharmony_ci// Direct access is use for speed, to avoid even internally declaring things
335ffe3c632Sopenharmony_ci// read/write, etc. The warning is enabled in the project to ensure code calling
336ffe3c632Sopenharmony_ci// protos can turn on -Wdirect-ivar-access without issues.
337ffe3c632Sopenharmony_ci#pragma clang diagnostic push
338ffe3c632Sopenharmony_ci#pragma clang diagnostic ignored "-Wdirect-ivar-access"
339ffe3c632Sopenharmony_ci
340ffe3c632Sopenharmony_ci- (int32_t)readTag {
341ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadTag(&state_);
342ffe3c632Sopenharmony_ci}
343ffe3c632Sopenharmony_ci
344ffe3c632Sopenharmony_ci- (void)checkLastTagWas:(int32_t)value {
345ffe3c632Sopenharmony_ci  GPBCodedInputStreamCheckLastTagWas(&state_, value);
346ffe3c632Sopenharmony_ci}
347ffe3c632Sopenharmony_ci
348ffe3c632Sopenharmony_ci- (BOOL)skipField:(int32_t)tag {
349ffe3c632Sopenharmony_ci  NSAssert(GPBWireFormatIsValidTag(tag), @"Invalid tag");
350ffe3c632Sopenharmony_ci  switch (GPBWireFormatGetTagWireType(tag)) {
351ffe3c632Sopenharmony_ci    case GPBWireFormatVarint:
352ffe3c632Sopenharmony_ci      GPBCodedInputStreamReadInt32(&state_);
353ffe3c632Sopenharmony_ci      return YES;
354ffe3c632Sopenharmony_ci    case GPBWireFormatFixed64:
355ffe3c632Sopenharmony_ci      SkipRawData(&state_, sizeof(int64_t));
356ffe3c632Sopenharmony_ci      return YES;
357ffe3c632Sopenharmony_ci    case GPBWireFormatLengthDelimited:
358ffe3c632Sopenharmony_ci      SkipRawData(&state_, ReadRawVarint32(&state_));
359ffe3c632Sopenharmony_ci      return YES;
360ffe3c632Sopenharmony_ci    case GPBWireFormatStartGroup:
361ffe3c632Sopenharmony_ci      [self skipMessage];
362ffe3c632Sopenharmony_ci      GPBCodedInputStreamCheckLastTagWas(
363ffe3c632Sopenharmony_ci          &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
364ffe3c632Sopenharmony_ci                                        GPBWireFormatEndGroup));
365ffe3c632Sopenharmony_ci      return YES;
366ffe3c632Sopenharmony_ci    case GPBWireFormatEndGroup:
367ffe3c632Sopenharmony_ci      return NO;
368ffe3c632Sopenharmony_ci    case GPBWireFormatFixed32:
369ffe3c632Sopenharmony_ci      SkipRawData(&state_, sizeof(int32_t));
370ffe3c632Sopenharmony_ci      return YES;
371ffe3c632Sopenharmony_ci  }
372ffe3c632Sopenharmony_ci}
373ffe3c632Sopenharmony_ci
374ffe3c632Sopenharmony_ci- (void)skipMessage {
375ffe3c632Sopenharmony_ci  while (YES) {
376ffe3c632Sopenharmony_ci    int32_t tag = GPBCodedInputStreamReadTag(&state_);
377ffe3c632Sopenharmony_ci    if (tag == 0 || ![self skipField:tag]) {
378ffe3c632Sopenharmony_ci      return;
379ffe3c632Sopenharmony_ci    }
380ffe3c632Sopenharmony_ci  }
381ffe3c632Sopenharmony_ci}
382ffe3c632Sopenharmony_ci
383ffe3c632Sopenharmony_ci- (BOOL)isAtEnd {
384ffe3c632Sopenharmony_ci  return GPBCodedInputStreamIsAtEnd(&state_);
385ffe3c632Sopenharmony_ci}
386ffe3c632Sopenharmony_ci
387ffe3c632Sopenharmony_ci- (size_t)position {
388ffe3c632Sopenharmony_ci  return state_.bufferPos;
389ffe3c632Sopenharmony_ci}
390ffe3c632Sopenharmony_ci
391ffe3c632Sopenharmony_ci- (size_t)pushLimit:(size_t)byteLimit {
392ffe3c632Sopenharmony_ci  return GPBCodedInputStreamPushLimit(&state_, byteLimit);
393ffe3c632Sopenharmony_ci}
394ffe3c632Sopenharmony_ci
395ffe3c632Sopenharmony_ci- (void)popLimit:(size_t)oldLimit {
396ffe3c632Sopenharmony_ci  GPBCodedInputStreamPopLimit(&state_, oldLimit);
397ffe3c632Sopenharmony_ci}
398ffe3c632Sopenharmony_ci
399ffe3c632Sopenharmony_ci- (double)readDouble {
400ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadDouble(&state_);
401ffe3c632Sopenharmony_ci}
402ffe3c632Sopenharmony_ci
403ffe3c632Sopenharmony_ci- (float)readFloat {
404ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadFloat(&state_);
405ffe3c632Sopenharmony_ci}
406ffe3c632Sopenharmony_ci
407ffe3c632Sopenharmony_ci- (uint64_t)readUInt64 {
408ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadUInt64(&state_);
409ffe3c632Sopenharmony_ci}
410ffe3c632Sopenharmony_ci
411ffe3c632Sopenharmony_ci- (int64_t)readInt64 {
412ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadInt64(&state_);
413ffe3c632Sopenharmony_ci}
414ffe3c632Sopenharmony_ci
415ffe3c632Sopenharmony_ci- (int32_t)readInt32 {
416ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadInt32(&state_);
417ffe3c632Sopenharmony_ci}
418ffe3c632Sopenharmony_ci
419ffe3c632Sopenharmony_ci- (uint64_t)readFixed64 {
420ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadFixed64(&state_);
421ffe3c632Sopenharmony_ci}
422ffe3c632Sopenharmony_ci
423ffe3c632Sopenharmony_ci- (uint32_t)readFixed32 {
424ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadFixed32(&state_);
425ffe3c632Sopenharmony_ci}
426ffe3c632Sopenharmony_ci
427ffe3c632Sopenharmony_ci- (BOOL)readBool {
428ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadBool(&state_);
429ffe3c632Sopenharmony_ci}
430ffe3c632Sopenharmony_ci
431ffe3c632Sopenharmony_ci- (NSString *)readString {
432ffe3c632Sopenharmony_ci  return [GPBCodedInputStreamReadRetainedString(&state_) autorelease];
433ffe3c632Sopenharmony_ci}
434ffe3c632Sopenharmony_ci
435ffe3c632Sopenharmony_ci- (void)readGroup:(int32_t)fieldNumber
436ffe3c632Sopenharmony_ci              message:(GPBMessage *)message
437ffe3c632Sopenharmony_ci    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
438ffe3c632Sopenharmony_ci  CheckRecursionLimit(&state_);
439ffe3c632Sopenharmony_ci  ++state_.recursionDepth;
440ffe3c632Sopenharmony_ci  [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
441ffe3c632Sopenharmony_ci  GPBCodedInputStreamCheckLastTagWas(
442ffe3c632Sopenharmony_ci      &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
443ffe3c632Sopenharmony_ci  --state_.recursionDepth;
444ffe3c632Sopenharmony_ci}
445ffe3c632Sopenharmony_ci
446ffe3c632Sopenharmony_ci- (void)readUnknownGroup:(int32_t)fieldNumber
447ffe3c632Sopenharmony_ci                 message:(GPBUnknownFieldSet *)message {
448ffe3c632Sopenharmony_ci  CheckRecursionLimit(&state_);
449ffe3c632Sopenharmony_ci  ++state_.recursionDepth;
450ffe3c632Sopenharmony_ci  [message mergeFromCodedInputStream:self];
451ffe3c632Sopenharmony_ci  GPBCodedInputStreamCheckLastTagWas(
452ffe3c632Sopenharmony_ci      &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
453ffe3c632Sopenharmony_ci  --state_.recursionDepth;
454ffe3c632Sopenharmony_ci}
455ffe3c632Sopenharmony_ci
456ffe3c632Sopenharmony_ci- (void)readMessage:(GPBMessage *)message
457ffe3c632Sopenharmony_ci    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
458ffe3c632Sopenharmony_ci  CheckRecursionLimit(&state_);
459ffe3c632Sopenharmony_ci  int32_t length = ReadRawVarint32(&state_);
460ffe3c632Sopenharmony_ci  size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
461ffe3c632Sopenharmony_ci  ++state_.recursionDepth;
462ffe3c632Sopenharmony_ci  [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
463ffe3c632Sopenharmony_ci  GPBCodedInputStreamCheckLastTagWas(&state_, 0);
464ffe3c632Sopenharmony_ci  --state_.recursionDepth;
465ffe3c632Sopenharmony_ci  GPBCodedInputStreamPopLimit(&state_, oldLimit);
466ffe3c632Sopenharmony_ci}
467ffe3c632Sopenharmony_ci
468ffe3c632Sopenharmony_ci- (void)readMapEntry:(id)mapDictionary
469ffe3c632Sopenharmony_ci    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
470ffe3c632Sopenharmony_ci                field:(GPBFieldDescriptor *)field
471ffe3c632Sopenharmony_ci        parentMessage:(GPBMessage *)parentMessage {
472ffe3c632Sopenharmony_ci  CheckRecursionLimit(&state_);
473ffe3c632Sopenharmony_ci  int32_t length = ReadRawVarint32(&state_);
474ffe3c632Sopenharmony_ci  size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
475ffe3c632Sopenharmony_ci  ++state_.recursionDepth;
476ffe3c632Sopenharmony_ci  GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field,
477ffe3c632Sopenharmony_ci                         parentMessage);
478ffe3c632Sopenharmony_ci  GPBCodedInputStreamCheckLastTagWas(&state_, 0);
479ffe3c632Sopenharmony_ci  --state_.recursionDepth;
480ffe3c632Sopenharmony_ci  GPBCodedInputStreamPopLimit(&state_, oldLimit);
481ffe3c632Sopenharmony_ci}
482ffe3c632Sopenharmony_ci
483ffe3c632Sopenharmony_ci- (NSData *)readBytes {
484ffe3c632Sopenharmony_ci  return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease];
485ffe3c632Sopenharmony_ci}
486ffe3c632Sopenharmony_ci
487ffe3c632Sopenharmony_ci- (uint32_t)readUInt32 {
488ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadUInt32(&state_);
489ffe3c632Sopenharmony_ci}
490ffe3c632Sopenharmony_ci
491ffe3c632Sopenharmony_ci- (int32_t)readEnum {
492ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadEnum(&state_);
493ffe3c632Sopenharmony_ci}
494ffe3c632Sopenharmony_ci
495ffe3c632Sopenharmony_ci- (int32_t)readSFixed32 {
496ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadSFixed32(&state_);
497ffe3c632Sopenharmony_ci}
498ffe3c632Sopenharmony_ci
499ffe3c632Sopenharmony_ci- (int64_t)readSFixed64 {
500ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadSFixed64(&state_);
501ffe3c632Sopenharmony_ci}
502ffe3c632Sopenharmony_ci
503ffe3c632Sopenharmony_ci- (int32_t)readSInt32 {
504ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadSInt32(&state_);
505ffe3c632Sopenharmony_ci}
506ffe3c632Sopenharmony_ci
507ffe3c632Sopenharmony_ci- (int64_t)readSInt64 {
508ffe3c632Sopenharmony_ci  return GPBCodedInputStreamReadSInt64(&state_);
509ffe3c632Sopenharmony_ci}
510ffe3c632Sopenharmony_ci
511ffe3c632Sopenharmony_ci#pragma clang diagnostic pop
512ffe3c632Sopenharmony_ci
513ffe3c632Sopenharmony_ci@end
514