Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
protobuf-c
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
protobuf-c
Commits
453f39e6
Commit
453f39e6
authored
Nov 24, 2014
by
Robert Edmonds
Browse files
Options
Browse Files
Download
Plain Diff
Merge oneof support
parents
8f23163f
6090d9a9
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
829 additions
and
88 deletions
+829
-88
configure.ac
configure.ac
+1
-1
protobuf-c/protobuf-c.c
protobuf-c/protobuf-c.c
+262
-65
protobuf-c/protobuf-c.h
protobuf-c/protobuf-c.h
+4
-1
protoc-c/c_bytes_field.cc
protoc-c/c_bytes_field.cc
+2
-1
protoc-c/c_enum_field.cc
protoc-c/c_enum_field.cc
+2
-1
protoc-c/c_field.cc
protoc-c/c_field.cc
+9
-1
protoc-c/c_message.cc
protoc-c/c_message.cc
+52
-3
protoc-c/c_primitive_field.cc
protoc-c/c_primitive_field.cc
+2
-1
t/generated-code2/cxx-generate-packed-data.cc
t/generated-code2/cxx-generate-packed-data.cc
+112
-14
t/generated-code2/test-generated-code2.c
t/generated-code2/test-generated-code2.c
+352
-0
t/test-full.proto
t/test-full.proto
+31
-0
No files found.
configure.ac
View file @
453f39e6
...
...
@@ -47,7 +47,7 @@ AC_ARG_ENABLE([protoc],
AS_HELP_STRING([--disable-protoc], [Disable building protoc_c (also disables tests)]))
if test "x$enable_protoc" != "xno"; then
AC_LANG_PUSH([C++])
PKG_CHECK_MODULES([protobuf], [protobuf >= 2.
5
.0])
PKG_CHECK_MODULES([protobuf], [protobuf >= 2.
6
.0])
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$save_CPPFLAGS $protobuf_CFLAGS"
...
...
protobuf-c/protobuf-c.c
View file @
453f39e6
...
...
@@ -460,6 +460,39 @@ required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
return
0
;
}
/**
* Calculate the serialized size of a single oneof message field, including
* the space needed by the preceding tag. Returns 0 if the oneof field isn't
* selected or is not set.
*
* \param field
* Field descriptor for member.
* \param oneof_case
* A pointer to the case enum that selects the field in the oneof.
* \param member
* Field to encode.
* \return
* Number of bytes required.
*/
static
size_t
oneof_field_get_packed_size
(
const
ProtobufCFieldDescriptor
*
field
,
const
uint32_t
*
oneof_case
,
const
void
*
member
)
{
if
(
*
oneof_case
==
field
->
id
)
{
if
(
field
->
type
==
PROTOBUF_C_TYPE_MESSAGE
||
field
->
type
==
PROTOBUF_C_TYPE_STRING
)
{
const
void
*
ptr
=
*
(
const
void
*
const
*
)
member
;
if
(
ptr
==
NULL
||
ptr
==
field
->
default_value
)
return
0
;
}
}
else
{
return
0
;
}
return
required_field_get_packed_size
(
field
,
member
);
}
/**
* Calculate the serialized size of a single optional message field, including
* the space needed by the preceding tag. Returns 0 if the optional field isn't
...
...
@@ -621,7 +654,10 @@ size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
if
(
field
->
label
==
PROTOBUF_C_LABEL_REQUIRED
)
{
rv
+=
required_field_get_packed_size
(
field
,
member
);
}
else
if
(
field
->
label
==
PROTOBUF_C_LABEL_OPTIONAL
)
{
rv
+=
optional_field_get_packed_size
(
field
,
qmember
,
member
);
if
(
0
!=
(
field
->
flags
&
PROTOBUF_C_FIELD_FLAG_ONEOF
))
rv
+=
oneof_field_get_packed_size
(
field
,
qmember
,
member
);
else
rv
+=
optional_field_get_packed_size
(
field
,
qmember
,
member
);
}
else
{
rv
+=
repeated_field_get_packed_size
(
field
,
...
...
@@ -1018,6 +1054,40 @@ required_field_pack(const ProtobufCFieldDescriptor *field,
return
0
;
}
/**
* Pack a oneof field and return the number of bytes written. Only packs the
* field that is selected by the case enum.
*
* \param field
* Field descriptor.
* \param oneof_case
* A pointer to the case enum that selects the field in the oneof.
* \param member
* The field member.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static
size_t
oneof_field_pack
(
const
ProtobufCFieldDescriptor
*
field
,
const
uint32_t
*
oneof_case
,
const
void
*
member
,
uint8_t
*
out
)
{
if
(
*
oneof_case
==
field
->
id
)
{
if
(
field
->
type
==
PROTOBUF_C_TYPE_MESSAGE
||
field
->
type
==
PROTOBUF_C_TYPE_STRING
)
{
const
void
*
ptr
=
*
(
const
void
*
const
*
)
member
;
if
(
ptr
==
NULL
||
ptr
==
field
->
default_value
)
return
0
;
}
}
else
{
return
0
;
}
return
required_field_pack
(
field
,
member
,
out
);
}
/**
* Pack an optional field and return the number of bytes written.
*
...
...
@@ -1312,6 +1382,7 @@ protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
* quantifier field of the structure), but the pointer is only
* valid if the field is:
* - a repeated field, or
* - a field that is part of a oneof
* - an optional field that isn't a pointer type
* (Meaning: not a message or a string).
*/
...
...
@@ -1321,11 +1392,10 @@ protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
if
(
field
->
label
==
PROTOBUF_C_LABEL_REQUIRED
)
{
rv
+=
required_field_pack
(
field
,
member
,
out
+
rv
);
}
else
if
(
field
->
label
==
PROTOBUF_C_LABEL_OPTIONAL
)
{
/*
* Note that qmember is bogus for strings and messages,
* but it isn't used.
*/
rv
+=
optional_field_pack
(
field
,
qmember
,
member
,
out
+
rv
);
if
(
0
!=
(
field
->
flags
&
PROTOBUF_C_FIELD_FLAG_ONEOF
))
rv
+=
oneof_field_pack
(
field
,
qmember
,
member
,
out
+
rv
);
else
rv
+=
optional_field_pack
(
field
,
qmember
,
member
,
out
+
rv
);
}
else
{
rv
+=
repeated_field_pack
(
field
,
*
(
const
size_t
*
)
qmember
,
member
,
out
+
rv
);
...
...
@@ -1459,6 +1529,39 @@ required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
return
rv
;
}
/**
* Pack a oneof field to a buffer. Only packs the field that is selected by the case enum.
*
* \param field
* Field descriptor.
* \param oneof_case
* A pointer to the case enum that selects the field in the oneof.
* \param member
* The element to be packed.
* \param[out] buffer
* Virtual buffer to append data to.
* \return
* Number of bytes serialised to `buffer`.
*/
static
size_t
oneof_field_pack_to_buffer
(
const
ProtobufCFieldDescriptor
*
field
,
const
uint32_t
*
oneof_case
,
const
void
*
member
,
ProtobufCBuffer
*
buffer
)
{
if
(
*
oneof_case
==
field
->
id
)
{
if
(
field
->
type
==
PROTOBUF_C_TYPE_MESSAGE
||
field
->
type
==
PROTOBUF_C_TYPE_STRING
)
{
const
void
*
ptr
=
*
(
const
void
*
const
*
)
member
;
if
(
ptr
==
NULL
||
ptr
==
field
->
default_value
)
return
0
;
}
}
else
{
return
0
;
}
return
required_field_pack_to_buffer
(
field
,
member
,
buffer
);
}
/**
* Pack an optional field to a buffer.
*
...
...
@@ -1735,12 +1838,21 @@ protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
if
(
field
->
label
==
PROTOBUF_C_LABEL_REQUIRED
)
{
rv
+=
required_field_pack_to_buffer
(
field
,
member
,
buffer
);
}
else
if
(
field
->
label
==
PROTOBUF_C_LABEL_OPTIONAL
)
{
rv
+=
optional_field_pack_to_buffer
(
field
,
qmember
,
member
,
buffer
);
if
(
0
!=
(
field
->
flags
&
PROTOBUF_C_FIELD_FLAG_ONEOF
))
{
rv
+=
oneof_field_pack_to_buffer
(
field
,
qmember
,
member
,
buffer
);
}
else
{
rv
+=
optional_field_pack_to_buffer
(
field
,
qmember
,
member
,
buffer
);
}
}
else
{
rv
+=
repeated_field_pack_to_buffer
(
field
,
...
...
@@ -1910,7 +2022,7 @@ merge_messages(ProtobufCMessage *earlier_msg,
{
unsigned
i
;
const
ProtobufCFieldDescriptor
*
fields
=
earli
er_msg
->
descriptor
->
fields
;
latt
er_msg
->
descriptor
->
fields
;
for
(
i
=
0
;
i
<
latter_msg
->
descriptor
->
n_fields
;
i
++
)
{
if
(
fields
[
i
].
label
==
PROTOBUF_C_LABEL_REPEATED
)
{
size_t
*
n_earlier
=
...
...
@@ -1958,40 +2070,62 @@ merge_messages(ProtobufCMessage *earlier_msg,
*
n_earlier
=
0
;
*
p_earlier
=
0
;
}
}
else
if
(
fields
[
i
].
type
==
PROTOBUF_C_TYPE_MESSAGE
)
{
ProtobufCMessage
**
em
=
STRUCT_MEMBER_PTR
(
ProtobufCMessage
*
,
earlier_msg
,
fields
[
i
].
offset
);
ProtobufCMessage
**
lm
=
STRUCT_MEMBER_PTR
(
ProtobufCMessage
*
,
latter_msg
,
fields
[
i
].
offset
);
if
(
*
em
!=
NULL
)
{
if
(
*
lm
!=
NULL
)
{
if
(
!
merge_messages
(
*
em
,
*
lm
,
allocator
))
return
FALSE
;
}
else
if
(
fields
[
i
].
label
==
PROTOBUF_C_LABEL_OPTIONAL
)
{
const
ProtobufCFieldDescriptor
*
field
;
uint32_t
*
earlier_case_p
=
STRUCT_MEMBER_PTR
(
uint32_t
,
earlier_msg
,
fields
[
i
].
quantifier_offset
);
uint32_t
*
latter_case_p
=
STRUCT_MEMBER_PTR
(
uint32_t
,
latter_msg
,
fields
[
i
].
quantifier_offset
);
if
(
fields
[
i
].
flags
&
PROTOBUF_C_FIELD_FLAG_ONEOF
)
{
if
(
*
latter_case_p
==
0
)
{
/* lookup correct oneof field */
int
field_index
=
int_range_lookup
(
latter_msg
->
descriptor
->
n_field_ranges
,
latter_msg
->
descriptor
->
field_ranges
,
*
earlier_case_p
);
field
=
latter_msg
->
descriptor
->
fields
+
field_index
;
}
else
{
/* Zero copy the optional message */
assert
(
fields
[
i
].
label
==
PROTOBUF_C_LABEL_OPTIONAL
);
*
lm
=
*
em
;
*
em
=
NULL
;
/* Oneof is present in the latter message, move on */
continue
;
}
}
else
{
field
=
&
fields
[
i
];
}
}
else
if
(
fields
[
i
].
label
==
PROTOBUF_C_LABEL_OPTIONAL
)
{
size_t
el_size
=
0
;
protobuf_c_boolean
need_to_merge
=
FALSE
;
void
*
earlier_elem
=
STRUCT_MEMBER_P
(
earlier_msg
,
field
s
[
i
].
offset
);
STRUCT_MEMBER_P
(
earlier_msg
,
field
->
offset
);
void
*
latter_elem
=
STRUCT_MEMBER_P
(
latter_msg
,
fields
[
i
].
offset
);
const
void
*
def_val
=
fields
[
i
].
default_value
;
switch
(
fields
[
i
].
type
)
{
STRUCT_MEMBER_P
(
latter_msg
,
field
->
offset
);
const
void
*
def_val
=
field
->
default_value
;
switch
(
field
->
type
)
{
case
PROTOBUF_C_TYPE_MESSAGE
:
{
ProtobufCMessage
*
em
=
*
(
ProtobufCMessage
**
)
earlier_elem
;
ProtobufCMessage
*
lm
=
*
(
ProtobufCMessage
**
)
latter_elem
;
if
(
em
!=
NULL
)
{
if
(
lm
!=
NULL
)
{
if
(
!
merge_messages
(
em
,
lm
,
allocator
))
return
FALSE
;
/* Already merged */
need_to_merge
=
FALSE
;
}
else
{
/* Zero copy the message */
need_to_merge
=
TRUE
;
}
}
break
;
}
case
PROTOBUF_C_TYPE_BYTES
:
{
el_size
=
sizeof
(
ProtobufCBinaryData
);
uint8_t
*
e_data
=
((
ProtobufCBinaryData
*
)
earlier_elem
)
->
data
;
uint8_t
*
l_data
=
...
...
@@ -2009,7 +2143,6 @@ merge_messages(ProtobufCMessage *earlier_msg,
break
;
}
case
PROTOBUF_C_TYPE_STRING
:
{
el_size
=
sizeof
(
char
*
);
char
*
e_str
=
*
(
char
**
)
earlier_elem
;
char
*
l_str
=
*
(
char
**
)
latter_elem
;
const
char
*
d_str
=
def_val
;
...
...
@@ -2018,20 +2151,18 @@ merge_messages(ProtobufCMessage *earlier_msg,
break
;
}
default:
{
el_size
=
sizeof_elt_in_repeated_array
(
fields
[
i
].
type
);
need_to_merge
=
STRUCT_MEMBER
(
protobuf_c_boolean
,
earlier_msg
,
fields
[
i
].
quantifier_offset
)
&&
!
STRUCT_MEMBER
(
protobuf_c_boolean
,
latter_msg
,
fields
[
i
].
quantifier_offset
);
/* Could be has field or case enum, the logic is
* equivalent, since 0 (FALSE) means not set for
* oneof */
need_to_merge
=
(
*
earlier_case_p
!=
0
)
&&
(
*
latter_case_p
==
0
);
break
;
}
}
if
(
need_to_merge
)
{
size_t
el_size
=
sizeof_elt_in_repeated_array
(
field
->
type
);
memcpy
(
latter_elem
,
earlier_elem
,
el_size
);
/*
* Reset the element from the old message to 0
...
...
@@ -2042,16 +2173,11 @@ merge_messages(ProtobufCMessage *earlier_msg,
*/
memset
(
earlier_elem
,
0
,
el_size
);
if
(
fields
[
i
].
quantifier_offset
!=
0
)
{
/* Set the has field, if applicable */
STRUCT_MEMBER
(
protobuf_c_boolean
,
latter_msg
,
fields
[
i
].
quantifier_offset
)
=
TRUE
;
STRUCT_MEMBER
(
protobuf_c_boolean
,
earlier_msg
,
fields
[
i
].
quantifier_offset
)
=
FALSE
;
if
(
field
->
quantifier_offset
!=
0
)
{
/* Set the has field or the case enum,
* if applicable */
*
latter_case_p
=
*
earlier_case_p
;
*
earlier_case_p
=
0
;
}
}
}
...
...
@@ -2349,6 +2475,64 @@ parse_required_member(ScannedMember *scanned_member,
return
FALSE
;
}
static
protobuf_c_boolean
parse_oneof_member
(
ScannedMember
*
scanned_member
,
void
*
member
,
ProtobufCMessage
*
message
,
ProtobufCAllocator
*
allocator
)
{
uint32_t
*
oneof_case
=
STRUCT_MEMBER_PTR
(
uint32_t
,
message
,
scanned_member
->
field
->
quantifier_offset
);
/* If we have already parsed a member of this oneof, free it. */
if
(
*
oneof_case
!=
0
)
{
/* lookup field */
int
field_index
=
int_range_lookup
(
message
->
descriptor
->
n_field_ranges
,
message
->
descriptor
->
field_ranges
,
*
oneof_case
);
const
ProtobufCFieldDescriptor
*
old_field
=
message
->
descriptor
->
fields
+
field_index
;
switch
(
old_field
->
type
)
{
case
PROTOBUF_C_TYPE_STRING
:
{
char
**
pstr
=
member
;
const
char
*
def
=
old_field
->
default_value
;
if
(
*
pstr
!=
NULL
&&
*
pstr
!=
def
)
do_free
(
allocator
,
*
pstr
);
break
;
}
case
PROTOBUF_C_TYPE_BYTES
:
{
ProtobufCBinaryData
*
bd
=
member
;
const
ProtobufCBinaryData
*
def_bd
=
old_field
->
default_value
;
if
(
bd
->
data
!=
NULL
&&
(
def_bd
==
NULL
||
bd
->
data
!=
def_bd
->
data
))
{
do_free
(
allocator
,
bd
->
data
);
}
break
;
}
case
PROTOBUF_C_TYPE_MESSAGE
:
{
ProtobufCMessage
**
pmessage
=
member
;
const
ProtobufCMessage
*
def_mess
=
old_field
->
default_value
;
if
(
*
pmessage
!=
NULL
&&
*
pmessage
!=
def_mess
)
protobuf_c_message_free_unpacked
(
*
pmessage
,
allocator
);
break
;
}
default:
break
;
}
size_t
el_size
=
sizeof_elt_in_repeated_array
(
old_field
->
type
);
memset
(
member
,
0
,
el_size
);
}
if
(
!
parse_required_member
(
scanned_member
,
member
,
allocator
,
TRUE
))
return
FALSE
;
*
oneof_case
=
scanned_member
->
tag
;
return
TRUE
;
}
static
protobuf_c_boolean
parse_optional_member
(
ScannedMember
*
scanned_member
,
void
*
member
,
...
...
@@ -2562,8 +2746,13 @@ parse_member(ScannedMember *scanned_member,
return
parse_required_member
(
scanned_member
,
member
,
allocator
,
TRUE
);
case
PROTOBUF_C_LABEL_OPTIONAL
:
return
parse_optional_member
(
scanned_member
,
member
,
message
,
allocator
);
if
(
0
!=
(
field
->
flags
&
PROTOBUF_C_FIELD_FLAG_ONEOF
))
{
return
parse_oneof_member
(
scanned_member
,
member
,
message
,
allocator
);
}
else
{
return
parse_optional_member
(
scanned_member
,
member
,
message
,
allocator
);
}
case
PROTOBUF_C_LABEL_REPEATED
:
if
(
scanned_member
->
wire_type
==
PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED
&&
...
...
@@ -2748,9 +2937,9 @@ protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
goto
error_cleanup_during_scan
;
}
/*
* \todo Consider optimizing for field[1].id == tag, if field[1]
* exists!
*/
* \todo Consider optimizing for field[1].id == tag, if field[1]
* exists!
*/
if
(
last_field
==
NULL
||
last_field
->
id
!=
tag
)
{
/* lookup field */
int
field_index
=
...
...
@@ -2977,6 +3166,14 @@ protobuf_c_message_free_unpacked(ProtobufCMessage *message,
allocator
=
&
protobuf_c__allocator
;
message
->
descriptor
=
NULL
;
for
(
f
=
0
;
f
<
desc
->
n_fields
;
f
++
)
{
if
(
0
!=
(
desc
->
fields
[
f
].
flags
&
PROTOBUF_C_FIELD_FLAG_ONEOF
)
&&
desc
->
fields
[
f
].
id
!=
STRUCT_MEMBER
(
uint32_t
,
message
,
desc
->
fields
[
f
].
quantifier_offset
))
{
/* This is not the selected oneof, skip it */
continue
;
}
if
(
desc
->
fields
[
f
].
label
==
PROTOBUF_C_LABEL_REPEATED
)
{
size_t
n
=
STRUCT_MEMBER
(
size_t
,
message
,
...
...
protobuf-c/protobuf-c.h
View file @
453f39e6
...
...
@@ -239,6 +239,9 @@ typedef enum {
/** Set if the field is marked with the `deprecated` option. */
PROTOBUF_C_FIELD_FLAG_DEPRECATED
=
(
1
<<
1
),
/** Set if the field is a member of a oneof (union). */
PROTOBUF_C_FIELD_FLAG_ONEOF
=
(
1
<<
2
),
}
ProtobufCFieldFlag
;
/**
...
...
@@ -545,7 +548,7 @@ struct ProtobufCFieldDescriptor {
/**
* The offset in bytes of the message's C structure's quantifier field
* (the `has_MEMBER` field for optional members or the `n_MEMBER` field
* for repeated members.
* for repeated members
or the case enum for oneofs)
.
*/
unsigned
quantifier_offset
;
...
...
protoc-c/c_bytes_field.cc
View file @
453f39e6
...
...
@@ -101,7 +101,8 @@ void BytesFieldGenerator::GenerateStructMembers(io::Printer* printer) const
printer
->
Print
(
variables_
,
"ProtobufCBinaryData $name$$deprecated$;
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_OPTIONAL
:
printer
->
Print
(
variables_
,
"protobuf_c_boolean has_$name$$deprecated$;
\n
"
);
if
(
descriptor_
->
containing_oneof
()
==
NULL
)
printer
->
Print
(
variables_
,
"protobuf_c_boolean has_$name$$deprecated$;
\n
"
);
printer
->
Print
(
variables_
,
"ProtobufCBinaryData $name$$deprecated$;
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_REPEATED
:
...
...
protoc-c/c_enum_field.cc
View file @
453f39e6
...
...
@@ -106,7 +106,8 @@ void EnumFieldGenerator::GenerateStructMembers(io::Printer* printer) const
printer
->
Print
(
variables_
,
"$type$ $name$$deprecated$;
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_OPTIONAL
:
printer
->
Print
(
variables_
,
"protobuf_c_boolean has_$name$$deprecated$;
\n
"
);
if
(
descriptor_
->
containing_oneof
()
==
NULL
)
printer
->
Print
(
variables_
,
"protobuf_c_boolean has_$name$$deprecated$;
\n
"
);
printer
->
Print
(
variables_
,
"$type$ $name$$deprecated$;
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_REPEATED
:
...
...
protoc-c/c_field.cc
View file @
453f39e6
...
...
@@ -114,6 +114,9 @@ void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer,
variables
[
"proto_name"
]
=
descriptor_
->
name
();
variables
[
"descriptor_addr"
]
=
descriptor_addr
;
variables
[
"value"
]
=
SimpleItoa
(
descriptor_
->
number
());
const
OneofDescriptor
*
oneof
=
descriptor_
->
containing_oneof
();
if
(
oneof
!=
NULL
)
variables
[
"oneofname"
]
=
FullNameToLower
(
oneof
->
name
());
if
(
descriptor_
->
has_default_value
())
{
variables
[
"default_value"
]
=
string
(
"&"
)
...
...
@@ -133,6 +136,9 @@ void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer,
if
(
descriptor_
->
options
().
deprecated
())
variables
[
"flags"
]
+=
" | PROTOBUF_C_FIELD_FLAG_DEPRECATED"
;
if
(
oneof
!=
NULL
)
variables
[
"flags"
]
+=
" | PROTOBUF_C_FIELD_FLAG_ONEOF"
;
printer
->
Print
(
variables
,
"{
\n
"
"
\"
$proto_name$
\"
,
\n
"
...
...
@@ -144,7 +150,9 @@ void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer,
printer
->
Print
(
variables
,
" 0, /* quantifier_offset */
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_OPTIONAL
:
if
(
optional_uses_has
)
{
if
(
oneof
!=
NULL
)
{
printer
->
Print
(
variables
,
" offsetof($classname$, $oneofname$_case),
\n
"
);
}
else
if
(
optional_uses_has
)
{
printer
->
Print
(
variables
,
" offsetof($classname$, has_$name$),
\n
"
);
}
else
{
printer
->
Print
(
variables
,
" 0, /* quantifier_offset */
\n
"
);
...
...
protoc-c/c_message.cc
View file @
453f39e6
...
...
@@ -147,6 +147,25 @@ GenerateStructDefinition(io::Printer* printer) {
vars
[
"dllexport"
]
=
dllexport_decl_
+
" "
;
}
// Generate the case enums for unions
for
(
int
i
=
0
;
i
<
descriptor_
->
oneof_decl_count
();
i
++
)
{
const
OneofDescriptor
*
oneof
=
descriptor_
->
oneof_decl
(
i
);
vars
[
"oneofname"
]
=
FullNameToUpper
(
oneof
->
name
());
vars
[
"foneofname"
]
=
FullNameToC
(
oneof
->
full_name
());
printer
->
Print
(
"typedef enum {
\n
"
);
printer
->
Indent
();
printer
->
Print
(
vars
,
"$ucclassname$__$oneofname$__NOT_SET = 0,
\n
"
);
for
(
int
j
=
0
;
j
<
oneof
->
field_count
();
j
++
)
{
const
FieldDescriptor
*
field
=
oneof
->
field
(
j
);
vars
[
"fieldname"
]
=
FullNameToUpper
(
field
->
name
());
vars
[
"fieldnum"
]
=
SimpleItoa
(
field
->
number
());
printer
->
Print
(
vars
,
"$ucclassname$__$oneofname$_$fieldname$ = $fieldnum$,
\n
"
);
}
printer
->
Outdent
();
printer
->
Print
(
vars
,
"} $foneofname$Case;
\n\n
"
);
}
printer
->
Print
(
vars
,
"struct $dllexport$ _$classname$
\n
"
"{
\n
"
...
...
@@ -156,7 +175,27 @@ GenerateStructDefinition(io::Printer* printer) {
printer
->
Indent
();
for
(
int
i
=
0
;
i
<
descriptor_
->
field_count
();
i
++
)
{
const
FieldDescriptor
*
field
=
descriptor_
->
field
(
i
);
field_generators_
.
get
(
field
).
GenerateStructMembers
(
printer
);
if
(
field
->
containing_oneof
()
==
NULL
)
{
field_generators_
.
get
(
field
).
GenerateStructMembers
(
printer
);
}
}
// Generate unions from oneofs.
for
(
int
i
=
0
;
i
<
descriptor_
->
oneof_decl_count
();
i
++
)
{
const
OneofDescriptor
*
oneof
=
descriptor_
->
oneof_decl
(
i
);
vars
[
"oneofname"
]
=
FullNameToLower
(
oneof
->
name
());
vars
[
"foneofname"
]
=
FullNameToC
(
oneof
->
full_name
());
printer
->
Print
(
vars
,
"$foneofname$Case $oneofname$_case;
\n
"
);
printer
->
Print
(
"union {
\n
"
);
printer
->
Indent
();
for
(
int
j
=
0
;
j
<
oneof
->
field_count
();
j
++
)
{
const
FieldDescriptor
*
field
=
oneof
->
field
(
j
);
field_generators_
.
get
(
field
).
GenerateStructMembers
(
printer
);
}
printer
->
Outdent
();
printer
->
Print
(
vars
,
"};
\n
"
);
}
printer
->
Outdent
();
...
...
@@ -173,8 +212,18 @@ GenerateStructDefinition(io::Printer* printer) {
" { PROTOBUF_C_MESSAGE_INIT (&$lcclassname$__descriptor)
\\\n
"
);
for
(
int
i
=
0
;
i
<
descriptor_
->
field_count
();
i
++
)
{
const
FieldDescriptor
*
field
=
descriptor_
->
field
(
i
);
printer
->
Print
(
", "
);
field_generators_
.
get
(
field
).
GenerateStaticInit
(
printer
);
if
(
field
->
containing_oneof
()
==
NULL
)
{
printer
->
Print
(
", "
);
field_generators_
.
get
(
field
).
GenerateStaticInit
(
printer
);
}
}
for
(
int
i
=
0
;
i
<
descriptor_
->
oneof_decl_count
();
i
++
)
{
const
OneofDescriptor
*
oneof
=
descriptor_
->
oneof_decl
(
i
);
vars
[
"foneofname"
]
=
FullNameToUpper
(
oneof
->
full_name
());
// Initialize the case enum
printer
->
Print
(
vars
,
", $foneofname$__NOT_SET"
);
// Initialize the enum
printer
->
Print
(
", {}"
);
}
printer
->
Print
(
" }
\n\n\n
"
);
...
...
protoc-c/c_primitive_field.cc
View file @
453f39e6
...
...
@@ -113,7 +113,8 @@ void PrimitiveFieldGenerator::GenerateStructMembers(io::Printer* printer) const
printer
->
Print
(
vars
,
"$c_type$ $name$$deprecated$;
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_OPTIONAL
:
printer
->
Print
(
vars
,
"protobuf_c_boolean has_$name$$deprecated$;
\n
"
);
if
(
descriptor_
->
containing_oneof
()
==
NULL
)
printer
->
Print
(
vars
,
"protobuf_c_boolean has_$name$$deprecated$;
\n
"
);
printer
->
Print
(
vars
,
"$c_type$ $name$$deprecated$;
\n
"
);
break
;
case
FieldDescriptor
:
:
LABEL_REPEATED
:
...
...
t/generated-code2/cxx-generate-packed-data.cc
View file @
453f39e6
...
...
@@ -36,25 +36,35 @@ using namespace foo;
#define N_ELEMENTS(arr) (sizeof(arr)/sizeof((arr)[0]))
static
void
dump_message_bytes
(
google
::
protobuf
::
Message
*
message
,
const
char
*
label
)
{
std
::
string
rv
;
unsigned
char
*
bytes
;
unsigned
len
;
if
(
!
message
->
SerializeToString
(
&
rv
))
assert
(
0
);
bytes
=
(
unsigned
char
*
)
rv
.
data
();
len
=
rv
.
size
();
printf
(
"static const uint8_t %s[%u] = { "
,
label
,
len
);
for
(
unsigned
i
=
0
;
i
<
len
;
i
++
)
{
if
(
i
)
dump_messages_bytes
(
size_t
n_msgs
,
google
::
protobuf
::
Message
**
messages
,
const
char
*
label
)
{
printf
(
"static const uint8_t %s[] = { "
,
label
);
for
(
unsigned
m
=
0
;
m
<
n_msgs
;
m
++
)
{
std
::
string
rv
;
google
::
protobuf
::
Message
*
message
=
messages
[
m
];
if
(
m
)
printf
(
", "
);
printf
(
"0x%02x"
,
bytes
[
i
]);
if
(
!
message
->
SerializeToString
(
&
rv
))
assert
(
0
);
unsigned
char
*
bytes
=
(
unsigned
char
*
)
rv
.
data
();
for
(
unsigned
i
=
0
;
i
<
rv
.
size
();
i
++
)
{
if
(
i
)
printf
(
", "
);
printf
(
"0x%02x"
,
bytes
[
i
]);
}
}
printf
(
" };
\n
"
);
}
static
void
dump_message_bytes
(
google
::
protobuf
::
Message
*
message
,
const
char
*
label
)
{
dump_messages_bytes
(
1
,
&
message
,
label
);
}
static
void
dump_test_enum_small
(
void
)
{
...
...
@@ -564,6 +574,33 @@ static void dump_test_optional_message (void)
opt
.
mutable_test_message
()
->
set_test
(
42
);
dump_message_bytes
(
&
opt
,
"test_optional_submess_42"
);
}
static
void
dump_test_oneof_merge
(
void
)
{
#define SWAP(a, b) temp = a, a = b, b = temp
google
::
protobuf
::
Message
*
temp
;
TestMessOptional
opt
[
6
];
google
::
protobuf
::
Message
*
msgs
[
6
]
=
{
&
opt
[
0
],
&
opt
[
1
],
&
opt
[
2
],
&
opt
[
3
],
&
opt
[
4
],
&
opt
[
5
]
};
opt
[
0
].
set_test_bytes
(
"hello"
);
opt
[
1
].
mutable_test_message
()
->
set_test
(
42
);
opt
[
2
].
set_test_string
(
""
);
opt
[
3
].
set_test_int32
(
666
);
opt
[
4
].
set_test_float
(
333
);
opt
[
5
].
set_test_double
(
444455555
);
dump_messages_bytes
(
6
,
msgs
,
"test_oneof_merge_double"
);
SWAP
(
msgs
[
5
],
msgs
[
4
]);
dump_messages_bytes
(
6
,
msgs
,
"test_oneof_merge_float"
);
SWAP
(
msgs
[
5
],
msgs
[
3
]);
dump_messages_bytes
(
6
,
msgs
,
"test_oneof_merge_int32"
);
SWAP
(
msgs
[
5
],
msgs
[
2
]);
dump_messages_bytes
(
6
,
msgs
,
"test_oneof_merge_string"
);
SWAP
(
msgs
[
5
],
msgs
[
1
]);
dump_messages_bytes
(
6
,
msgs
,
"test_oneof_merge_submess"
);
SWAP
(
msgs
[
5
],
msgs
[
0
]);
dump_messages_bytes
(
6
,
msgs
,
"test_oneof_merge_bytes"
);
#undef SWAP
}
#define DUMP_STATIC_ARRAY_GENERIC(member, static_array, output_array_name) \
do{ \
...
...
@@ -978,6 +1015,65 @@ static void dump_test_unknown_fields (void)
dump_message_bytes
(
&
mess
,
"test_unknown_fields_1"
);
}
static
void
dump_test_submess_merge
(
void
)
{
TestMessSubMess
mess1
,
mess2
,
merged1
,
merged2
;
/* Repeated merge */
mess1
.
mutable_rep_mess
()
->
add_test_int32
(
1
);
mess1
.
mutable_rep_mess
()
->
add_test_int32
(
2
);
mess2
.
mutable_rep_mess
()
->
add_test_int32
(
3
);
mess2
.
mutable_rep_mess
()
->
add_test_int32
(
4
);
mess1
.
mutable_rep_mess
()
->
add_test_string
(
"hello "
);
mess2
.
mutable_rep_mess
()
->
add_test_string
(
"world"
);
mess1
.
mutable_rep_mess
()
->
add_test_bytes
(
"
\001\002\003
"
);
mess2
.
mutable_rep_mess
()
->
add_test_bytes
(
"
\004\005\006
"
);
mess1
.
mutable_rep_mess
()
->
add_test_message
()
->
set_test
(
111
);
mess2
.
mutable_rep_mess
()
->
add_test_message
()
->
set_test
(
222
);
/* Optional merge */
mess1
.
mutable_opt_mess
()
->
set_test_sint32
(
-
1
);
mess2
.
mutable_opt_mess
()
->
set_test_sint32
(
-
2
);
mess1
.
mutable_opt_mess
()
->
set_test_float
(
333
);
mess2
.
mutable_opt_mess
()
->
set_test_double
(
444
);
mess1
.
mutable_opt_mess
()
->
set_test_bytes
(
"
\001\002\003
"
);
mess1
.
mutable_opt_mess
()
->
mutable_test_message
()
->
set_test
(
111
);
mess2
.
mutable_opt_mess
()
->
set_test_string
(
"hello"
);
/* Oneof merge */
mess1
.
mutable_oneof_mess
()
->
set_opt_int
(
1
);
mess2
.
mutable_oneof_mess
()
->
mutable_test_message
()
->
set_test
(
111
);
/* Required merge */
mess1
.
mutable_req_mess
()
->
set_test
(
1
);
mess2
.
mutable_req_mess
()
->
set_test
(
2
);
/* Default value merge */
mess1
.
mutable_def_mess
()
->
set_v_int32
(
111
);
mess1
.
mutable_def_mess
()
->
set_v_string
(
"hello"
);
mess2
.
mutable_def_mess
()
->
set_v_bytes
(
"
\001\002\003
"
);
mess2
.
mutable_def_mess
()
->
set_v_double
(
444
);
/* Merge both ways and encode the merged and unmerged messages */
merged1
.
CopyFrom
(
mess1
);
merged1
.
MergeFrom
(
mess2
);
merged2
.
CopyFrom
(
mess2
);
merged2
.
MergeFrom
(
mess1
);
google
::
protobuf
::
Message
*
msgs
[]
=
{
&
mess1
,
&
mess2
};
dump_messages_bytes
(
2
,
msgs
,
"test_submess_unmerged1"
);
msgs
[
0
]
=
&
mess2
;
msgs
[
1
]
=
&
mess1
;
dump_messages_bytes
(
2
,
msgs
,
"test_submess_unmerged2"
);
dump_message_bytes
(
&
merged1
,
"test_submess_merged1"
);
dump_message_bytes
(
&
merged2
,
"test_submess_merged2"
);
}
int
main
()
{
dump_test_enum_small
();
...
...
@@ -1019,6 +1115,7 @@ int main()
dump_test_optional_string
();
dump_test_optional_bytes
();
dump_test_optional_message
();
dump_test_oneof_merge
();
dump_test_repeated_int32
();
dump_test_repeated_sint32
();
dump_test_repeated_uint32
();
...
...
@@ -1053,5 +1150,6 @@ int main()
dump_test_packed_repeated_enum_small
();
dump_test_packed_repeated_enum
();
dump_test_unknown_fields
();
dump_test_submess_merge
();
return
0
;
}
t/generated-code2/test-generated-code2.c
View file @
453f39e6
...
...
@@ -82,9 +82,14 @@ test_compare_pack_methods (ProtobufCMessage *message,
return
rv
;
}
#define GENERIC_ASSIGN(dst,src) ((dst) = (src))
#define NUMERIC_EQUALS(a,b) ((a) == (b))
#define STRING_EQUALS(a,b) (strcmp((a),(b))==0)
#define CHECK_NONE(a)
#define CHECK_NOT_NULL(a) assert( (a) != NULL )
static
protobuf_c_boolean
binary_data_equals
(
ProtobufCBinaryData
a
,
ProtobufCBinaryData
b
)
{
...
...
@@ -681,6 +686,297 @@ static void test_optional_SubMess (void)
DO_TEST
(
&
submess
,
test_optional_submess_42
);
#undef DO_TEST
}
/* === Oneof type fields === */
static
void
test_empty_oneof
(
void
)
{
Foo__TestMessOneof
mess
=
FOO__TEST_MESS_ONEOF__INIT
;
size_t
len
;
uint8_t
*
data
;
Foo__TestMessOneof
*
mess2
=
test_compare_pack_methods
(
&
mess
.
base
,
&
len
,
&
data
);
assert
(
len
==
0
);
free
(
data
);
foo__test_mess_oneof__free_unpacked
(
mess2
,
NULL
);
}
#define DO_TEST_GENERIC_ONEOF(type, init, free_unpacked, case_member, case_enum, member, value, example_packed_data, assign, equal_func, result_check) \
do{ \
type opt = init; \
type *mess; \
size_t len; uint8_t *data; \
opt.case_member = case_enum; \
assign(opt.member, value); \
mess = test_compare_pack_methods (&opt.base, &len, &data); \
TEST_VERSUS_STATIC_ARRAY (len, data, example_packed_data); \
assert (mess->case_member == case_enum); \
result_check(mess->member); \
assert (equal_func (mess->member, value)); \
free_unpacked (mess, NULL); \
free (data); \
}while(0)
#define DO_TEST_ONEOF(member, MEMBER, value, example_packed_data, assign, equal_func) \
DO_TEST_GENERIC_ONEOF(Foo__TestMessOneof, \
FOO__TEST_MESS_ONEOF__INIT, \
foo__test_mess_oneof__free_unpacked, \
test_oneof_case, \
FOO__TEST_MESS_ONEOF__TEST_ONEOF_##MEMBER, \
member, \
value, example_packed_data, assign, equal_func, CHECK_NONE)
#define DO_TEST_ONEOF_REF_VAL(member, MEMBER, value, example_packed_data, assign, equal_func) \
DO_TEST_GENERIC_ONEOF(Foo__TestMessOneof, \
FOO__TEST_MESS_ONEOF__INIT, \
foo__test_mess_oneof__free_unpacked, \
test_oneof_case, \
FOO__TEST_MESS_ONEOF__TEST_ONEOF_##MEMBER, \
member, \
value, example_packed_data, assign, equal_func, CHECK_NOT_NULL)
static
void
test_oneof_int32
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_int32, TEST_INT32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
INT32_MIN
,
test_optional_int32_min
);
DO_TEST
(
-
1
,
test_optional_int32_m1
);
DO_TEST
(
0
,
test_optional_int32_0
);
DO_TEST
(
666
,
test_optional_int32_666
);
DO_TEST
(
INT32_MAX
,
test_optional_int32_max
);
#undef DO_TEST
}
static
void
test_oneof_sint32
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_sint32, TEST_SINT32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
INT32_MIN
,
test_optional_sint32_min
);
DO_TEST
(
-
1
,
test_optional_sint32_m1
);
DO_TEST
(
0
,
test_optional_sint32_0
);
DO_TEST
(
666
,
test_optional_sint32_666
);
DO_TEST
(
INT32_MAX
,
test_optional_sint32_max
);
#undef DO_TEST
}
static
void
test_oneof_sfixed32
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_sfixed32, TEST_SFIXED32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
INT32_MIN
,
test_optional_sfixed32_min
);
DO_TEST
(
-
1
,
test_optional_sfixed32_m1
);
DO_TEST
(
0
,
test_optional_sfixed32_0
);
DO_TEST
(
666
,
test_optional_sfixed32_666
);
DO_TEST
(
INT32_MAX
,
test_optional_sfixed32_max
);
#undef DO_TEST
}
static
void
test_oneof_int64
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_int64, TEST_INT64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
INT64_MIN
,
test_optional_int64_min
);
DO_TEST
(
-
1111111111LL
,
test_optional_int64_m1111111111LL
);
DO_TEST
(
0
,
test_optional_int64_0
);
DO_TEST
(
QUINTILLION
,
test_optional_int64_quintillion
);
DO_TEST
(
INT64_MAX
,
test_optional_int64_max
);
#undef DO_TEST
}
static
void
test_oneof_sint64
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_sint64, TEST_SINT64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
INT64_MIN
,
test_optional_sint64_min
);
DO_TEST
(
-
1111111111LL
,
test_optional_sint64_m1111111111LL
);
DO_TEST
(
0
,
test_optional_sint64_0
);
DO_TEST
(
QUINTILLION
,
test_optional_sint64_quintillion
);
DO_TEST
(
INT64_MAX
,
test_optional_sint64_max
);
#undef DO_TEST
}
static
void
test_oneof_sfixed64
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_sfixed64, TEST_SFIXED64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
INT64_MIN
,
test_optional_sfixed64_min
);
DO_TEST
(
-
1111111111LL
,
test_optional_sfixed64_m1111111111LL
);
DO_TEST
(
0
,
test_optional_sfixed64_0
);
DO_TEST
(
QUINTILLION
,
test_optional_sfixed64_quintillion
);
DO_TEST
(
INT64_MAX
,
test_optional_sfixed64_max
);
#undef DO_TEST
}
static
void
test_oneof_uint32
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_uint32, TEST_UINT32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
0
,
test_optional_uint32_0
);
DO_TEST
(
669
,
test_optional_uint32_669
);
DO_TEST
(
UINT32_MAX
,
test_optional_uint32_max
);
#undef DO_TEST
}
static
void
test_oneof_fixed32
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_fixed32, TEST_FIXED32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
0
,
test_optional_fixed32_0
);
DO_TEST
(
669
,
test_optional_fixed32_669
);
DO_TEST
(
UINT32_MAX
,
test_optional_fixed32_max
);
#undef DO_TEST
}
static
void
test_oneof_uint64
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_uint64, TEST_UINT64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
0
,
test_optional_uint64_0
);
DO_TEST
(
669669669669669ULL
,
test_optional_uint64_669669669669669
);
DO_TEST
(
UINT64_MAX
,
test_optional_uint64_max
);
#undef DO_TEST
}
static
void
test_oneof_fixed64
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_fixed64, TEST_FIXED64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
0
,
test_optional_fixed64_0
);
DO_TEST
(
669669669669669ULL
,
test_optional_fixed64_669669669669669
);
DO_TEST
(
UINT64_MAX
,
test_optional_fixed64_max
);
#undef DO_TEST
}
static
void
test_oneof_float
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_float, TEST_FLOAT, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
-
100
,
test_optional_float_m100
);
DO_TEST
(
0
,
test_optional_float_0
);
DO_TEST
(
141243
,
test_optional_float_141243
);
#undef DO_TEST
}
static
void
test_oneof_double
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_double, TEST_DOUBLE, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
-
100
,
test_optional_double_m100
);
DO_TEST
(
0
,
test_optional_double_0
);
DO_TEST
(
141243
,
test_optional_double_141243
);
#undef DO_TEST
}
static
void
test_oneof_bool
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_boolean, TEST_BOOLEAN, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
0
,
test_optional_bool_0
);
DO_TEST
(
1
,
test_optional_bool_1
);
#undef DO_TEST
}
static
void
test_oneof_TestEnumSmall
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_enum_small, TEST_ENUM_SMALL, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
0
,
test_optional_enum_small_0
);
DO_TEST
(
1
,
test_optional_enum_small_1
);
#undef DO_TEST
}
static
void
test_oneof_TestEnum
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF(test_enum, TEST_ENUM, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS)
DO_TEST
(
FOO__TEST_ENUM__VALUE0
,
test_optional_enum_0
);
DO_TEST
(
FOO__TEST_ENUM__VALUE1
,
test_optional_enum_1
);
DO_TEST
(
FOO__TEST_ENUM__VALUE127
,
test_optional_enum_127
);
DO_TEST
(
FOO__TEST_ENUM__VALUE128
,
test_optional_enum_128
);
DO_TEST
(
FOO__TEST_ENUM__VALUE16383
,
test_optional_enum_16383
);
DO_TEST
(
FOO__TEST_ENUM__VALUE16384
,
test_optional_enum_16384
);
DO_TEST
(
FOO__TEST_ENUM__VALUE2097151
,
test_optional_enum_2097151
);
DO_TEST
(
FOO__TEST_ENUM__VALUE2097152
,
test_optional_enum_2097152
);
DO_TEST
(
FOO__TEST_ENUM__VALUE268435455
,
test_optional_enum_268435455
);
DO_TEST
(
FOO__TEST_ENUM__VALUE268435456
,
test_optional_enum_268435456
);
#undef DO_TEST
}
static
void
test_oneof_string
(
void
)
{
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF_REF_VAL (test_string, TEST_STRING, value, example_packed_data, GENERIC_ASSIGN, STRING_EQUALS)
DO_TEST
(
""
,
test_optional_string_empty
);
DO_TEST
(
"hello"
,
test_optional_string_hello
);
#undef DO_TEST
}
static
void
test_oneof_bytes
(
void
)
{
static
ProtobufCBinaryData
bd_empty
=
{
0
,
(
uint8_t
*
)
""
};
static
ProtobufCBinaryData
bd_hello
=
{
5
,
(
uint8_t
*
)
"hello"
};
static
ProtobufCBinaryData
bd_random
=
{
5
,
(
uint8_t
*
)
"
\1\0\375\2\4
"
};
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF (test_bytes, TEST_BYTES, value, example_packed_data, GENERIC_ASSIGN, binary_data_equals)
DO_TEST
(
bd_empty
,
test_optional_bytes_empty
);
DO_TEST
(
bd_hello
,
test_optional_bytes_hello
);
DO_TEST
(
bd_random
,
test_optional_bytes_random
);
#undef DO_TEST
}
static
void
test_oneof_SubMess
(
void
)
{
Foo__SubMess
submess
=
FOO__SUB_MESS__INIT
;
#define DO_TEST(value, example_packed_data) \
DO_TEST_ONEOF_REF_VAL (test_message, TEST_MESSAGE, value, example_packed_data, GENERIC_ASSIGN, submesses_equals)
submess
.
test
=
0
;
DO_TEST
(
&
submess
,
test_optional_submess_0
);
submess
.
test
=
42
;
DO_TEST
(
&
submess
,
test_optional_submess_42
);
#undef DO_TEST
}
static
void
test_oneof_merge
(
void
)
{
Foo__TestMessOneof
*
msg
;
#define DO_TEST(value, member, MEMBER, equals_func, example_packed_data) \
msg = foo__test_mess_oneof__unpack (NULL, sizeof (example_packed_data), example_packed_data); \
assert (msg); \
assert (msg->test_oneof_case == FOO__TEST_MESS_ONEOF__TEST_ONEOF_##MEMBER); \
assert (equals_func (msg->member, value)); \
foo__test_mess_oneof__free_unpacked (msg, NULL);
DO_TEST
(
444455555
,
test_double
,
TEST_DOUBLE
,
NUMERIC_EQUALS
,
test_oneof_merge_double
);
DO_TEST
(
333
,
test_float
,
TEST_FLOAT
,
NUMERIC_EQUALS
,
test_oneof_merge_float
);
DO_TEST
(
666
,
test_int32
,
TEST_INT32
,
NUMERIC_EQUALS
,
test_oneof_merge_int32
);
DO_TEST
(
""
,
test_string
,
TEST_STRING
,
STRING_EQUALS
,
test_oneof_merge_string
);
Foo__SubMess
submess
=
FOO__SUB_MESS__INIT
;
submess
.
test
=
42
;
DO_TEST
(
&
submess
,
test_message
,
TEST_MESSAGE
,
submesses_equals
,
test_oneof_merge_submess
);
ProtobufCBinaryData
bd_hello
=
{
5
,
(
uint8_t
*
)
"hello"
};
DO_TEST
(
bd_hello
,
test_bytes
,
TEST_BYTES
,
binary_data_equals
,
test_oneof_merge_bytes
);
#undef DO_TEST
}
/* === repeated type fields === */
#define DO_TEST_REPEATED(lc_member_name, cast, \
static_array, example_packed_data, \
...
...
@@ -1514,6 +1810,40 @@ test_field_merge (void)
foo__test_mess_optional__free_unpacked
(
merged
,
NULL
);
}
static
void
test_submessage_merge
(
void
)
{
Foo__TestMessSubMess
*
merged
;
size_t
size
;
uint8_t
*
packed
;
merged
=
foo__test_mess_sub_mess__unpack
(
NULL
,
sizeof
(
test_submess_unmerged1
),
test_submess_unmerged1
);
size
=
foo__test_mess_sub_mess__get_packed_size
(
merged
);
packed
=
malloc
(
size
);
foo__test_mess_sub_mess__pack
(
merged
,
packed
);
assert
(
size
==
sizeof
(
test_submess_merged1
));
assert
(
memcmp
(
packed
,
test_submess_merged1
,
size
)
==
0
);
foo__test_mess_sub_mess__free_unpacked
(
merged
,
NULL
);
free
(
packed
);
merged
=
foo__test_mess_sub_mess__unpack
(
NULL
,
sizeof
(
test_submess_unmerged2
),
test_submess_unmerged2
);
size
=
foo__test_mess_sub_mess__get_packed_size
(
merged
);
packed
=
malloc
(
size
);
foo__test_mess_sub_mess__pack
(
merged
,
packed
);
assert
(
size
==
sizeof
(
test_submess_merged2
));
assert
(
memcmp
(
packed
,
test_submess_merged2
,
size
)
==
0
);
foo__test_mess_sub_mess__free_unpacked
(
merged
,
NULL
);
free
(
packed
);
}
static
struct
alloc_data
{
uint32_t
alloc_count
;
int32_t
allocs_left
;
...
...
@@ -1821,6 +2151,27 @@ static Test tests[] =
{
"test optional string"
,
test_optional_string
},
{
"test optional bytes"
,
test_optional_bytes
},
{
"test optional SubMess"
,
test_optional_SubMess
},
{
"test empty oneof"
,
test_empty_oneof
},
{
"test oneof int32"
,
test_oneof_int32
},
{
"test oneof sint32"
,
test_oneof_sint32
},
{
"test oneof sfixed32"
,
test_oneof_sfixed32
},
{
"test oneof int64"
,
test_oneof_int64
},
{
"test oneof sint64"
,
test_oneof_sint64
},
{
"test oneof sfixed64"
,
test_oneof_sfixed64
},
{
"test oneof uint32"
,
test_oneof_uint32
},
{
"test oneof fixed32"
,
test_oneof_fixed32
},
{
"test oneof uint64"
,
test_oneof_uint64
},
{
"test oneof fixed64"
,
test_oneof_fixed64
},
{
"test oneof float"
,
test_oneof_float
},
{
"test oneof double"
,
test_oneof_double
},
{
"test oneof bool"
,
test_oneof_bool
},
{
"test oneof TestEnumSmall"
,
test_oneof_TestEnumSmall
},
{
"test oneof TestEnum"
,
test_oneof_TestEnum
},
{
"test oneof string"
,
test_oneof_string
},
{
"test oneof bytes"
,
test_oneof_bytes
},
{
"test oneof SubMess"
,
test_oneof_SubMess
},
{
"test merged oneof unpack"
,
test_oneof_merge
},
{
"test empty repeated"
,
test_empty_repeated
},
{
"test repeated int32"
,
test_repeated_int32
},
...
...
@@ -1869,6 +2220,7 @@ static Test tests[] =
{
"test optional lowercase enum default value"
,
test_optional_lowercase_enum_default_value
},
{
"test field merge"
,
test_field_merge
},
{
"test submessage merge"
,
test_submessage_merge
},
{
"test free unpacked"
,
test_alloc_free_all
},
{
"test alloc failure"
,
test_alloc_fail
},
...
...
t/test-full.proto
View file @
453f39e6
...
...
@@ -132,6 +132,30 @@ message TestMessOptional {
optional
SubMess
test_message
=
18
;
}
message
TestMessOneof
{
oneof
test_oneof
{
int32
test_int32
=
1
;
sint32
test_sint32
=
2
;
sfixed32
test_sfixed32
=
3
;
int64
test_int64
=
4
;
sint64
test_sint64
=
5
;
sfixed64
test_sfixed64
=
6
;
uint32
test_uint32
=
7
;
fixed32
test_fixed32
=
8
;
uint64
test_uint64
=
9
;
fixed64
test_fixed64
=
10
;
float
test_float
=
11
;
double
test_double
=
12
;
bool
test_boolean
=
13
;
TestEnumSmall
test_enum_small
=
14
;
TestEnum
test_enum
=
15
;
string
test_string
=
16
;
bytes
test_bytes
=
17
;
SubMess
test_message
=
18
;
}
optional
int32
opt_int
=
19
;
}
message
TestMessRequiredInt32
{
required
int32
test
=
42
;
}
...
...
@@ -379,3 +403,10 @@ message TestMessageCheck {
optional
bytes
optional_bytes
=
9
;
}
message
TestMessSubMess
{
required
TestMess
rep_mess
=
1
;
required
TestMessOptional
opt_mess
=
2
;
required
TestMessOneof
oneof_mess
=
3
;
required
SubMess
req_mess
=
4
;
required
DefaultOptionalValues
def_mess
=
5
;
}
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