@ -24,14 +24,15 @@
[ NSException raise : NSInvalidArgumentException format : @ "Not a valid field number . "] ; \
}
@ interface GPBUnknownFields ( )
- ( BOOL ) mergeFromInputStream : ( nonnull GPBCodedInputStream * ) input endTag : ( uint32_t ) endTag ;
@ end
/ / TODO : Consider using on other functions to reduce bloat when
/ / some compiler optimizations are enabled .
#define GPB_NOINLINE __attribute__ ( ( noinline ) )
@ implementation GPBUnknownFields {
@ interface GPBUnknownFields ( ) {
@ package
NSMutableArray < GPBUnknownField * > * fields_ ;
}
@ end
/ / Direct access is use for speed , to avoid even internally declaring things
/ / read / write , etc . The warning is enabled in the project to ensure code calling
@ -39,6 +40,157 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "- Wdirect - ivar - access "
GPB_NOINLINE
static size_t ComputeSerializeSize ( GPBUnknownFields * _Nonnull self ) {
size_t result = 0 ;
for ( GPBUnknownField * field in self - > fields_ ) {
uint32_t fieldNumber = field - > number_ ;
switch ( field - > type_ ) {
case GPBUnknownFieldTypeVarint :
result + = GPBComputeUInt64Size ( fieldNumber , field - > storage_ . intValue ) ;
break ;
case GPBUnknownFieldTypeFixed32 :
result + = GPBComputeFixed32Size ( fieldNumber , ( uint32_t ) field - > storage_ . intValue ) ;
break ;
case GPBUnknownFieldTypeFixed64 :
result + = GPBComputeFixed64Size ( fieldNumber , field - > storage_ . intValue ) ;
break ;
case GPBUnknownFieldTypeLengthDelimited :
result + = GPBComputeBytesSize ( fieldNumber , field - > storage_ . lengthDelimited ) ;
break ;
case GPBUnknownFieldTypeGroup :
result + =
( GPBComputeTagSize ( fieldNumber ) * 2 ) + ComputeSerializeSize ( field - > storage_ . group ) ;
break ;
case GPBUnknownFieldTypeLegacy :
#if defined ( DEBUG ) && DEBUG
NSCAssert ( NO , @ "Internal error within the library ") ;
#endif
break ;
}
}
return result ;
}
GPB_NOINLINE
static void WriteToCoddedOutputStream ( GPBUnknownFields * _Nonnull self ,
GPBCodedOutputStream * _Nonnull output ) {
for ( GPBUnknownField * field in self - > fields_ ) {
uint32_t fieldNumber = field - > number_ ;
switch ( field - > type_ ) {
case GPBUnknownFieldTypeVarint :
[ output writeUInt64 : fieldNumber value : field - > storage_ . intValue ] ;
break ;
case GPBUnknownFieldTypeFixed32 :
[ output writeFixed32 : fieldNumber value : ( uint32_t ) field - > storage_ . intValue ] ;
break ;
case GPBUnknownFieldTypeFixed64 :
[ output writeFixed64 : fieldNumber value : field - > storage_ . intValue ] ;
break ;
case GPBUnknownFieldTypeLengthDelimited :
[ output writeBytes : fieldNumber value : field - > storage_ . lengthDelimited ] ;
break ;
case GPBUnknownFieldTypeGroup :
[ output writeRawVarint32 : GPBWireFormatMakeTag ( fieldNumber , GPBWireFormatStartGroup ) ] ;
WriteToCoddedOutputStream ( field - > storage_ . group , output ) ;
[ output writeRawVarint32 : GPBWireFormatMakeTag ( fieldNumber , GPBWireFormatEndGroup ) ] ;
break ;
case GPBUnknownFieldTypeLegacy :
#if defined ( DEBUG ) && DEBUG
NSCAssert ( NO , @ "Internal error within the library ") ;
#endif
break ;
}
}
}
GPB_NOINLINE
static BOOL MergeFromInputStream ( GPBUnknownFields * self , GPBCodedInputStream * input ,
uint32_t endTag ) {
#if defined ( DEBUG ) && DEBUG
NSCAssert ( endTag == 0 || GPBWireFormatGetTagWireType ( endTag ) == GPBWireFormatEndGroup ,
@ "Internal error : Invalid end tag : %u", endTag);
#endif
GPBCodedInputStreamState * state = & input - > state_ ;
NSMutableArray < GPBUnknownField * > * fields = self - > fields_ ;
@ try {
while ( YES ) {
uint32_t tag = GPBCodedInputStreamReadTag ( state ) ;
if ( tag == endTag ) {
return YES ;
}
if ( tag == 0 ) {
/ / Reached end of input without finding the end tag .
return NO ;
}
GPBWireFormat wireType = GPBWireFormatGetTagWireType ( tag ) ;
int32_t fieldNumber = GPBWireFormatGetTagFieldNumber ( tag ) ;
switch ( wireType ) {
case GPBWireFormatVarint : {
uint64_t value = GPBCodedInputStreamReadInt64 ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
varint : value ] ;
[ fields addObject : field ] ;
[ field release ] ;
break ;
}
case GPBWireFormatFixed32 : {
uint32_t value = GPBCodedInputStreamReadFixed32 ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
fixed32 : value ] ;
[ fields addObject : field ] ;
[ field release ] ;
break ;
}
case GPBWireFormatFixed64 : {
uint64_t value = GPBCodedInputStreamReadFixed64 ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
fixed64 : value ] ;
[ fields addObject : field ] ;
[ field release ] ;
break ;
}
case GPBWireFormatLengthDelimited : {
NSData * data = GPBCodedInputStreamReadRetainedBytes ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
lengthDelimited : data ] ;
[ fields addObject : field ] ;
[ field release ] ;
[ data release ] ;
break ;
}
case GPBWireFormatStartGroup : {
GPBUnknownFields * group = [ [ GPBUnknownFields alloc ] init ] ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber group : group ] ;
[ fields addObject : field ] ;
[ field release ] ;
[ group release ] ; / / Still will be held in the field / fields .
uint32_t endGroupTag = GPBWireFormatMakeTag ( fieldNumber , GPBWireFormatEndGroup ) ;
if ( MergeFromInputStream ( group , input , endGroupTag ) ) {
GPBCodedInputStreamCheckLastTagWas ( state , endGroupTag ) ;
} else {
[ NSException
raise : NSInternalInconsistencyException
format : @ "Internal error : Unknown field data for nested group was malformed . "] ;
}
break ;
}
case GPBWireFormatEndGroup :
[ NSException raise : NSInternalInconsistencyException
format : @ "Unexpected end group tag : %u", tag];
break ;
}
}
} @ catch ( NSException * exception ) {
#if defined ( DEBUG ) && DEBUG
NSLog ( @ "%@: Internal exception while parsing unknown data, this shouldn't happen!: %@",
[ self class ] , exception ) ;
#endif
}
}
@ implementation GPBUnknownFields
- ( instancetype ) initFromMessage : ( nonnull GPBMessage * ) message {
self = [ super init ] ;
if ( self ) {
@ -50,7 +202,7 @@
GPBCodedInputStream * input =
[ [ GPBCodedInputStream alloc ] initWithData : [ legacyUnknownFields data ] ] ;
/ / Parse until the end of the data ( tag will be zero ) .
if ( ![ self mergeFromInputStream : input endTag : 0 ] ) {
if ( !MergeFromInputStream ( self , input , 0 ) ) {
[ input release ] ;
[ self release ] ;
[ NSException raise : NSInternalInconsistencyException
@ -177,29 +329,15 @@
#pragma mark - Internal Methods
- ( size_t ) serializedSize {
size_t result = 0 ;
for ( GPBUnknownField * field in self - > fields_ ) {
result + = [ field serializedSize ] ;
}
return result ;
}
- ( void ) writeToCodedOutputStream : ( GPBCodedOutputStream * ) output {
for ( GPBUnknownField * field in fields_ ) {
[ field writeToOutput : output ] ;
}
}
- ( NSData * ) serializeAsData {
if ( fields_ . count == 0 ) {
return [ NSData data ] ;
}
size_t expectedSize = [ self serializedSize ] ;
size_t expectedSize = ComputeSerializeSize ( self ) ;
NSMutableData * data = [ NSMutableData dataWithLength : expectedSize ] ;
GPBCodedOutputStream * stream = [ [ GPBCodedOutputStream alloc ] initWithData : data ] ;
@ try {
[ self writeToCodedOutputStream : stream ] ;
WriteToCoddedOutputStream ( self , stream ) ;
[ stream flush ] ;
} @ catch ( NSException * exception ) {
#if defined ( DEBUG ) && DEBUG
@ -213,88 +351,6 @@
return data ;
}
- ( BOOL ) mergeFromInputStream : ( nonnull GPBCodedInputStream * ) input endTag : ( uint32_t ) endTag {
#if defined ( DEBUG ) && DEBUG
NSAssert ( endTag == 0 || GPBWireFormatGetTagWireType ( endTag ) == GPBWireFormatEndGroup ,
@ "Internal error : Invalid end tag : %u", endTag);
#endif
GPBCodedInputStreamState * state = & input - > state_ ;
@ try {
while ( YES ) {
uint32_t tag = GPBCodedInputStreamReadTag ( state ) ;
if ( tag == endTag ) {
return YES ;
}
if ( tag == 0 ) {
/ / Reached end of input without finding the end tag .
return NO ;
}
GPBWireFormat wireType = GPBWireFormatGetTagWireType ( tag ) ;
int32_t fieldNumber = GPBWireFormatGetTagFieldNumber ( tag ) ;
switch ( wireType ) {
case GPBWireFormatVarint : {
uint64_t value = GPBCodedInputStreamReadInt64 ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
varint : value ] ;
[ fields_ addObject : field ] ;
[ field release ] ;
break ;
}
case GPBWireFormatFixed32 : {
uint32_t value = GPBCodedInputStreamReadFixed32 ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
fixed32 : value ] ;
[ fields_ addObject : field ] ;
[ field release ] ;
break ;
}
case GPBWireFormatFixed64 : {
uint64_t value = GPBCodedInputStreamReadFixed64 ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
fixed64 : value ] ;
[ fields_ addObject : field ] ;
[ field release ] ;
break ;
}
case GPBWireFormatLengthDelimited : {
NSData * data = GPBCodedInputStreamReadRetainedBytes ( state ) ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber
lengthDelimited : data ] ;
[ fields_ addObject : field ] ;
[ field release ] ;
[ data release ] ;
break ;
}
case GPBWireFormatStartGroup : {
GPBUnknownFields * group = [ [ GPBUnknownFields alloc ] init ] ;
GPBUnknownField * field = [ [ GPBUnknownField alloc ] initWithNumber : fieldNumber group : group ] ;
[ fields_ addObject : field ] ;
[ field release ] ;
[ group release ] ; / / Still will be held in the field / fields_ .
uint32_t endGroupTag = GPBWireFormatMakeTag ( fieldNumber , GPBWireFormatEndGroup ) ;
if ( [ group mergeFromInputStream : input endTag : endGroupTag ] ) {
GPBCodedInputStreamCheckLastTagWas ( state , endGroupTag ) ;
} else {
[ NSException
raise : NSInternalInconsistencyException
format : @ "Internal error : Unknown field data for nested group was malformed . "] ;
}
break ;
}
case GPBWireFormatEndGroup :
[ NSException raise : NSInternalInconsistencyException
format : @ "Unexpected end group tag : %u", tag];
break ;
}
}
} @ catch ( NSException * exception ) {
#if defined ( DEBUG ) && DEBUG
NSLog ( @ "%@: Internal exception while parsing unknown data, this shouldn't happen!: %@",
[ self class ] , exception ) ;
#endif
}
}
@ end
@ implementation GPBUnknownFields ( AccessHelpers )
@ -352,6 +408,6 @@
return nil ;
}
#pragma clang diagnostic pop
@ end
#pragma clang diagnostic pop