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