mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
6.7 KiB
Objective-C
238 lines
6.7 KiB
Objective-C
// Copyright 2008 Cyrus Najmabadi
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#import "UnknownFieldSet_Builder.h"
|
|
|
|
#import "CodedInputStream.h"
|
|
#import "Field.h"
|
|
#import "MutableField.h"
|
|
#import "UnknownFieldSet.h"
|
|
#import "WireFormat.h"
|
|
|
|
@interface PBUnknownFieldSet_Builder ()
|
|
@property (retain) NSMutableDictionary* fields;
|
|
@property int32_t lastFieldNumber;
|
|
@property (retain) PBMutableField* lastField;
|
|
@end
|
|
|
|
|
|
@implementation PBUnknownFieldSet_Builder
|
|
|
|
@synthesize fields;
|
|
@synthesize lastFieldNumber;
|
|
@synthesize lastField;
|
|
|
|
|
|
- (void) dealloc {
|
|
self.fields = nil;
|
|
self.lastFieldNumber = 0;
|
|
self.lastField = nil;
|
|
}
|
|
|
|
|
|
- (id) init {
|
|
if ((self = [super init])) {
|
|
self.fields = [NSMutableDictionary dictionary];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
+ (PBUnknownFieldSet_Builder*) newBuilder:(PBUnknownFieldSet*) unknownFields {
|
|
PBUnknownFieldSet_Builder* builder = [[PBUnknownFieldSet_Builder alloc] init];
|
|
[builder mergeUnknownFields:unknownFields];
|
|
return builder;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a field to the {@code PBUnknownFieldSet}. If a field with the same
|
|
* number already exists, it is removed.
|
|
*/
|
|
- (PBUnknownFieldSet_Builder*) addField:(PBField*) field forNumber:(int32_t) number {
|
|
if (number == 0) {
|
|
@throw [NSException exceptionWithName:@"IllegalArgument" reason:@"" userInfo:nil];
|
|
}
|
|
if (lastField != nil && lastFieldNumber == number) {
|
|
// Discard this.
|
|
self.lastField = nil;
|
|
lastFieldNumber = 0;
|
|
}
|
|
[fields setObject:field forKey:[NSNumber numberWithInt:number]];
|
|
return self;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a field builder for the given field number which includes any
|
|
* values that already exist.
|
|
*/
|
|
- (PBMutableField*) getFieldBuilder:(int32_t) number {
|
|
if (lastField != nil) {
|
|
if (number == lastFieldNumber) {
|
|
return lastField;
|
|
}
|
|
// Note: addField() will reset lastField and lastFieldNumber.
|
|
[self addField:lastField forNumber:lastFieldNumber];
|
|
}
|
|
if (number == 0) {
|
|
return nil;
|
|
} else {
|
|
PBField* existing = [fields objectForKey:[NSNumber numberWithInt:number]];
|
|
lastFieldNumber = number;
|
|
self.lastField = [PBMutableField field];
|
|
if (existing != nil) {
|
|
[lastField mergeFromField:existing];
|
|
}
|
|
return lastField;
|
|
}
|
|
}
|
|
|
|
|
|
- (PBUnknownFieldSet*) build {
|
|
[self getFieldBuilder:0]; // Force lastField to be built.
|
|
PBUnknownFieldSet* result;
|
|
if (fields.count == 0) {
|
|
result = [PBUnknownFieldSet defaultInstance];
|
|
} else {
|
|
result = [PBUnknownFieldSet setWithFields:fields];
|
|
}
|
|
self.fields = nil;
|
|
return result;
|
|
}
|
|
|
|
|
|
/** Check if the given field number is present in the set. */
|
|
- (BOOL) hasField:(int32_t) number {
|
|
if (number == 0) {
|
|
@throw [NSException exceptionWithName:@"IllegalArgument" reason:@"" userInfo:nil];
|
|
}
|
|
|
|
return number == lastFieldNumber || ([fields objectForKey:[NSNumber numberWithInt:number]] != nil);
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a field to the {@code PBUnknownFieldSet}. If a field with the same
|
|
* number already exists, the two are merged.
|
|
*/
|
|
- (PBUnknownFieldSet_Builder*) mergeField:(PBField*) field forNumber:(int32_t) number {
|
|
if (number == 0) {
|
|
@throw [NSException exceptionWithName:@"IllegalArgument" reason:@"" userInfo:nil];
|
|
}
|
|
if ([self hasField:number]) {
|
|
[[self getFieldBuilder:number] mergeFromField:field];
|
|
} else {
|
|
// Optimization: We could call getFieldBuilder(number).mergeFrom(field)
|
|
// in this case, but that would create a copy of the PBField object.
|
|
// We'd rather reuse the one passed to us, so call addField() instead.
|
|
[self addField:field forNumber:number];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- (PBUnknownFieldSet_Builder*) mergeUnknownFields:(PBUnknownFieldSet*) other {
|
|
if (other != [PBUnknownFieldSet defaultInstance]) {
|
|
for (NSNumber* number in other.fields) {
|
|
PBField* field = [other.fields objectForKey:number];
|
|
[self mergeField:field forNumber:[number intValue]];
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
- (PBUnknownFieldSet_Builder*) mergeFromData:(NSData*) data {
|
|
PBCodedInputStream* input = [PBCodedInputStream streamWithData:data];
|
|
[self mergeFromCodedInputStream:input];
|
|
[input checkLastTagWas:0];
|
|
return self;
|
|
}
|
|
|
|
|
|
- (PBUnknownFieldSet_Builder*) mergeFromInputStream:(NSInputStream*) input {
|
|
@throw [NSException exceptionWithName:@"" reason:@"" userInfo:nil];
|
|
}
|
|
|
|
|
|
- (PBUnknownFieldSet_Builder*) mergeVarintField:(int32_t) number value:(int32_t) value {
|
|
if (number == 0) {
|
|
@throw [NSException exceptionWithName:@"IllegalArgument" reason:@"Zero is not a valid field number." userInfo:nil];
|
|
}
|
|
|
|
[[self getFieldBuilder:number] addVarint:value];
|
|
return self;
|
|
}
|
|
|
|
|
|
/**
|
|
* Parse a single field from {@code input} and merge it into this set.
|
|
* @param tag The field's tag number, which was already parsed.
|
|
* @return {@code NO} if the tag is an engroup tag.
|
|
*/
|
|
- (BOOL) mergeFieldFrom:(int32_t) tag input:(PBCodedInputStream*) input {
|
|
int32_t number = PBWireFormatGetTagFieldNumber(tag);
|
|
switch (PBWireFormatGetTagWireType(tag)) {
|
|
case PBWireFormatVarint:
|
|
[[self getFieldBuilder:number] addVarint:[input readInt64]];
|
|
return YES;
|
|
case PBWireFormatFixed64:
|
|
[[self getFieldBuilder:number] addFixed64:[input readFixed64]];
|
|
return YES;
|
|
case PBWireFormatLengthDelimited:
|
|
[[self getFieldBuilder:number] addLengthDelimited:[input readData]];
|
|
return YES;
|
|
case PBWireFormatStartGroup: {
|
|
PBUnknownFieldSet_Builder* subBuilder = [PBUnknownFieldSet builder];
|
|
[input readUnknownGroup:number builder:subBuilder];
|
|
[[self getFieldBuilder:number] addGroup:[subBuilder build]];
|
|
return YES;
|
|
}
|
|
case PBWireFormatEndGroup:
|
|
return NO;
|
|
case PBWireFormatFixed32:
|
|
[[self getFieldBuilder:number] addFixed32:[input readFixed32]];
|
|
return YES;
|
|
default:
|
|
@throw [NSException exceptionWithName:@"InvalidProtocolBuffer" reason:@"" userInfo:nil];
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Parse an entire message from {@code input} and merge its fields into
|
|
* this set.
|
|
*/
|
|
- (PBUnknownFieldSet_Builder*) mergeFromCodedInputStream:(PBCodedInputStream*) input {
|
|
while (YES) {
|
|
int32_t tag = [input readTag];
|
|
if (tag == 0 || ![self mergeFieldFrom:tag input:input]) {
|
|
break;
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
- (PBUnknownFieldSet_Builder*) clear {
|
|
self.fields = [NSMutableDictionary dictionary];
|
|
self.lastFieldNumber = 0;
|
|
self.lastField = nil;
|
|
return self;
|
|
}
|
|
|
|
@end
|