Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
963473b1
Commit
963473b1
authored
Feb 23, 2017
by
Thomas Van Lenten
Committed by
GitHub
Feb 23, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2753 from thomasvl/recursive_drop
Add GPBMessageDropUnknownFieldsRecursively() and tests.
parents
17174b54
d0717665
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
324 additions
and
0 deletions
+324
-0
GPBUtilities.h
objectivec/GPBUtilities.h
+5
-0
GPBUtilities.m
objectivec/GPBUtilities.m
+119
-0
GPBUtilitiesTests.m
objectivec/Tests/GPBUtilitiesTests.m
+200
-0
No files found.
objectivec/GPBUtilities.h
View file @
963473b1
...
...
@@ -392,6 +392,11 @@ void GPBSetMessageMapField(GPBMessage *self,
**/
NSData
*
GPBEmptyNSData
(
void
)
__attribute__
((
pure
));
/**
* Drops the `unknownFields` from the given message and from all sub message.
**/
void
GPBMessageDropUnknownFieldsRecursively
(
GPBMessage
*
message
);
NS_ASSUME_NONNULL_END
CF_EXTERN_C_END
...
...
objectivec/GPBUtilities.m
View file @
963473b1
...
...
@@ -58,6 +58,125 @@ NSData *GPBEmptyNSData(void) {
return
defaultNSData
;
}
void
GPBMessageDropUnknownFieldsRecursively
(
GPBMessage
*
initialMessage
)
{
if
(
!
initialMessage
)
{
return
;
}
// Use an array as a list to process to avoid recursion.
NSMutableArray
*
todo
=
[
NSMutableArray
arrayWithObject
:
initialMessage
];
while
(
todo
.
count
)
{
GPBMessage
*
msg
=
todo
.
lastObject
;
[
todo
removeLastObject
];
// Clear unknowns.
msg
.
unknownFields
=
nil
;
// Handle the message fields.
GPBDescriptor
*
descriptor
=
[[
msg
class
]
descriptor
];
for
(
GPBFieldDescriptor
*
field
in
descriptor
->
fields_
)
{
if
(
!
GPBFieldDataTypeIsMessage
(
field
))
{
continue
;
}
switch
(
field
.
fieldType
)
{
case
GPBFieldTypeSingle
:
if
(
GPBGetHasIvarField
(
msg
,
field
))
{
GPBMessage
*
fieldMessage
=
GPBGetObjectIvarWithFieldNoAutocreate
(
msg
,
field
);
[
todo
addObject
:
fieldMessage
];
}
break
;
case
GPBFieldTypeRepeated
:
{
NSArray
*
fieldMessages
=
GPBGetObjectIvarWithFieldNoAutocreate
(
msg
,
field
);
if
(
fieldMessages
.
count
)
{
[
todo
addObjectsFromArray
:
fieldMessages
];
}
break
;
}
case
GPBFieldTypeMap
:
{
id
rawFieldMap
=
GPBGetObjectIvarWithFieldNoAutocreate
(
msg
,
field
);
switch
(
field
.
mapKeyDataType
)
{
case
GPBDataTypeBool
:
[(
GPBBoolObjectDictionary
*
)
rawFieldMap
enumerateKeysAndObjectsUsingBlock
:
^
(
BOOL
key
,
id
_Nonnull
object
,
BOOL
*
_Nonnull
stop
)
{
#pragma unused(key, stop)
[
todo
addObject
:
object
];
}];
break
;
case
GPBDataTypeFixed32
:
case
GPBDataTypeUInt32
:
[(
GPBUInt32ObjectDictionary
*
)
rawFieldMap
enumerateKeysAndObjectsUsingBlock
:
^
(
uint32_t
key
,
id
_Nonnull
object
,
BOOL
*
_Nonnull
stop
)
{
#pragma unused(key, stop)
[
todo
addObject
:
object
];
}];
break
;
case
GPBDataTypeInt32
:
case
GPBDataTypeSFixed32
:
case
GPBDataTypeSInt32
:
[(
GPBInt32ObjectDictionary
*
)
rawFieldMap
enumerateKeysAndObjectsUsingBlock
:
^
(
int32_t
key
,
id
_Nonnull
object
,
BOOL
*
_Nonnull
stop
)
{
#pragma unused(key, stop)
[
todo
addObject
:
object
];
}];
break
;
case
GPBDataTypeFixed64
:
case
GPBDataTypeUInt64
:
[(
GPBUInt64ObjectDictionary
*
)
rawFieldMap
enumerateKeysAndObjectsUsingBlock
:
^
(
uint64_t
key
,
id
_Nonnull
object
,
BOOL
*
_Nonnull
stop
)
{
#pragma unused(key, stop)
[
todo
addObject
:
object
];
}];
break
;
case
GPBDataTypeInt64
:
case
GPBDataTypeSFixed64
:
case
GPBDataTypeSInt64
:
[(
GPBInt64ObjectDictionary
*
)
rawFieldMap
enumerateKeysAndObjectsUsingBlock
:
^
(
int64_t
key
,
id
_Nonnull
object
,
BOOL
*
_Nonnull
stop
)
{
#pragma unused(key, stop)
[
todo
addObject
:
object
];
}];
break
;
case
GPBDataTypeString
:
[(
NSDictionary
*
)
rawFieldMap
enumerateKeysAndObjectsUsingBlock
:
^
(
NSString
*
_Nonnull
key
,
GPBMessage
*
_Nonnull
obj
,
BOOL
*
_Nonnull
stop
)
{
#pragma unused(key, stop)
[
todo
addObject
:
obj
];
}];
break
;
case
GPBDataTypeFloat
:
case
GPBDataTypeDouble
:
case
GPBDataTypeEnum
:
case
GPBDataTypeBytes
:
case
GPBDataTypeGroup
:
case
GPBDataTypeMessage
:
NSCAssert
(
NO
,
@"Aren't valid key types."
);
}
break
;
}
// switch(field.mapKeyDataType)
}
// switch(field.fieldType)
}
// for(fields)
// Handle any extensions holding messages.
for
(
GPBExtensionDescriptor
*
extension
in
[
msg
extensionsCurrentlySet
])
{
if
(
!
GPBDataTypeIsMessage
(
extension
.
dataType
))
{
continue
;
}
if
(
extension
.
isRepeated
)
{
NSArray
*
extMessages
=
[
msg
getExtension
:
extension
];
[
todo
addObjectsFromArray
:
extMessages
];
}
else
{
GPBMessage
*
extMessage
=
[
msg
getExtension
:
extension
];
[
todo
addObject
:
extMessage
];
}
}
// for(extensionsCurrentlySet)
}
// while(todo.count)
}
// -- About Version Checks --
// There's actually 3 places these checks all come into play:
// 1. When the generated source is compile into .o files, the header check
...
...
objectivec/Tests/GPBUtilitiesTests.m
View file @
963473b1
...
...
@@ -39,6 +39,7 @@
#import "GPBDescriptor.h"
#import "GPBDescriptor_PackagePrivate.h"
#import "GPBMessage.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "google/protobuf/MapUnittest.pbobjc.h"
#import "google/protobuf/Unittest.pbobjc.h"
...
...
@@ -197,4 +198,203 @@
}
}
// Helper to make an unknown field set with something in it.
static
GPBUnknownFieldSet
*
UnknownFieldsSetHelper
(
int
num
)
{
GPBUnknownFieldSet
*
result
=
[[[
GPBUnknownFieldSet
alloc
]
init
]
autorelease
];
GPBUnknownField
*
field
=
[[[
GPBUnknownField
alloc
]
initWithNumber
:
num
]
autorelease
];
[
field
addVarint
:
num
];
[
result
addField
:
field
];
return
result
;
}
-
(
void
)
testDropMessageUnknownFieldsRecursively
{
TestAllExtensions
*
message
=
[
TestAllExtensions
message
];
// Give it unknownFields.
message
.
unknownFields
=
UnknownFieldsSetHelper
(
777
);
// Given it extensions that include a message with unknown fields of its own.
{
// Int
[
message
setExtension
:[
UnittestRoot
optionalInt32Extension
]
value
:
@5
];
// Group
OptionalGroup_extension
*
optionalGroup
=
[
OptionalGroup_extension
message
];
optionalGroup
.
a
=
123
;
optionalGroup
.
unknownFields
=
UnknownFieldsSetHelper
(
779
);
[
message
setExtension
:[
UnittestRoot
optionalGroupExtension
]
value
:
optionalGroup
];
// Message
TestAllTypes_NestedMessage
*
nestedMessage
=
[
TestAllTypes_NestedMessage
message
];
nestedMessage
.
bb
=
456
;
nestedMessage
.
unknownFields
=
UnknownFieldsSetHelper
(
778
);
[
message
setExtension
:[
UnittestRoot
optionalNestedMessageExtension
]
value
:
nestedMessage
];
// Repeated Group
RepeatedGroup_extension
*
repeatedGroup
=
[[
RepeatedGroup_extension
alloc
]
init
];
repeatedGroup
.
a
=
567
;
repeatedGroup
.
unknownFields
=
UnknownFieldsSetHelper
(
780
);
[
message
addExtension
:[
UnittestRoot
repeatedGroupExtension
]
value
:
repeatedGroup
];
[
repeatedGroup
release
];
// Repeated Message
nestedMessage
=
[[
TestAllTypes_NestedMessage
alloc
]
init
];
nestedMessage
.
bb
=
678
;
nestedMessage
.
unknownFields
=
UnknownFieldsSetHelper
(
781
);
[
message
addExtension
:[
UnittestRoot
repeatedNestedMessageExtension
]
value
:
nestedMessage
];
[
nestedMessage
release
];
}
// Confirm everything is there.
XCTAssertNotNil
(
message
);
XCTAssertNotNil
(
message
.
unknownFields
);
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
optionalInt32Extension
]]);
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
optionalGroupExtension
]]);
OptionalGroup_extension
*
optionalGroup
=
[
message
getExtension
:[
UnittestRoot
optionalGroupExtension
]];
XCTAssertNotNil
(
optionalGroup
);
XCTAssertEqual
(
optionalGroup
.
a
,
123
);
XCTAssertNotNil
(
optionalGroup
.
unknownFields
);
}
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
optionalNestedMessageExtension
]]);
TestAllTypes_NestedMessage
*
nestedMessage
=
[
message
getExtension
:[
UnittestRoot
optionalNestedMessageExtension
]];
XCTAssertNotNil
(
nestedMessage
);
XCTAssertEqual
(
nestedMessage
.
bb
,
456
);
XCTAssertNotNil
(
nestedMessage
.
unknownFields
);
}
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
repeatedGroupExtension
]]);
NSArray
*
repeatedGroups
=
[
message
getExtension
:[
UnittestRoot
repeatedGroupExtension
]];
XCTAssertEqual
(
repeatedGroups
.
count
,
(
NSUInteger
)
1
);
RepeatedGroup_extension
*
repeatedGroup
=
repeatedGroups
.
firstObject
;
XCTAssertNotNil
(
repeatedGroup
);
XCTAssertEqual
(
repeatedGroup
.
a
,
567
);
XCTAssertNotNil
(
repeatedGroup
.
unknownFields
);
}
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
repeatedNestedMessageExtension
]]);
NSArray
*
repeatedNestedMessages
=
[
message
getExtension
:[
UnittestRoot
repeatedNestedMessageExtension
]];
XCTAssertEqual
(
repeatedNestedMessages
.
count
,
(
NSUInteger
)
1
);
TestAllTypes_NestedMessage
*
repeatedNestedMessage
=
repeatedNestedMessages
.
firstObject
;
XCTAssertNotNil
(
repeatedNestedMessage
);
XCTAssertEqual
(
repeatedNestedMessage
.
bb
,
678
);
XCTAssertNotNil
(
repeatedNestedMessage
.
unknownFields
);
}
// Drop them.
GPBMessageDropUnknownFieldsRecursively
(
message
);
// Confirm unknowns are gone from within the messages.
XCTAssertNotNil
(
message
);
XCTAssertNil
(
message
.
unknownFields
);
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
optionalInt32Extension
]]);
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
optionalGroupExtension
]]);
OptionalGroup_extension
*
optionalGroup
=
[
message
getExtension
:[
UnittestRoot
optionalGroupExtension
]];
XCTAssertNotNil
(
optionalGroup
);
XCTAssertEqual
(
optionalGroup
.
a
,
123
);
XCTAssertNil
(
optionalGroup
.
unknownFields
);
}
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
optionalNestedMessageExtension
]]);
TestAllTypes_NestedMessage
*
nestedMessage
=
[
message
getExtension
:[
UnittestRoot
optionalNestedMessageExtension
]];
XCTAssertNotNil
(
nestedMessage
);
XCTAssertEqual
(
nestedMessage
.
bb
,
456
);
XCTAssertNil
(
nestedMessage
.
unknownFields
);
}
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
repeatedGroupExtension
]]);
NSArray
*
repeatedGroups
=
[
message
getExtension
:[
UnittestRoot
repeatedGroupExtension
]];
XCTAssertEqual
(
repeatedGroups
.
count
,
(
NSUInteger
)
1
);
RepeatedGroup_extension
*
repeatedGroup
=
repeatedGroups
.
firstObject
;
XCTAssertNotNil
(
repeatedGroup
);
XCTAssertEqual
(
repeatedGroup
.
a
,
567
);
XCTAssertNil
(
repeatedGroup
.
unknownFields
);
}
{
XCTAssertTrue
([
message
hasExtension
:[
UnittestRoot
repeatedNestedMessageExtension
]]);
NSArray
*
repeatedNestedMessages
=
[
message
getExtension
:[
UnittestRoot
repeatedNestedMessageExtension
]];
XCTAssertEqual
(
repeatedNestedMessages
.
count
,
(
NSUInteger
)
1
);
TestAllTypes_NestedMessage
*
repeatedNestedMessage
=
repeatedNestedMessages
.
firstObject
;
XCTAssertNotNil
(
repeatedNestedMessage
);
XCTAssertEqual
(
repeatedNestedMessage
.
bb
,
678
);
XCTAssertNil
(
repeatedNestedMessage
.
unknownFields
);
}
}
-
(
void
)
testDropMessageUnknownFieldsRecursively_Maps
{
TestMap
*
message
=
[
TestMap
message
];
{
ForeignMessage
*
foreignMessage
=
[
ForeignMessage
message
];
foreignMessage
.
unknownFields
=
UnknownFieldsSetHelper
(
100
);
[
message
.
mapInt32ForeignMessage
setObject
:
foreignMessage
forKey
:
100
];
foreignMessage
=
[
ForeignMessage
message
];
foreignMessage
.
unknownFields
=
UnknownFieldsSetHelper
(
101
);
[
message
.
mapStringForeignMessage
setObject
:
foreignMessage
forKey
:
@"101"
];
}
// Confirm everything is there.
XCTAssertNotNil
(
message
);
{
ForeignMessage
*
foreignMessage
=
[
message
.
mapInt32ForeignMessage
objectForKey
:
100
];
XCTAssertNotNil
(
foreignMessage
);
XCTAssertNotNil
(
foreignMessage
.
unknownFields
);
}
{
ForeignMessage
*
foreignMessage
=
[
message
.
mapStringForeignMessage
objectForKey
:
@"101"
];
XCTAssertNotNil
(
foreignMessage
);
XCTAssertNotNil
(
foreignMessage
.
unknownFields
);
}
GPBMessageDropUnknownFieldsRecursively
(
message
);
// Confirm unknowns are gone from within the messages.
XCTAssertNotNil
(
message
);
{
ForeignMessage
*
foreignMessage
=
[
message
.
mapInt32ForeignMessage
objectForKey
:
100
];
XCTAssertNotNil
(
foreignMessage
);
XCTAssertNil
(
foreignMessage
.
unknownFields
);
}
{
ForeignMessage
*
foreignMessage
=
[
message
.
mapStringForeignMessage
objectForKey
:
@"101"
];
XCTAssertNotNil
(
foreignMessage
);
XCTAssertNil
(
foreignMessage
.
unknownFields
);
}
}
@end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment