Imported Upstream version 1.1.1
Robert Edmonds
8 years ago
0 | protobuf-c (1.1.1) | |
1 | ||
2 | [ Robert Edmonds ] | |
3 | * Release 1.1.1. | |
4 | ||
5 | * Use protobuf 2.6.1 in the Travis-CI environment. | |
6 | ||
7 | [ Ilya Lipnitskiy ] | |
8 | * Munge C block comment delimiters in protobuf comments, preventing syntax | |
9 | errors in generated header files (Issue #180, #185). | |
10 | ||
11 | * Add static qualifier to ProtobufCEnumValue and ProtobufCEnumValueIndex | |
12 | variables in generated output. | |
13 | ||
14 | [ Oleg Efimov ] | |
15 | * Fix -Wpointer-sign compiler diagnostics in the test suite. | |
16 | ||
17 | * Check for NULL pointers in protobuf_c_message_free_unpacked() | |
18 | (Issue #177). | |
19 | ||
20 | * Exclude protoc-c and downloaded protobuf sources from Coveralls report. | |
21 | ||
22 | [ Andrey Myznikov ] | |
23 | * Fix incorrect 'short_name' field values in ProtobufCServiceDescriptor | |
24 | variables in generated output. | |
25 | ||
26 | protobuf-c (1.1.0) | |
27 | ||
28 | [ Robert Edmonds ] | |
29 | * Release 1.1.0. | |
30 | ||
31 | [ Ilya Lipnitskiy ] | |
32 | * Fix a bug when merging optional byte fields. | |
33 | ||
34 | * Documentation updates. | |
35 | ||
36 | * Implement oneof support (Issue #174). Protobuf 2.6.0 or newer is now | |
37 | required to build protobuf-c. | |
38 | ||
39 | * Print leading comments for enum, message, and field definitions into | |
40 | generated header files (Issue #175). | |
41 | ||
0 | 42 | protobuf-c (1.0.2) |
1 | 43 | |
2 | 44 | [ Robert Edmonds ] |
0 | Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors. | |
0 | Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors. | |
1 | 1 | All rights reserved. |
2 | 2 | |
3 | 3 | Redistribution and use in source and binary forms, with or without |
18 | 18 | If building from a git checkout, the `autotools` (`autoconf`, `automake`, `libtool`) must also be installed, and the build system must be generated by running the `autogen.sh` script. |
19 | 19 | |
20 | 20 | ./autogen.sh && ./configure && make && make install |
21 | ||
22 | ## Documentation | |
23 | ||
24 | See the [online Doxygen documentation here](http://lib.protobuf-c.io) or [the Wiki](https://github.com/protobuf-c/protobuf-c/wiki) for a detailed reference. The Doxygen documentation can be built from the source tree by running: | |
25 | ||
26 | make html | |
21 | 27 | |
22 | 28 | ## Synopsis |
23 | 29 |
0 | 0 | ---------------------- |
1 | 1 | --- IMPORTANT TODO --- |
2 | 2 | ---------------------- |
3 | - ensure enums are int-size | |
4 | - per comments on the main page: wire_format_inl.h is now | |
5 | wire_format_lite_inl.h .. adjust somehow .. possibly write an email | |
6 | - BUG? shouldn't enum..by_name[] and enum..by_number[] in the generated-code | |
7 | be static?? | |
8 | 3 | |
9 | 4 | -------------------- |
10 | 5 | --- NEEDED TESTS --- |
0 | 0 | SET(PACKAGE protobuf-c) |
1 | 1 | SET(PACKAGE_NAME protobuf-c) |
2 | SET(PACKAGE_VERSION 1.0.2) | |
2 | SET(PACKAGE_VERSION 1.1.1) | |
3 | 3 | |
4 | 4 | |
5 | 5 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for protobuf-c 1.0.2. | |
2 | # Generated by GNU Autoconf 2.69 for protobuf-c 1.1.1. | |
3 | 3 | # |
4 | 4 | # Report bugs to <https://github.com/protobuf-c/protobuf-c/issues>. |
5 | 5 | # |
589 | 589 | # Identity of this package. |
590 | 590 | PACKAGE_NAME='protobuf-c' |
591 | 591 | PACKAGE_TARNAME='protobuf-c' |
592 | PACKAGE_VERSION='1.0.2' | |
593 | PACKAGE_STRING='protobuf-c 1.0.2' | |
592 | PACKAGE_VERSION='1.1.1' | |
593 | PACKAGE_STRING='protobuf-c 1.1.1' | |
594 | 594 | PACKAGE_BUGREPORT='https://github.com/protobuf-c/protobuf-c/issues' |
595 | 595 | PACKAGE_URL='https://github.com/protobuf-c/protobuf-c' |
596 | 596 | |
1357 | 1357 | # Omit some internal or obsolete options to make the list less imposing. |
1358 | 1358 | # This message is too long to be a string in the A/UX 3.1 sh. |
1359 | 1359 | cat <<_ACEOF |
1360 | \`configure' configures protobuf-c 1.0.2 to adapt to many kinds of systems. | |
1360 | \`configure' configures protobuf-c 1.1.1 to adapt to many kinds of systems. | |
1361 | 1361 | |
1362 | 1362 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1363 | 1363 | |
1427 | 1427 | |
1428 | 1428 | if test -n "$ac_init_help"; then |
1429 | 1429 | case $ac_init_help in |
1430 | short | recursive ) echo "Configuration of protobuf-c 1.0.2:";; | |
1430 | short | recursive ) echo "Configuration of protobuf-c 1.1.1:";; | |
1431 | 1431 | esac |
1432 | 1432 | cat <<\_ACEOF |
1433 | 1433 | |
1555 | 1555 | test -n "$ac_init_help" && exit $ac_status |
1556 | 1556 | if $ac_init_version; then |
1557 | 1557 | cat <<\_ACEOF |
1558 | protobuf-c configure 1.0.2 | |
1558 | protobuf-c configure 1.1.1 | |
1559 | 1559 | generated by GNU Autoconf 2.69 |
1560 | 1560 | |
1561 | 1561 | Copyright (C) 2012 Free Software Foundation, Inc. |
2178 | 2178 | This file contains any messages produced by compilers while |
2179 | 2179 | running configure, to aid debugging if configure makes a mistake. |
2180 | 2180 | |
2181 | It was created by protobuf-c $as_me 1.0.2, which was | |
2181 | It was created by protobuf-c $as_me 1.1.1, which was | |
2182 | 2182 | generated by GNU Autoconf 2.69. Invocation command line was |
2183 | 2183 | |
2184 | 2184 | $ $0 $@ |
3045 | 3045 | |
3046 | 3046 | # Define the identity of the package. |
3047 | 3047 | PACKAGE='protobuf-c' |
3048 | VERSION='1.0.2' | |
3048 | VERSION='1.1.1' | |
3049 | 3049 | |
3050 | 3050 | |
3051 | 3051 | cat >>confdefs.h <<_ACEOF |
16195 | 16195 | pkg_cv_protobuf_CFLAGS="$protobuf_CFLAGS" |
16196 | 16196 | elif test -n "$PKG_CONFIG"; then |
16197 | 16197 | if test -n "$PKG_CONFIG" && \ |
16198 | { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"protobuf >= 2.5.0\""; } >&5 | |
16199 | ($PKG_CONFIG --exists --print-errors "protobuf >= 2.5.0") 2>&5 | |
16198 | { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"protobuf >= 2.6.0\""; } >&5 | |
16199 | ($PKG_CONFIG --exists --print-errors "protobuf >= 2.6.0") 2>&5 | |
16200 | 16200 | ac_status=$? |
16201 | 16201 | $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 |
16202 | 16202 | test $ac_status = 0; }; then |
16203 | pkg_cv_protobuf_CFLAGS=`$PKG_CONFIG --cflags "protobuf >= 2.5.0" 2>/dev/null` | |
16203 | pkg_cv_protobuf_CFLAGS=`$PKG_CONFIG --cflags "protobuf >= 2.6.0" 2>/dev/null` | |
16204 | 16204 | test "x$?" != "x0" && pkg_failed=yes |
16205 | 16205 | else |
16206 | 16206 | pkg_failed=yes |
16212 | 16212 | pkg_cv_protobuf_LIBS="$protobuf_LIBS" |
16213 | 16213 | elif test -n "$PKG_CONFIG"; then |
16214 | 16214 | if test -n "$PKG_CONFIG" && \ |
16215 | { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"protobuf >= 2.5.0\""; } >&5 | |
16216 | ($PKG_CONFIG --exists --print-errors "protobuf >= 2.5.0") 2>&5 | |
16215 | { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"protobuf >= 2.6.0\""; } >&5 | |
16216 | ($PKG_CONFIG --exists --print-errors "protobuf >= 2.6.0") 2>&5 | |
16217 | 16217 | ac_status=$? |
16218 | 16218 | $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 |
16219 | 16219 | test $ac_status = 0; }; then |
16220 | pkg_cv_protobuf_LIBS=`$PKG_CONFIG --libs "protobuf >= 2.5.0" 2>/dev/null` | |
16220 | pkg_cv_protobuf_LIBS=`$PKG_CONFIG --libs "protobuf >= 2.6.0" 2>/dev/null` | |
16221 | 16221 | test "x$?" != "x0" && pkg_failed=yes |
16222 | 16222 | else |
16223 | 16223 | pkg_failed=yes |
16238 | 16238 | _pkg_short_errors_supported=no |
16239 | 16239 | fi |
16240 | 16240 | if test $_pkg_short_errors_supported = yes; then |
16241 | protobuf_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "protobuf >= 2.5.0" 2>&1` | |
16241 | protobuf_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "protobuf >= 2.6.0" 2>&1` | |
16242 | 16242 | else |
16243 | protobuf_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "protobuf >= 2.5.0" 2>&1` | |
16243 | protobuf_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "protobuf >= 2.6.0" 2>&1` | |
16244 | 16244 | fi |
16245 | 16245 | # Put the nasty error message in config.log where it belongs |
16246 | 16246 | echo "$protobuf_PKG_ERRORS" >&5 |
16247 | 16247 | |
16248 | as_fn_error $? "Package requirements (protobuf >= 2.5.0) were not met: | |
16248 | as_fn_error $? "Package requirements (protobuf >= 2.6.0) were not met: | |
16249 | 16249 | |
16250 | 16250 | $protobuf_PKG_ERRORS |
16251 | 16251 | |
17488 | 17488 | # report actual input values of CONFIG_FILES etc. instead of their |
17489 | 17489 | # values after options handling. |
17490 | 17490 | ac_log=" |
17491 | This file was extended by protobuf-c $as_me 1.0.2, which was | |
17491 | This file was extended by protobuf-c $as_me 1.1.1, which was | |
17492 | 17492 | generated by GNU Autoconf 2.69. Invocation command line was |
17493 | 17493 | |
17494 | 17494 | CONFIG_FILES = $CONFIG_FILES |
17555 | 17555 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
17556 | 17556 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
17557 | 17557 | ac_cs_version="\\ |
17558 | protobuf-c config.status 1.0.2 | |
17558 | protobuf-c config.status 1.1.1 | |
17559 | 17559 | configured by $0, generated by GNU Autoconf 2.69, |
17560 | 17560 | with options \\"\$ac_cs_config\\" |
17561 | 17561 |
0 | 0 | AC_PREREQ(2.64) |
1 | 1 | |
2 | 2 | AC_INIT([protobuf-c], |
3 | [1.0.2], | |
3 | [1.1.1], | |
4 | 4 | [https://github.com/protobuf-c/protobuf-c/issues], |
5 | 5 | [protobuf-c], |
6 | 6 | [https://github.com/protobuf-c/protobuf-c]) |
46 | 46 | AS_HELP_STRING([--disable-protoc], [Disable building protoc_c (also disables tests)])) |
47 | 47 | if test "x$enable_protoc" != "xno"; then |
48 | 48 | AC_LANG_PUSH([C++]) |
49 | PKG_CHECK_MODULES([protobuf], [protobuf >= 2.5.0]) | |
49 | PKG_CHECK_MODULES([protobuf], [protobuf >= 2.6.0]) | |
50 | 50 | |
51 | 51 | save_CPPFLAGS="$CPPFLAGS" |
52 | 52 | CPPFLAGS="$save_CPPFLAGS $protobuf_CFLAGS" |
0 | 0 | /* |
1 | * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors. | |
1 | * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors. | |
2 | 2 | * All rights reserved. |
3 | 3 | * |
4 | 4 | * Redistribution and use in source and binary forms, with or without |
460 | 460 | } |
461 | 461 | |
462 | 462 | /** |
463 | * Calculate the serialized size of a single oneof message field, including | |
464 | * the space needed by the preceding tag. Returns 0 if the oneof field isn't | |
465 | * selected or is not set. | |
466 | * | |
467 | * \param field | |
468 | * Field descriptor for member. | |
469 | * \param oneof_case | |
470 | * A pointer to the case enum that selects the field in the oneof. | |
471 | * \param member | |
472 | * Field to encode. | |
473 | * \return | |
474 | * Number of bytes required. | |
475 | */ | |
476 | static size_t | |
477 | oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field, | |
478 | const uint32_t *oneof_case, | |
479 | const void *member) | |
480 | { | |
481 | if (*oneof_case == field->id) { | |
482 | if (field->type == PROTOBUF_C_TYPE_MESSAGE || | |
483 | field->type == PROTOBUF_C_TYPE_STRING) | |
484 | { | |
485 | const void *ptr = *(const void * const *) member; | |
486 | if (ptr == NULL || ptr == field->default_value) | |
487 | return 0; | |
488 | } | |
489 | } else { | |
490 | return 0; | |
491 | } | |
492 | return required_field_get_packed_size(field, member); | |
493 | } | |
494 | ||
495 | /** | |
463 | 496 | * Calculate the serialized size of a single optional message field, including |
464 | 497 | * the space needed by the preceding tag. Returns 0 if the optional field isn't |
465 | 498 | * set. |
620 | 653 | if (field->label == PROTOBUF_C_LABEL_REQUIRED) { |
621 | 654 | rv += required_field_get_packed_size(field, member); |
622 | 655 | } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { |
623 | rv += optional_field_get_packed_size(field, qmember, member); | |
656 | if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) | |
657 | rv += oneof_field_get_packed_size(field, qmember, member); | |
658 | else | |
659 | rv += optional_field_get_packed_size(field, qmember, member); | |
624 | 660 | } else { |
625 | 661 | rv += repeated_field_get_packed_size( |
626 | 662 | field, |
1018 | 1054 | } |
1019 | 1055 | |
1020 | 1056 | /** |
1057 | * Pack a oneof field and return the number of bytes written. Only packs the | |
1058 | * field that is selected by the case enum. | |
1059 | * | |
1060 | * \param field | |
1061 | * Field descriptor. | |
1062 | * \param oneof_case | |
1063 | * A pointer to the case enum that selects the field in the oneof. | |
1064 | * \param member | |
1065 | * The field member. | |
1066 | * \param[out] out | |
1067 | * Packed value. | |
1068 | * \return | |
1069 | * Number of bytes written to `out`. | |
1070 | */ | |
1071 | static size_t | |
1072 | oneof_field_pack(const ProtobufCFieldDescriptor *field, | |
1073 | const uint32_t *oneof_case, | |
1074 | const void *member, uint8_t *out) | |
1075 | { | |
1076 | if (*oneof_case == field->id) { | |
1077 | if (field->type == PROTOBUF_C_TYPE_MESSAGE || | |
1078 | field->type == PROTOBUF_C_TYPE_STRING) | |
1079 | { | |
1080 | const void *ptr = *(const void * const *) member; | |
1081 | if (ptr == NULL || ptr == field->default_value) | |
1082 | return 0; | |
1083 | } | |
1084 | } else { | |
1085 | return 0; | |
1086 | } | |
1087 | return required_field_pack(field, member, out); | |
1088 | } | |
1089 | ||
1090 | /** | |
1021 | 1091 | * Pack an optional field and return the number of bytes written. |
1022 | 1092 | * |
1023 | 1093 | * \param field |
1311 | 1381 | * quantifier field of the structure), but the pointer is only |
1312 | 1382 | * valid if the field is: |
1313 | 1383 | * - a repeated field, or |
1384 | * - a field that is part of a oneof | |
1314 | 1385 | * - an optional field that isn't a pointer type |
1315 | 1386 | * (Meaning: not a message or a string). |
1316 | 1387 | */ |
1320 | 1391 | if (field->label == PROTOBUF_C_LABEL_REQUIRED) { |
1321 | 1392 | rv += required_field_pack(field, member, out + rv); |
1322 | 1393 | } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { |
1323 | /* | |
1324 | * Note that qmember is bogus for strings and messages, | |
1325 | * but it isn't used. | |
1326 | */ | |
1327 | rv += optional_field_pack(field, qmember, member, out + rv); | |
1394 | if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) | |
1395 | rv += oneof_field_pack (field, qmember, member, out + rv); | |
1396 | else | |
1397 | rv += optional_field_pack(field, qmember, member, out + rv); | |
1328 | 1398 | } else { |
1329 | 1399 | rv += repeated_field_pack(field, *(const size_t *) qmember, |
1330 | 1400 | member, out + rv); |
1456 | 1526 | PROTOBUF_C__ASSERT_NOT_REACHED(); |
1457 | 1527 | } |
1458 | 1528 | return rv; |
1529 | } | |
1530 | ||
1531 | /** | |
1532 | * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum. | |
1533 | * | |
1534 | * \param field | |
1535 | * Field descriptor. | |
1536 | * \param oneof_case | |
1537 | * A pointer to the case enum that selects the field in the oneof. | |
1538 | * \param member | |
1539 | * The element to be packed. | |
1540 | * \param[out] buffer | |
1541 | * Virtual buffer to append data to. | |
1542 | * \return | |
1543 | * Number of bytes serialised to `buffer`. | |
1544 | */ | |
1545 | static size_t | |
1546 | oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, | |
1547 | const uint32_t *oneof_case, | |
1548 | const void *member, ProtobufCBuffer *buffer) | |
1549 | { | |
1550 | if (*oneof_case == field->id) { | |
1551 | if (field->type == PROTOBUF_C_TYPE_MESSAGE || | |
1552 | field->type == PROTOBUF_C_TYPE_STRING) | |
1553 | { | |
1554 | const void *ptr = *(const void *const *) member; | |
1555 | if (ptr == NULL || ptr == field->default_value) | |
1556 | return 0; | |
1557 | } | |
1558 | } else { | |
1559 | return 0; | |
1560 | } | |
1561 | return required_field_pack_to_buffer(field, member, buffer); | |
1459 | 1562 | } |
1460 | 1563 | |
1461 | 1564 | /** |
1734 | 1837 | if (field->label == PROTOBUF_C_LABEL_REQUIRED) { |
1735 | 1838 | rv += required_field_pack_to_buffer(field, member, buffer); |
1736 | 1839 | } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { |
1737 | rv += optional_field_pack_to_buffer( | |
1738 | field, | |
1739 | qmember, | |
1740 | member, | |
1741 | buffer | |
1742 | ); | |
1840 | if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) { | |
1841 | rv += oneof_field_pack_to_buffer( | |
1842 | field, | |
1843 | qmember, | |
1844 | member, | |
1845 | buffer | |
1846 | ); | |
1847 | } else { | |
1848 | rv += optional_field_pack_to_buffer( | |
1849 | field, | |
1850 | qmember, | |
1851 | member, | |
1852 | buffer | |
1853 | ); | |
1854 | } | |
1743 | 1855 | } else { |
1744 | 1856 | rv += repeated_field_pack_to_buffer( |
1745 | 1857 | field, |
1909 | 2021 | { |
1910 | 2022 | unsigned i; |
1911 | 2023 | const ProtobufCFieldDescriptor *fields = |
1912 | earlier_msg->descriptor->fields; | |
2024 | latter_msg->descriptor->fields; | |
1913 | 2025 | for (i = 0; i < latter_msg->descriptor->n_fields; i++) { |
1914 | 2026 | if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) { |
1915 | 2027 | size_t *n_earlier = |
1957 | 2069 | *n_earlier = 0; |
1958 | 2070 | *p_earlier = 0; |
1959 | 2071 | } |
1960 | } else if (fields[i].type == PROTOBUF_C_TYPE_MESSAGE) { | |
1961 | ProtobufCMessage **em = | |
1962 | STRUCT_MEMBER_PTR(ProtobufCMessage *, | |
1963 | earlier_msg, | |
1964 | fields[i].offset); | |
1965 | ProtobufCMessage **lm = | |
1966 | STRUCT_MEMBER_PTR(ProtobufCMessage *, | |
1967 | latter_msg, | |
1968 | fields[i].offset); | |
1969 | if (*em != NULL) { | |
1970 | if (*lm != NULL) { | |
1971 | if (!merge_messages | |
1972 | (*em, *lm, allocator)) | |
1973 | return FALSE; | |
2072 | } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL) { | |
2073 | const ProtobufCFieldDescriptor *field; | |
2074 | uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t, | |
2075 | earlier_msg, | |
2076 | fields[i]. | |
2077 | quantifier_offset); | |
2078 | uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t, | |
2079 | latter_msg, | |
2080 | fields[i]. | |
2081 | quantifier_offset); | |
2082 | ||
2083 | if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) { | |
2084 | if (*latter_case_p == 0) { | |
2085 | /* lookup correct oneof field */ | |
2086 | int field_index = | |
2087 | int_range_lookup( | |
2088 | latter_msg->descriptor | |
2089 | ->n_field_ranges, | |
2090 | latter_msg->descriptor | |
2091 | ->field_ranges, | |
2092 | *earlier_case_p); | |
2093 | field = latter_msg->descriptor->fields + | |
2094 | field_index; | |
1974 | 2095 | } else { |
1975 | /* Zero copy the optional message */ | |
1976 | assert(fields[i].label == | |
1977 | PROTOBUF_C_LABEL_OPTIONAL); | |
1978 | *lm = *em; | |
1979 | *em = NULL; | |
2096 | /* Oneof is present in the latter message, move on */ | |
2097 | continue; | |
1980 | 2098 | } |
2099 | } else { | |
2100 | field = &fields[i]; | |
1981 | 2101 | } |
1982 | } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL) { | |
1983 | size_t el_size = 0; | |
2102 | ||
1984 | 2103 | protobuf_c_boolean need_to_merge = FALSE; |
1985 | 2104 | void *earlier_elem = |
1986 | STRUCT_MEMBER_P(earlier_msg, fields[i].offset); | |
2105 | STRUCT_MEMBER_P(earlier_msg, field->offset); | |
1987 | 2106 | void *latter_elem = |
1988 | STRUCT_MEMBER_P(latter_msg, fields[i].offset); | |
1989 | const void *def_val = fields[i].default_value; | |
1990 | ||
1991 | switch (fields[i].type) { | |
2107 | STRUCT_MEMBER_P(latter_msg, field->offset); | |
2108 | const void *def_val = field->default_value; | |
2109 | ||
2110 | switch (field->type) { | |
2111 | case PROTOBUF_C_TYPE_MESSAGE: { | |
2112 | ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem; | |
2113 | ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem; | |
2114 | if (em != NULL) { | |
2115 | if (lm != NULL) { | |
2116 | if (!merge_messages(em, lm, allocator)) | |
2117 | return FALSE; | |
2118 | /* Already merged */ | |
2119 | need_to_merge = FALSE; | |
2120 | } else { | |
2121 | /* Zero copy the message */ | |
2122 | need_to_merge = TRUE; | |
2123 | } | |
2124 | } | |
2125 | break; | |
2126 | } | |
1992 | 2127 | case PROTOBUF_C_TYPE_BYTES: { |
1993 | el_size = sizeof(ProtobufCBinaryData); | |
1994 | 2128 | uint8_t *e_data = |
1995 | 2129 | ((ProtobufCBinaryData *) earlier_elem)->data; |
1996 | 2130 | uint8_t *l_data = |
2000 | 2134 | |
2001 | 2135 | need_to_merge = |
2002 | 2136 | (e_data != NULL && |
2003 | (d_bd != NULL && | |
2137 | (d_bd == NULL || | |
2004 | 2138 | e_data != d_bd->data)) && |
2005 | 2139 | (l_data == NULL || |
2006 | 2140 | (d_bd != NULL && |
2008 | 2142 | break; |
2009 | 2143 | } |
2010 | 2144 | case PROTOBUF_C_TYPE_STRING: { |
2011 | el_size = sizeof(char *); | |
2012 | 2145 | char *e_str = *(char **) earlier_elem; |
2013 | 2146 | char *l_str = *(char **) latter_elem; |
2014 | 2147 | const char *d_str = def_val; |
2017 | 2150 | break; |
2018 | 2151 | } |
2019 | 2152 | default: { |
2020 | el_size = sizeof_elt_in_repeated_array(fields[i].type); | |
2021 | ||
2022 | need_to_merge = | |
2023 | STRUCT_MEMBER(protobuf_c_boolean, | |
2024 | earlier_msg, | |
2025 | fields[i].quantifier_offset) && | |
2026 | !STRUCT_MEMBER(protobuf_c_boolean, | |
2027 | latter_msg, | |
2028 | fields[i].quantifier_offset); | |
2153 | /* Could be has field or case enum, the logic is | |
2154 | * equivalent, since 0 (FALSE) means not set for | |
2155 | * oneof */ | |
2156 | need_to_merge = (*earlier_case_p != 0) && | |
2157 | (*latter_case_p == 0); | |
2029 | 2158 | break; |
2030 | 2159 | } |
2031 | 2160 | } |
2032 | 2161 | |
2033 | 2162 | if (need_to_merge) { |
2163 | size_t el_size = | |
2164 | sizeof_elt_in_repeated_array(field->type); | |
2034 | 2165 | memcpy(latter_elem, earlier_elem, el_size); |
2035 | 2166 | /* |
2036 | 2167 | * Reset the element from the old message to 0 |
2041 | 2172 | */ |
2042 | 2173 | memset(earlier_elem, 0, el_size); |
2043 | 2174 | |
2044 | if (fields[i].quantifier_offset != 0) { | |
2045 | /* Set the has field, if applicable */ | |
2046 | STRUCT_MEMBER(protobuf_c_boolean, | |
2047 | latter_msg, | |
2048 | fields[i]. | |
2049 | quantifier_offset) = TRUE; | |
2050 | STRUCT_MEMBER(protobuf_c_boolean, | |
2051 | earlier_msg, | |
2052 | fields[i]. | |
2053 | quantifier_offset) = FALSE; | |
2175 | if (field->quantifier_offset != 0) { | |
2176 | /* Set the has field or the case enum, | |
2177 | * if applicable */ | |
2178 | *latter_case_p = *earlier_case_p; | |
2179 | *earlier_case_p = 0; | |
2054 | 2180 | } |
2055 | 2181 | } |
2056 | 2182 | } |
2349 | 2475 | } |
2350 | 2476 | |
2351 | 2477 | static protobuf_c_boolean |
2478 | parse_oneof_member (ScannedMember *scanned_member, | |
2479 | void *member, | |
2480 | ProtobufCMessage *message, | |
2481 | ProtobufCAllocator *allocator) | |
2482 | { | |
2483 | uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message, | |
2484 | scanned_member->field->quantifier_offset); | |
2485 | ||
2486 | /* If we have already parsed a member of this oneof, free it. */ | |
2487 | if (*oneof_case != 0) { | |
2488 | /* lookup field */ | |
2489 | int field_index = | |
2490 | int_range_lookup(message->descriptor->n_field_ranges, | |
2491 | message->descriptor->field_ranges, | |
2492 | *oneof_case); | |
2493 | const ProtobufCFieldDescriptor *old_field = | |
2494 | message->descriptor->fields + field_index; | |
2495 | switch (old_field->type) { | |
2496 | case PROTOBUF_C_TYPE_STRING: { | |
2497 | char **pstr = member; | |
2498 | const char *def = old_field->default_value; | |
2499 | if (*pstr != NULL && *pstr != def) | |
2500 | do_free(allocator, *pstr); | |
2501 | break; | |
2502 | } | |
2503 | case PROTOBUF_C_TYPE_BYTES: { | |
2504 | ProtobufCBinaryData *bd = member; | |
2505 | const ProtobufCBinaryData *def_bd = old_field->default_value; | |
2506 | if (bd->data != NULL && | |
2507 | (def_bd == NULL || bd->data != def_bd->data)) | |
2508 | { | |
2509 | do_free(allocator, bd->data); | |
2510 | } | |
2511 | break; | |
2512 | } | |
2513 | case PROTOBUF_C_TYPE_MESSAGE: { | |
2514 | ProtobufCMessage **pmessage = member; | |
2515 | const ProtobufCMessage *def_mess = old_field->default_value; | |
2516 | if (*pmessage != NULL && *pmessage != def_mess) | |
2517 | protobuf_c_message_free_unpacked(*pmessage, allocator); | |
2518 | break; | |
2519 | } | |
2520 | default: | |
2521 | break; | |
2522 | } | |
2523 | ||
2524 | size_t el_size = sizeof_elt_in_repeated_array(old_field->type); | |
2525 | memset (member, 0, el_size); | |
2526 | } | |
2527 | if (!parse_required_member (scanned_member, member, allocator, TRUE)) | |
2528 | return FALSE; | |
2529 | ||
2530 | *oneof_case = scanned_member->tag; | |
2531 | return TRUE; | |
2532 | } | |
2533 | ||
2534 | ||
2535 | static protobuf_c_boolean | |
2352 | 2536 | parse_optional_member(ScannedMember *scanned_member, |
2353 | 2537 | void *member, |
2354 | 2538 | ProtobufCMessage *message, |
2561 | 2745 | return parse_required_member(scanned_member, member, |
2562 | 2746 | allocator, TRUE); |
2563 | 2747 | case PROTOBUF_C_LABEL_OPTIONAL: |
2564 | return parse_optional_member(scanned_member, member, | |
2565 | message, allocator); | |
2748 | if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) { | |
2749 | return parse_oneof_member(scanned_member, member, | |
2750 | message, allocator); | |
2751 | } else { | |
2752 | return parse_optional_member(scanned_member, member, | |
2753 | message, allocator); | |
2754 | } | |
2566 | 2755 | case PROTOBUF_C_LABEL_REPEATED: |
2567 | 2756 | if (scanned_member->wire_type == |
2568 | 2757 | PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && |
2747 | 2936 | goto error_cleanup_during_scan; |
2748 | 2937 | } |
2749 | 2938 | /* |
2750 | * \todo Consider optimizing for field[1].id == tag, if field[1] | |
2751 | * exists! | |
2752 | */ | |
2939 | * \todo Consider optimizing for field[1].id == tag, if field[1] | |
2940 | * exists! | |
2941 | */ | |
2753 | 2942 | if (last_field == NULL || last_field->id != tag) { |
2754 | 2943 | /* lookup field */ |
2755 | 2944 | int field_index = |
2968 | 3157 | protobuf_c_message_free_unpacked(ProtobufCMessage *message, |
2969 | 3158 | ProtobufCAllocator *allocator) |
2970 | 3159 | { |
3160 | if (message == NULL) | |
3161 | return; | |
3162 | ||
2971 | 3163 | const ProtobufCMessageDescriptor *desc = message->descriptor; |
2972 | 3164 | unsigned f; |
2973 | 3165 | |
2974 | 3166 | ASSERT_IS_MESSAGE(message); |
3167 | ||
2975 | 3168 | if (allocator == NULL) |
2976 | 3169 | allocator = &protobuf_c__allocator; |
2977 | 3170 | message->descriptor = NULL; |
2978 | 3171 | for (f = 0; f < desc->n_fields; f++) { |
3172 | if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) && | |
3173 | desc->fields[f].id != | |
3174 | STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset)) | |
3175 | { | |
3176 | /* This is not the selected oneof, skip it */ | |
3177 | continue; | |
3178 | } | |
3179 | ||
2979 | 3180 | if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) { |
2980 | 3181 | size_t n = STRUCT_MEMBER(size_t, |
2981 | 3182 | message, |
2984 | 3185 | message, |
2985 | 3186 | desc->fields[f].offset); |
2986 | 3187 | |
2987 | if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { | |
2988 | unsigned i; | |
2989 | for (i = 0; i < n; i++) | |
2990 | do_free(allocator, ((char **) arr)[i]); | |
2991 | } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { | |
2992 | unsigned i; | |
2993 | for (i = 0; i < n; i++) | |
2994 | do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); | |
2995 | } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { | |
2996 | unsigned i; | |
2997 | for (i = 0; i < n; i++) | |
2998 | protobuf_c_message_free_unpacked( | |
2999 | ((ProtobufCMessage **) arr)[i], | |
3000 | allocator | |
3001 | ); | |
3188 | if (arr != NULL) { | |
3189 | if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { | |
3190 | unsigned i; | |
3191 | for (i = 0; i < n; i++) | |
3192 | do_free(allocator, ((char **) arr)[i]); | |
3193 | } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { | |
3194 | unsigned i; | |
3195 | for (i = 0; i < n; i++) | |
3196 | do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); | |
3197 | } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { | |
3198 | unsigned i; | |
3199 | for (i = 0; i < n; i++) | |
3200 | protobuf_c_message_free_unpacked( | |
3201 | ((ProtobufCMessage **) arr)[i], | |
3202 | allocator | |
3203 | ); | |
3204 | } | |
3205 | do_free(allocator, arr); | |
3002 | 3206 | } |
3003 | if (arr != NULL) | |
3004 | do_free(allocator, arr); | |
3005 | 3207 | } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { |
3006 | 3208 | char *str = STRUCT_MEMBER(char *, message, |
3007 | 3209 | desc->fields[f].offset); |
105 | 105 | * sufficient to allow them to be cast to `ProtobufCMessage`. |
106 | 106 | * |
107 | 107 | * For each message defined in a `.proto` file, we generate a number of |
108 | * functions. Each function name contains a prefix based on the package name and | |
109 | * message name in order to make it a unique C identifier. | |
110 | * | |
108 | * functions and macros. Each function name contains a prefix based on the | |
109 | * package name and message name in order to make it a unique C identifier. | |
110 | * | |
111 | * - `INIT`. Statically initializes a message object, initializing its | |
112 | * descriptor and setting its fields to default values. Uninitialized | |
113 | * messages cannot be processed by the protobuf-c library. | |
114 | * | |
115 | ~~~{.c} | |
116 | #define FOO__BAR__BAZ_BAH__INIT \ | |
117 | { PROTOBUF_C_MESSAGE_INIT (&foo__bar__baz_bah__descriptor), 0 } | |
118 | ~~~ | |
119 | * - `init()`. Initializes a message object, initializing its descriptor and | |
120 | * setting its fields to default values. Uninitialized messages cannot be | |
121 | * processed by the protobuf-c library. | |
122 | * | |
123 | ~~~{.c} | |
124 | void foo__bar__baz_bah__init | |
125 | (Foo__Bar__BazBah *message); | |
126 | ~~~ | |
111 | 127 | * - `unpack()`. Unpacks data for a particular message format. Note that the |
112 | 128 | * `allocator` parameter is usually `NULL` to indicate that the system's |
113 | 129 | * `malloc()` and `free()` functions should be used for dynamically allocating |
238 | 254 | |
239 | 255 | /** Set if the field is marked with the `deprecated` option. */ |
240 | 256 | PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1), |
257 | ||
258 | /** Set if the field is a member of a oneof (union). */ | |
259 | PROTOBUF_C_FIELD_FLAG_ONEOF = (1 << 2), | |
241 | 260 | } ProtobufCFieldFlag; |
242 | 261 | |
243 | 262 | /** |
544 | 563 | /** |
545 | 564 | * The offset in bytes of the message's C structure's quantifier field |
546 | 565 | * (the `has_MEMBER` field for optional members or the `n_MEMBER` field |
547 | * for repeated members. | |
566 | * for repeated members or the case enum for oneofs). | |
548 | 567 | */ |
549 | 568 | unsigned quantifier_offset; |
550 | 569 | |
761 | 780 | * The version of the protobuf-c headers, represented as a string using the same |
762 | 781 | * format as protobuf_c_version(). |
763 | 782 | */ |
764 | #define PROTOBUF_C_VERSION "1.0.2" | |
783 | #define PROTOBUF_C_VERSION "1.1.1" | |
765 | 784 | |
766 | 785 | /** |
767 | 786 | * The version of the protobuf-c headers, represented as an integer using the |
768 | 787 | * same format as protobuf_c_version_number(). |
769 | 788 | */ |
770 | #define PROTOBUF_C_VERSION_NUMBER 1000002 | |
789 | #define PROTOBUF_C_VERSION_NUMBER 1001001 | |
771 | 790 | |
772 | 791 | /** |
773 | 792 | * The minimum protoc-c version which works with the current version of the |
100 | 100 | printer->Print(variables_, "ProtobufCBinaryData $name$$deprecated$;\n"); |
101 | 101 | break; |
102 | 102 | case FieldDescriptor::LABEL_OPTIONAL: |
103 | printer->Print(variables_, "protobuf_c_boolean has_$name$$deprecated$;\n"); | |
103 | if (descriptor_->containing_oneof() == NULL) | |
104 | printer->Print(variables_, "protobuf_c_boolean has_$name$$deprecated$;\n"); | |
104 | 105 | printer->Print(variables_, "ProtobufCBinaryData $name$$deprecated$;\n"); |
105 | 106 | break; |
106 | 107 | case FieldDescriptor::LABEL_REPEATED: |
85 | 85 | vars["shortname"] = descriptor_->name(); |
86 | 86 | vars["uc_name"] = FullNameToUpper(descriptor_->full_name()); |
87 | 87 | |
88 | SourceLocation sourceLoc; | |
89 | descriptor_->GetSourceLocation(&sourceLoc); | |
90 | PrintComment (printer, sourceLoc.leading_comments); | |
91 | ||
88 | 92 | printer->Print(vars, "typedef enum _$classname$ {\n"); |
89 | 93 | printer->Indent(); |
90 | 94 | |
100 | 104 | if (i + 1 == descriptor_->value_count()) |
101 | 105 | vars["opt_comma"] = ""; |
102 | 106 | |
107 | SourceLocation valSourceLoc; | |
108 | descriptor_->value(i)->GetSourceLocation(&valSourceLoc); | |
109 | ||
110 | PrintComment (printer, valSourceLoc.leading_comments); | |
111 | PrintComment (printer, valSourceLoc.trailing_comments); | |
103 | 112 | printer->Print(vars, "$prefix$$name$ = $number$$opt_comma$\n"); |
104 | 113 | |
105 | 114 | if (descriptor_->value(i)->number() < min_value->number()) { |
206 | 215 | |
207 | 216 | vars["unique_value_count"] = SimpleItoa(n_unique_values); |
208 | 217 | printer->Print(vars, |
209 | "const ProtobufCEnumValue $lcclassname$__enum_values_by_number[$unique_value_count$] =\n" | |
218 | "static const ProtobufCEnumValue $lcclassname$__enum_values_by_number[$unique_value_count$] =\n" | |
210 | 219 | "{\n"); |
211 | 220 | if (descriptor_->value_count() > 0) { |
212 | 221 | GenerateValueInitializer(printer, value_index[0].index); |
259 | 268 | qsort(value_index, descriptor_->value_count(), |
260 | 269 | sizeof(ValueIndex), compare_value_indices_by_name); |
261 | 270 | printer->Print(vars, |
262 | "const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n" | |
271 | "static const ProtobufCEnumValueIndex $lcclassname$__enum_values_by_name[$value_count$] =\n" | |
263 | 272 | "{\n"); |
264 | 273 | for (int j = 0; j < descriptor_->value_count(); j++) { |
265 | 274 | vars["index"] = SimpleItoa(value_index[j].final_index); |
105 | 105 | printer->Print(variables_, "$type$ $name$$deprecated$;\n"); |
106 | 106 | break; |
107 | 107 | case FieldDescriptor::LABEL_OPTIONAL: |
108 | printer->Print(variables_, "protobuf_c_boolean has_$name$$deprecated$;\n"); | |
108 | if (descriptor_->containing_oneof() == NULL) | |
109 | printer->Print(variables_, "protobuf_c_boolean has_$name$$deprecated$;\n"); | |
109 | 110 | printer->Print(variables_, "$type$ $name$$deprecated$;\n"); |
110 | 111 | break; |
111 | 112 | case FieldDescriptor::LABEL_REPEATED: |
113 | 113 | variables["proto_name"] = descriptor_->name(); |
114 | 114 | variables["descriptor_addr"] = descriptor_addr; |
115 | 115 | variables["value"] = SimpleItoa(descriptor_->number()); |
116 | const OneofDescriptor *oneof = descriptor_->containing_oneof(); | |
117 | if (oneof != NULL) | |
118 | variables["oneofname"] = FullNameToLower(oneof->name()); | |
116 | 119 | |
117 | 120 | if (descriptor_->has_default_value()) { |
118 | 121 | variables["default_value"] = string("&") |
131 | 134 | |
132 | 135 | if (descriptor_->options().deprecated()) |
133 | 136 | variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_DEPRECATED"; |
137 | ||
138 | if (oneof != NULL) | |
139 | variables["flags"] += " | PROTOBUF_C_FIELD_FLAG_ONEOF"; | |
134 | 140 | |
135 | 141 | printer->Print(variables, |
136 | 142 | "{\n" |
143 | 149 | printer->Print(variables, " 0, /* quantifier_offset */\n"); |
144 | 150 | break; |
145 | 151 | case FieldDescriptor::LABEL_OPTIONAL: |
146 | if (optional_uses_has) { | |
152 | if (oneof != NULL) { | |
153 | printer->Print(variables, " offsetof($classname$, $oneofname$_case),\n"); | |
154 | } else if (optional_uses_has) { | |
147 | 155 | printer->Print(variables, " offsetof($classname$, has_$name$),\n"); |
148 | 156 | } else { |
149 | 157 | printer->Print(variables, " 0, /* quantifier_offset */\n"); |
207 | 207 | rv += ToCamel(pieces[i]); |
208 | 208 | } |
209 | 209 | return rv; |
210 | } | |
211 | ||
212 | void PrintComment (io::Printer* printer, string comment) | |
213 | { | |
214 | if (!comment.empty()) | |
215 | { | |
216 | vector<string> comment_lines; | |
217 | SplitStringUsing (comment, "\r\n", &comment_lines); | |
218 | printer->Print ("/*\n"); | |
219 | for (int i = 0; i < comment_lines.size(); i++) | |
220 | { | |
221 | if (!comment_lines[i].empty()) | |
222 | { | |
223 | /* Make sure we don't inadvertently close the comment block */ | |
224 | if (comment_lines[i][0] == '/') | |
225 | comment_lines[i] = ' ' + comment_lines[i]; | |
226 | ||
227 | /* Or cause other compiler issues. */ | |
228 | size_t delim_i; | |
229 | while ((delim_i = comment_lines[i].find("/*")) != string::npos) | |
230 | comment_lines[i][delim_i] = ' '; | |
231 | ||
232 | while ((delim_i = comment_lines[i].find("*/")) != string::npos) | |
233 | comment_lines[i][delim_i + 1] = ' '; | |
234 | ||
235 | printer->Print (" *$line$\n", "line", comment_lines[i]); | |
236 | } | |
237 | } | |
238 | printer->Print (" */\n"); | |
239 | } | |
210 | 240 | } |
211 | 241 | |
212 | 242 | string ConvertToSpaces(const string &input) { |
137 | 137 | // full_name() to c-typename (with underscores for packages, otherwise camel case) |
138 | 138 | string FullNameToC(const string &class_name); |
139 | 139 | |
140 | // Splits, indents, formats, and prints comment lines | |
141 | void PrintComment (io::Printer* printer, string comment); | |
142 | ||
140 | 143 | // make a string of spaces as long as input |
141 | 144 | string ConvertToSpaces(const string &input); |
142 | 145 |
146 | 146 | vars["dllexport"] = dllexport_decl_ + " "; |
147 | 147 | } |
148 | 148 | |
149 | // Generate the case enums for unions | |
150 | for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | |
151 | const OneofDescriptor *oneof = descriptor_->oneof_decl(i); | |
152 | vars["oneofname"] = FullNameToUpper(oneof->name()); | |
153 | vars["foneofname"] = FullNameToC(oneof->full_name()); | |
154 | ||
155 | printer->Print("typedef enum {\n"); | |
156 | printer->Indent(); | |
157 | printer->Print(vars, "$ucclassname$__$oneofname$__NOT_SET = 0,\n"); | |
158 | for (int j = 0; j < oneof->field_count(); j++) { | |
159 | const FieldDescriptor *field = oneof->field(j); | |
160 | vars["fieldname"] = FullNameToUpper(field->name()); | |
161 | vars["fieldnum"] = SimpleItoa(field->number()); | |
162 | printer->Print(vars, "$ucclassname$__$oneofname$_$fieldname$ = $fieldnum$,\n"); | |
163 | } | |
164 | printer->Outdent(); | |
165 | printer->Print(vars, "} $foneofname$Case;\n\n"); | |
166 | } | |
167 | ||
168 | SourceLocation msgSourceLoc; | |
169 | descriptor_->GetSourceLocation(&msgSourceLoc); | |
170 | PrintComment (printer, msgSourceLoc.leading_comments); | |
171 | ||
149 | 172 | printer->Print(vars, |
150 | 173 | "struct $dllexport$ _$classname$\n" |
151 | 174 | "{\n" |
155 | 178 | printer->Indent(); |
156 | 179 | for (int i = 0; i < descriptor_->field_count(); i++) { |
157 | 180 | const FieldDescriptor *field = descriptor_->field(i); |
158 | field_generators_.get(field).GenerateStructMembers(printer); | |
181 | if (field->containing_oneof() == NULL) { | |
182 | SourceLocation fieldSourceLoc; | |
183 | field->GetSourceLocation(&fieldSourceLoc); | |
184 | ||
185 | PrintComment (printer, fieldSourceLoc.leading_comments); | |
186 | PrintComment (printer, fieldSourceLoc.trailing_comments); | |
187 | field_generators_.get(field).GenerateStructMembers(printer); | |
188 | } | |
189 | } | |
190 | ||
191 | // Generate unions from oneofs. | |
192 | for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | |
193 | const OneofDescriptor *oneof = descriptor_->oneof_decl(i); | |
194 | vars["oneofname"] = FullNameToLower(oneof->name()); | |
195 | vars["foneofname"] = FullNameToC(oneof->full_name()); | |
196 | ||
197 | printer->Print(vars, "$foneofname$Case $oneofname$_case;\n"); | |
198 | ||
199 | printer->Print("union {\n"); | |
200 | printer->Indent(); | |
201 | for (int j = 0; j < oneof->field_count(); j++) { | |
202 | const FieldDescriptor *field = oneof->field(j); | |
203 | SourceLocation fieldSourceLoc; | |
204 | field->GetSourceLocation(&fieldSourceLoc); | |
205 | ||
206 | PrintComment (printer, fieldSourceLoc.leading_comments); | |
207 | PrintComment (printer, fieldSourceLoc.trailing_comments); | |
208 | field_generators_.get(field).GenerateStructMembers(printer); | |
209 | } | |
210 | printer->Outdent(); | |
211 | printer->Print(vars, "};\n"); | |
159 | 212 | } |
160 | 213 | printer->Outdent(); |
161 | 214 | |
172 | 225 | " { PROTOBUF_C_MESSAGE_INIT (&$lcclassname$__descriptor) \\\n "); |
173 | 226 | for (int i = 0; i < descriptor_->field_count(); i++) { |
174 | 227 | const FieldDescriptor *field = descriptor_->field(i); |
175 | printer->Print(", "); | |
176 | field_generators_.get(field).GenerateStaticInit(printer); | |
228 | if (field->containing_oneof() == NULL) { | |
229 | printer->Print(", "); | |
230 | field_generators_.get(field).GenerateStaticInit(printer); | |
231 | } | |
232 | } | |
233 | for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { | |
234 | const OneofDescriptor *oneof = descriptor_->oneof_decl(i); | |
235 | vars["foneofname"] = FullNameToUpper(oneof->full_name()); | |
236 | // Initialize the case enum | |
237 | printer->Print(vars, ", $foneofname$__NOT_SET"); | |
238 | // Initialize the enum | |
239 | printer->Print(", {}"); | |
177 | 240 | } |
178 | 241 | printer->Print(" }\n\n\n"); |
179 | 242 |
112 | 112 | printer->Print(vars, "$c_type$ $name$$deprecated$;\n"); |
113 | 113 | break; |
114 | 114 | case FieldDescriptor::LABEL_OPTIONAL: |
115 | printer->Print(vars, "protobuf_c_boolean has_$name$$deprecated$;\n"); | |
115 | if (descriptor_->containing_oneof() == NULL) | |
116 | printer->Print(vars, "protobuf_c_boolean has_$name$$deprecated$;\n"); | |
116 | 117 | printer->Print(vars, "$c_type$ $name$$deprecated$;\n"); |
117 | 118 | break; |
118 | 119 | case FieldDescriptor::LABEL_REPEATED: |
196 | 196 | { |
197 | 197 | int n_methods = descriptor_->method_count(); |
198 | 198 | MethodIndexAndName *mi_array = new MethodIndexAndName[n_methods]; |
199 | ||
199 | ||
200 | 200 | vars_["n_methods"] = SimpleItoa(n_methods); |
201 | 201 | printer->Print(vars_, "static const ProtobufCMethodDescriptor $lcfullname$__method_descriptors[$n_methods$] =\n" |
202 | 202 | "{\n"); |
222 | 222 | printer->Print(vars_, " $i$$comma$ /* $name$ */\n"); |
223 | 223 | } |
224 | 224 | printer->Print(vars_, "};\n"); |
225 | ||
226 | vars_["name"] = descriptor_->name(); | |
225 | 227 | |
226 | 228 | printer->Print(vars_, "const ProtobufCServiceDescriptor $lcfullname$__descriptor =\n" |
227 | 229 | "{\n" |
250 | 252 | vars_["output_typename"] = FullNameToC(method->output_type()->full_name()); |
251 | 253 | vars_["padddddddddddddddddd"] = ConvertToSpaces(lcfullname + "__" + lcname); |
252 | 254 | vars_["index"] = SimpleItoa(i); |
253 | ||
255 | ||
254 | 256 | printer->Print(vars_, |
255 | 257 | "void $lcfullname$__$method$(ProtobufCService *service,\n" |
256 | 258 | " $padddddddddddddddddd$ const $input_typename$ *input,\n" |
35 | 35 | #define N_ELEMENTS(arr) (sizeof(arr)/sizeof((arr)[0])) |
36 | 36 | |
37 | 37 | static void |
38 | dump_messages_bytes(size_t n_msgs, | |
39 | google::protobuf::Message **messages, | |
40 | const char *label) | |
41 | { | |
42 | printf ("static const uint8_t %s[] = { ", label); | |
43 | for (unsigned m = 0; m < n_msgs; m++) { | |
44 | std::string rv; | |
45 | google::protobuf::Message *message = messages[m]; | |
46 | if (m) | |
47 | printf (", "); | |
48 | if (!message->SerializeToString(&rv)) | |
49 | assert(0); | |
50 | unsigned char *bytes = (unsigned char *) rv.data(); | |
51 | for (unsigned i = 0; i < rv.size(); i++) { | |
52 | if (i) | |
53 | printf (", "); | |
54 | printf ("0x%02x", bytes[i]); | |
55 | } | |
56 | } | |
57 | printf (" };\n"); | |
58 | } | |
59 | ||
60 | static void | |
38 | 61 | dump_message_bytes(google::protobuf::Message *message, |
39 | 62 | const char *label) |
40 | 63 | { |
41 | std::string rv; | |
42 | unsigned char *bytes; | |
43 | unsigned len; | |
44 | if (!message->SerializeToString(&rv)) | |
45 | assert(0); | |
46 | bytes = (unsigned char *) rv.data(); | |
47 | len = rv.size(); | |
48 | printf ("static const uint8_t %s[%u] = { ", label, len); | |
49 | for (unsigned i = 0; i < len; i++) { | |
50 | if (i) | |
51 | printf (", "); | |
52 | printf ("0x%02x", bytes[i]); | |
53 | } | |
54 | printf (" };\n"); | |
64 | dump_messages_bytes (1, &message, label); | |
55 | 65 | } |
56 | 66 | |
57 | 67 | static void |
563 | 573 | opt.mutable_test_message()->set_test(42); |
564 | 574 | dump_message_bytes (&opt, "test_optional_submess_42"); |
565 | 575 | } |
576 | static void dump_test_oneof_merge (void) | |
577 | { | |
578 | #define SWAP(a, b) temp = a, a = b, b = temp | |
579 | google::protobuf::Message *temp; | |
580 | TestMessOptional opt[6]; | |
581 | google::protobuf::Message *msgs[6] = { &opt[0], &opt[1], &opt[2], &opt[3], | |
582 | &opt[4], &opt[5] }; | |
583 | opt[0].set_test_bytes ("hello"); | |
584 | opt[1].mutable_test_message()->set_test (42); | |
585 | opt[2].set_test_string (""); | |
586 | opt[3].set_test_int32 (666); | |
587 | opt[4].set_test_float (333); | |
588 | opt[5].set_test_double (444455555); | |
589 | dump_messages_bytes (6, msgs, "test_oneof_merge_double"); | |
590 | SWAP (msgs[5], msgs[4]); | |
591 | dump_messages_bytes (6, msgs, "test_oneof_merge_float"); | |
592 | SWAP (msgs[5], msgs[3]); | |
593 | dump_messages_bytes (6, msgs, "test_oneof_merge_int32"); | |
594 | SWAP (msgs[5], msgs[2]); | |
595 | dump_messages_bytes (6, msgs, "test_oneof_merge_string"); | |
596 | SWAP (msgs[5], msgs[1]); | |
597 | dump_messages_bytes (6, msgs, "test_oneof_merge_submess"); | |
598 | SWAP (msgs[5], msgs[0]); | |
599 | dump_messages_bytes (6, msgs, "test_oneof_merge_bytes"); | |
600 | ||
601 | #undef SWAP | |
602 | } | |
566 | 603 | |
567 | 604 | #define DUMP_STATIC_ARRAY_GENERIC(member, static_array, output_array_name) \ |
568 | 605 | do{ \ |
975 | 1012 | #endif |
976 | 1013 | |
977 | 1014 | dump_message_bytes (&mess, "test_unknown_fields_1"); |
1015 | } | |
1016 | ||
1017 | static void dump_test_submess_merge (void) | |
1018 | { | |
1019 | TestMessSubMess mess1, mess2, merged1, merged2; | |
1020 | ||
1021 | /* Repeated merge */ | |
1022 | mess1.mutable_rep_mess()->add_test_int32(1); | |
1023 | mess1.mutable_rep_mess()->add_test_int32(2); | |
1024 | mess2.mutable_rep_mess()->add_test_int32(3); | |
1025 | mess2.mutable_rep_mess()->add_test_int32(4); | |
1026 | ||
1027 | mess1.mutable_rep_mess()->add_test_string("hello "); | |
1028 | mess2.mutable_rep_mess()->add_test_string("world"); | |
1029 | ||
1030 | mess1.mutable_rep_mess()->add_test_bytes("\001\002\003"); | |
1031 | mess2.mutable_rep_mess()->add_test_bytes("\004\005\006"); | |
1032 | ||
1033 | mess1.mutable_rep_mess()->add_test_message()->set_test(111); | |
1034 | mess2.mutable_rep_mess()->add_test_message()->set_test(222); | |
1035 | ||
1036 | /* Optional merge */ | |
1037 | mess1.mutable_opt_mess()->set_test_sint32(-1); | |
1038 | mess2.mutable_opt_mess()->set_test_sint32(-2); | |
1039 | ||
1040 | mess1.mutable_opt_mess()->set_test_float(333); | |
1041 | mess2.mutable_opt_mess()->set_test_double(444); | |
1042 | ||
1043 | mess1.mutable_opt_mess()->set_test_bytes("\001\002\003"); | |
1044 | mess1.mutable_opt_mess()->mutable_test_message()->set_test(111); | |
1045 | mess2.mutable_opt_mess()->set_test_string("hello"); | |
1046 | ||
1047 | /* Oneof merge */ | |
1048 | mess1.mutable_oneof_mess()->set_opt_int (1); | |
1049 | mess2.mutable_oneof_mess()->mutable_test_message()->set_test(111); | |
1050 | ||
1051 | /* Required merge */ | |
1052 | mess1.mutable_req_mess()->set_test(1); | |
1053 | mess2.mutable_req_mess()->set_test(2); | |
1054 | ||
1055 | /* Default value merge */ | |
1056 | mess1.mutable_def_mess()->set_v_int32(111); | |
1057 | mess1.mutable_def_mess()->set_v_string("hello"); | |
1058 | mess2.mutable_def_mess()->set_v_bytes("\001\002\003"); | |
1059 | mess2.mutable_def_mess()->set_v_double(444); | |
1060 | ||
1061 | /* Merge both ways and encode the merged and unmerged messages */ | |
1062 | merged1.CopyFrom(mess1); | |
1063 | merged1.MergeFrom(mess2); | |
1064 | merged2.CopyFrom(mess2); | |
1065 | merged2.MergeFrom(mess1); | |
1066 | ||
1067 | google::protobuf::Message *msgs[] = { &mess1, &mess2 }; | |
1068 | dump_messages_bytes (2, msgs, "test_submess_unmerged1"); | |
1069 | msgs[0] = &mess2; | |
1070 | msgs[1] = &mess1; | |
1071 | dump_messages_bytes (2, msgs, "test_submess_unmerged2"); | |
1072 | dump_message_bytes(&merged1, "test_submess_merged1"); | |
1073 | dump_message_bytes(&merged2, "test_submess_merged2"); | |
978 | 1074 | } |
979 | 1075 | |
980 | 1076 | int main() |
1018 | 1114 | dump_test_optional_string (); |
1019 | 1115 | dump_test_optional_bytes (); |
1020 | 1116 | dump_test_optional_message (); |
1117 | dump_test_oneof_merge (); | |
1021 | 1118 | dump_test_repeated_int32 (); |
1022 | 1119 | dump_test_repeated_sint32 (); |
1023 | 1120 | dump_test_repeated_uint32 (); |
1052 | 1149 | dump_test_packed_repeated_enum_small (); |
1053 | 1150 | dump_test_packed_repeated_enum (); |
1054 | 1151 | dump_test_unknown_fields (); |
1152 | dump_test_submess_merge (); | |
1055 | 1153 | return 0; |
1056 | 1154 | } |
81 | 81 | return rv; |
82 | 82 | } |
83 | 83 | |
84 | #define GENERIC_ASSIGN(dst,src) ((dst) = (src)) | |
85 | ||
84 | 86 | #define NUMERIC_EQUALS(a,b) ((a) == (b)) |
85 | 87 | #define STRING_EQUALS(a,b) (strcmp((a),(b))==0) |
88 | ||
89 | #define CHECK_NONE(a) | |
90 | #define CHECK_NOT_NULL(a) assert( (a) != NULL ) | |
86 | 91 | |
87 | 92 | static protobuf_c_boolean |
88 | 93 | binary_data_equals (ProtobufCBinaryData a, ProtobufCBinaryData b) |
680 | 685 | DO_TEST (&submess, test_optional_submess_42); |
681 | 686 | #undef DO_TEST |
682 | 687 | } |
688 | ||
689 | /* === Oneof type fields === */ | |
690 | static void test_empty_oneof (void) | |
691 | { | |
692 | Foo__TestMessOneof mess = FOO__TEST_MESS_ONEOF__INIT; | |
693 | size_t len; | |
694 | uint8_t *data; | |
695 | Foo__TestMessOneof *mess2 = test_compare_pack_methods (&mess.base, &len, &data); | |
696 | assert (len == 0); | |
697 | free (data); | |
698 | foo__test_mess_oneof__free_unpacked (mess2, NULL); | |
699 | } | |
700 | ||
701 | #define DO_TEST_GENERIC_ONEOF(type, init, free_unpacked, case_member, case_enum, member, value, example_packed_data, assign, equal_func, result_check) \ | |
702 | do{ \ | |
703 | type opt = init; \ | |
704 | type *mess; \ | |
705 | size_t len; uint8_t *data; \ | |
706 | opt.case_member = case_enum; \ | |
707 | assign(opt.member, value); \ | |
708 | mess = test_compare_pack_methods (&opt.base, &len, &data); \ | |
709 | TEST_VERSUS_STATIC_ARRAY (len, data, example_packed_data); \ | |
710 | assert (mess->case_member == case_enum); \ | |
711 | result_check(mess->member); \ | |
712 | assert (equal_func (mess->member, value)); \ | |
713 | free_unpacked (mess, NULL); \ | |
714 | free (data); \ | |
715 | }while(0) | |
716 | ||
717 | #define DO_TEST_ONEOF(member, MEMBER, value, example_packed_data, assign, equal_func) \ | |
718 | DO_TEST_GENERIC_ONEOF(Foo__TestMessOneof, \ | |
719 | FOO__TEST_MESS_ONEOF__INIT, \ | |
720 | foo__test_mess_oneof__free_unpacked, \ | |
721 | test_oneof_case, \ | |
722 | FOO__TEST_MESS_ONEOF__TEST_ONEOF_##MEMBER, \ | |
723 | member, \ | |
724 | value, example_packed_data, assign, equal_func, CHECK_NONE) | |
725 | ||
726 | #define DO_TEST_ONEOF_REF_VAL(member, MEMBER, value, example_packed_data, assign, equal_func) \ | |
727 | DO_TEST_GENERIC_ONEOF(Foo__TestMessOneof, \ | |
728 | FOO__TEST_MESS_ONEOF__INIT, \ | |
729 | foo__test_mess_oneof__free_unpacked, \ | |
730 | test_oneof_case, \ | |
731 | FOO__TEST_MESS_ONEOF__TEST_ONEOF_##MEMBER, \ | |
732 | member, \ | |
733 | value, example_packed_data, assign, equal_func, CHECK_NOT_NULL) | |
734 | ||
735 | static void test_oneof_int32 (void) | |
736 | { | |
737 | #define DO_TEST(value, example_packed_data) \ | |
738 | DO_TEST_ONEOF(test_int32, TEST_INT32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
739 | ||
740 | DO_TEST (INT32_MIN, test_optional_int32_min); | |
741 | DO_TEST (-1, test_optional_int32_m1); | |
742 | DO_TEST (0, test_optional_int32_0); | |
743 | DO_TEST (666, test_optional_int32_666); | |
744 | DO_TEST (INT32_MAX, test_optional_int32_max); | |
745 | ||
746 | #undef DO_TEST | |
747 | } | |
748 | static void test_oneof_sint32 (void) | |
749 | { | |
750 | #define DO_TEST(value, example_packed_data) \ | |
751 | DO_TEST_ONEOF(test_sint32, TEST_SINT32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
752 | ||
753 | DO_TEST (INT32_MIN, test_optional_sint32_min); | |
754 | DO_TEST (-1, test_optional_sint32_m1); | |
755 | DO_TEST (0, test_optional_sint32_0); | |
756 | DO_TEST (666, test_optional_sint32_666); | |
757 | DO_TEST (INT32_MAX, test_optional_sint32_max); | |
758 | ||
759 | #undef DO_TEST | |
760 | } | |
761 | static void test_oneof_sfixed32 (void) | |
762 | { | |
763 | #define DO_TEST(value, example_packed_data) \ | |
764 | DO_TEST_ONEOF(test_sfixed32, TEST_SFIXED32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
765 | ||
766 | DO_TEST (INT32_MIN, test_optional_sfixed32_min); | |
767 | DO_TEST (-1, test_optional_sfixed32_m1); | |
768 | DO_TEST (0, test_optional_sfixed32_0); | |
769 | DO_TEST (666, test_optional_sfixed32_666); | |
770 | DO_TEST (INT32_MAX, test_optional_sfixed32_max); | |
771 | ||
772 | #undef DO_TEST | |
773 | } | |
774 | static void test_oneof_int64 (void) | |
775 | { | |
776 | #define DO_TEST(value, example_packed_data) \ | |
777 | DO_TEST_ONEOF(test_int64, TEST_INT64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
778 | ||
779 | DO_TEST (INT64_MIN, test_optional_int64_min); | |
780 | DO_TEST (-1111111111LL, test_optional_int64_m1111111111LL); | |
781 | DO_TEST (0, test_optional_int64_0); | |
782 | DO_TEST (QUINTILLION, test_optional_int64_quintillion); | |
783 | DO_TEST (INT64_MAX, test_optional_int64_max); | |
784 | ||
785 | #undef DO_TEST | |
786 | } | |
787 | static void test_oneof_sint64 (void) | |
788 | { | |
789 | #define DO_TEST(value, example_packed_data) \ | |
790 | DO_TEST_ONEOF(test_sint64, TEST_SINT64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
791 | ||
792 | DO_TEST (INT64_MIN, test_optional_sint64_min); | |
793 | DO_TEST (-1111111111LL, test_optional_sint64_m1111111111LL); | |
794 | DO_TEST (0, test_optional_sint64_0); | |
795 | DO_TEST (QUINTILLION, test_optional_sint64_quintillion); | |
796 | DO_TEST (INT64_MAX, test_optional_sint64_max); | |
797 | ||
798 | #undef DO_TEST | |
799 | } | |
800 | static void test_oneof_sfixed64 (void) | |
801 | { | |
802 | #define DO_TEST(value, example_packed_data) \ | |
803 | DO_TEST_ONEOF(test_sfixed64, TEST_SFIXED64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
804 | ||
805 | DO_TEST (INT64_MIN, test_optional_sfixed64_min); | |
806 | DO_TEST (-1111111111LL, test_optional_sfixed64_m1111111111LL); | |
807 | DO_TEST (0, test_optional_sfixed64_0); | |
808 | DO_TEST (QUINTILLION, test_optional_sfixed64_quintillion); | |
809 | DO_TEST (INT64_MAX, test_optional_sfixed64_max); | |
810 | ||
811 | #undef DO_TEST | |
812 | } | |
813 | ||
814 | static void test_oneof_uint32 (void) | |
815 | { | |
816 | #define DO_TEST(value, example_packed_data) \ | |
817 | DO_TEST_ONEOF(test_uint32, TEST_UINT32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
818 | ||
819 | DO_TEST (0, test_optional_uint32_0); | |
820 | DO_TEST (669, test_optional_uint32_669); | |
821 | DO_TEST (UINT32_MAX, test_optional_uint32_max); | |
822 | ||
823 | #undef DO_TEST | |
824 | } | |
825 | ||
826 | static void test_oneof_fixed32 (void) | |
827 | { | |
828 | #define DO_TEST(value, example_packed_data) \ | |
829 | DO_TEST_ONEOF(test_fixed32, TEST_FIXED32, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
830 | ||
831 | DO_TEST (0, test_optional_fixed32_0); | |
832 | DO_TEST (669, test_optional_fixed32_669); | |
833 | DO_TEST (UINT32_MAX, test_optional_fixed32_max); | |
834 | ||
835 | #undef DO_TEST | |
836 | } | |
837 | ||
838 | static void test_oneof_uint64 (void) | |
839 | { | |
840 | #define DO_TEST(value, example_packed_data) \ | |
841 | DO_TEST_ONEOF(test_uint64, TEST_UINT64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
842 | ||
843 | DO_TEST (0, test_optional_uint64_0); | |
844 | DO_TEST (669669669669669ULL, test_optional_uint64_669669669669669); | |
845 | DO_TEST (UINT64_MAX, test_optional_uint64_max); | |
846 | ||
847 | #undef DO_TEST | |
848 | } | |
849 | ||
850 | static void test_oneof_fixed64 (void) | |
851 | { | |
852 | #define DO_TEST(value, example_packed_data) \ | |
853 | DO_TEST_ONEOF(test_fixed64, TEST_FIXED64, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
854 | ||
855 | DO_TEST (0, test_optional_fixed64_0); | |
856 | DO_TEST (669669669669669ULL, test_optional_fixed64_669669669669669); | |
857 | DO_TEST (UINT64_MAX, test_optional_fixed64_max); | |
858 | ||
859 | #undef DO_TEST | |
860 | } | |
861 | ||
862 | static void test_oneof_float (void) | |
863 | { | |
864 | #define DO_TEST(value, example_packed_data) \ | |
865 | DO_TEST_ONEOF(test_float, TEST_FLOAT, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
866 | ||
867 | DO_TEST (-100, test_optional_float_m100); | |
868 | DO_TEST (0, test_optional_float_0); | |
869 | DO_TEST (141243, test_optional_float_141243); | |
870 | ||
871 | #undef DO_TEST | |
872 | } | |
873 | static void test_oneof_double (void) | |
874 | { | |
875 | #define DO_TEST(value, example_packed_data) \ | |
876 | DO_TEST_ONEOF(test_double, TEST_DOUBLE, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
877 | ||
878 | DO_TEST (-100, test_optional_double_m100); | |
879 | DO_TEST (0, test_optional_double_0); | |
880 | DO_TEST (141243, test_optional_double_141243); | |
881 | ||
882 | #undef DO_TEST | |
883 | } | |
884 | static void test_oneof_bool (void) | |
885 | { | |
886 | #define DO_TEST(value, example_packed_data) \ | |
887 | DO_TEST_ONEOF(test_boolean, TEST_BOOLEAN, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
888 | ||
889 | DO_TEST (0, test_optional_bool_0); | |
890 | DO_TEST (1, test_optional_bool_1); | |
891 | ||
892 | #undef DO_TEST | |
893 | } | |
894 | static void test_oneof_TestEnumSmall (void) | |
895 | { | |
896 | #define DO_TEST(value, example_packed_data) \ | |
897 | DO_TEST_ONEOF(test_enum_small, TEST_ENUM_SMALL, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
898 | ||
899 | DO_TEST (0, test_optional_enum_small_0); | |
900 | DO_TEST (1, test_optional_enum_small_1); | |
901 | ||
902 | #undef DO_TEST | |
903 | } | |
904 | ||
905 | static void test_oneof_TestEnum (void) | |
906 | { | |
907 | #define DO_TEST(value, example_packed_data) \ | |
908 | DO_TEST_ONEOF(test_enum, TEST_ENUM, value, example_packed_data, GENERIC_ASSIGN, NUMERIC_EQUALS) | |
909 | ||
910 | DO_TEST (FOO__TEST_ENUM__VALUE0, test_optional_enum_0); | |
911 | DO_TEST (FOO__TEST_ENUM__VALUE1, test_optional_enum_1); | |
912 | DO_TEST (FOO__TEST_ENUM__VALUE127, test_optional_enum_127); | |
913 | DO_TEST (FOO__TEST_ENUM__VALUE128, test_optional_enum_128); | |
914 | DO_TEST (FOO__TEST_ENUM__VALUE16383, test_optional_enum_16383); | |
915 | DO_TEST (FOO__TEST_ENUM__VALUE16384, test_optional_enum_16384); | |
916 | DO_TEST (FOO__TEST_ENUM__VALUE2097151, test_optional_enum_2097151); | |
917 | DO_TEST (FOO__TEST_ENUM__VALUE2097152, test_optional_enum_2097152); | |
918 | DO_TEST (FOO__TEST_ENUM__VALUE268435455, test_optional_enum_268435455); | |
919 | DO_TEST (FOO__TEST_ENUM__VALUE268435456, test_optional_enum_268435456); | |
920 | ||
921 | #undef DO_TEST | |
922 | } | |
923 | ||
924 | static void test_oneof_string (void) | |
925 | { | |
926 | #define DO_TEST(value, example_packed_data) \ | |
927 | DO_TEST_ONEOF_REF_VAL (test_string, TEST_STRING, value, example_packed_data, GENERIC_ASSIGN, STRING_EQUALS) | |
928 | DO_TEST ("", test_optional_string_empty); | |
929 | DO_TEST ("hello", test_optional_string_hello); | |
930 | #undef DO_TEST | |
931 | } | |
932 | static void test_oneof_bytes (void) | |
933 | { | |
934 | static ProtobufCBinaryData bd_empty = { 0, (uint8_t*)"" }; | |
935 | static ProtobufCBinaryData bd_hello = { 5, (uint8_t*)"hello" }; | |
936 | static ProtobufCBinaryData bd_random = { 5, (uint8_t*)"\1\0\375\2\4" }; | |
937 | #define DO_TEST(value, example_packed_data) \ | |
938 | DO_TEST_ONEOF (test_bytes, TEST_BYTES, value, example_packed_data, GENERIC_ASSIGN, binary_data_equals) | |
939 | DO_TEST (bd_empty, test_optional_bytes_empty); | |
940 | DO_TEST (bd_hello, test_optional_bytes_hello); | |
941 | DO_TEST (bd_random, test_optional_bytes_random); | |
942 | #undef DO_TEST | |
943 | } | |
944 | static void test_oneof_SubMess (void) | |
945 | { | |
946 | Foo__SubMess submess = FOO__SUB_MESS__INIT; | |
947 | #define DO_TEST(value, example_packed_data) \ | |
948 | DO_TEST_ONEOF_REF_VAL (test_message, TEST_MESSAGE, value, example_packed_data, GENERIC_ASSIGN, submesses_equals) | |
949 | submess.test = 0; | |
950 | DO_TEST (&submess, test_optional_submess_0); | |
951 | submess.test = 42; | |
952 | DO_TEST (&submess, test_optional_submess_42); | |
953 | #undef DO_TEST | |
954 | } | |
955 | static void test_oneof_merge (void) | |
956 | { | |
957 | Foo__TestMessOneof *msg; | |
958 | #define DO_TEST(value, member, MEMBER, equals_func, example_packed_data) \ | |
959 | msg = foo__test_mess_oneof__unpack (NULL, sizeof (example_packed_data), example_packed_data); \ | |
960 | assert (msg); \ | |
961 | assert (msg->test_oneof_case == FOO__TEST_MESS_ONEOF__TEST_ONEOF_##MEMBER); \ | |
962 | assert (equals_func (msg->member, value)); \ | |
963 | foo__test_mess_oneof__free_unpacked (msg, NULL); | |
964 | ||
965 | DO_TEST (444455555, test_double, TEST_DOUBLE, NUMERIC_EQUALS, test_oneof_merge_double); | |
966 | DO_TEST (333, test_float, TEST_FLOAT, NUMERIC_EQUALS, test_oneof_merge_float); | |
967 | DO_TEST (666, test_int32, TEST_INT32, NUMERIC_EQUALS, test_oneof_merge_int32); | |
968 | DO_TEST ("", test_string, TEST_STRING, STRING_EQUALS, test_oneof_merge_string); | |
969 | ||
970 | Foo__SubMess submess = FOO__SUB_MESS__INIT; | |
971 | submess.test = 42; | |
972 | DO_TEST (&submess, test_message, TEST_MESSAGE, submesses_equals, test_oneof_merge_submess); | |
973 | ||
974 | ProtobufCBinaryData bd_hello = { 5, (uint8_t*)"hello" }; | |
975 | DO_TEST(bd_hello, test_bytes, TEST_BYTES, binary_data_equals, test_oneof_merge_bytes); | |
976 | #undef DO_TEST | |
977 | } | |
978 | ||
683 | 979 | /* === repeated type fields === */ |
684 | 980 | #define DO_TEST_REPEATED(lc_member_name, cast, \ |
685 | 981 | static_array, example_packed_data, \ |
1513 | 1809 | foo__test_mess_optional__free_unpacked (merged, NULL); |
1514 | 1810 | } |
1515 | 1811 | |
1812 | static void | |
1813 | test_submessage_merge (void) | |
1814 | { | |
1815 | Foo__TestMessSubMess *merged; | |
1816 | size_t size; | |
1817 | uint8_t *packed; | |
1818 | ||
1819 | merged = foo__test_mess_sub_mess__unpack | |
1820 | (NULL, sizeof (test_submess_unmerged1), test_submess_unmerged1); | |
1821 | ||
1822 | size = foo__test_mess_sub_mess__get_packed_size(merged); | |
1823 | packed = malloc (size); | |
1824 | foo__test_mess_sub_mess__pack (merged, packed); | |
1825 | ||
1826 | assert (size == sizeof (test_submess_merged1)); | |
1827 | assert (memcmp (packed, test_submess_merged1, size) == 0); | |
1828 | ||
1829 | foo__test_mess_sub_mess__free_unpacked (merged, NULL); | |
1830 | free (packed); | |
1831 | ||
1832 | merged = foo__test_mess_sub_mess__unpack | |
1833 | (NULL, sizeof (test_submess_unmerged2), test_submess_unmerged2); | |
1834 | ||
1835 | size = foo__test_mess_sub_mess__get_packed_size(merged); | |
1836 | packed = malloc (size); | |
1837 | foo__test_mess_sub_mess__pack (merged, packed); | |
1838 | ||
1839 | assert (size == sizeof (test_submess_merged2)); | |
1840 | assert (memcmp (packed, test_submess_merged2, size) == 0); | |
1841 | ||
1842 | foo__test_mess_sub_mess__free_unpacked (merged, NULL); | |
1843 | free (packed); | |
1844 | } | |
1845 | ||
1516 | 1846 | static struct alloc_data { |
1517 | 1847 | uint32_t alloc_count; |
1518 | 1848 | int32_t allocs_left; |
1594 | 1924 | free (packed); |
1595 | 1925 | } |
1596 | 1926 | |
1927 | static void | |
1928 | test_free_unpacked_input_check_for_null_message (void) | |
1929 | { | |
1930 | protobuf_c_message_free_unpacked (NULL, NULL); | |
1931 | } | |
1932 | ||
1933 | static void | |
1934 | test_free_unpacked_input_check_for_null_repeated_field (void) | |
1935 | { | |
1936 | Foo__TestMess *tm = calloc(1, foo__test_mess__descriptor.sizeof_message); | |
1937 | foo__test_mess__init(tm); | |
1938 | ||
1939 | tm->n_test_string = 1; | |
1940 | tm->test_string = NULL; | |
1941 | ||
1942 | tm->n_test_bytes = 1; | |
1943 | tm->test_bytes = NULL; | |
1944 | ||
1945 | tm->n_test_message = 1; | |
1946 | tm->test_message = NULL; | |
1947 | ||
1948 | foo__test_mess__free_unpacked (tm, NULL); | |
1949 | } | |
1950 | ||
1597 | 1951 | /* This test checks that protobuf decoder is capable of detecting special |
1598 | 1952 | cases of incomplete messages. The message should have at least two required |
1599 | 1953 | fields field1 and field129 with positions pos1 and pos2 (no matter what the |
1615 | 1969 | test_field_flags (void) |
1616 | 1970 | { |
1617 | 1971 | const ProtobufCFieldDescriptor *f; |
1618 | ||
1619 | f = protobuf_c_message_descriptor_get_field_by_name( | |
1620 | &foo__test_field_flags__descriptor, "no_flags1"); | |
1972 | const ProtobufCMessageDescriptor *desc = &foo__test_field_flags__descriptor; | |
1973 | ||
1974 | f = protobuf_c_message_descriptor_get_field_by_name(desc, "no_flags1"); | |
1621 | 1975 | assert(f != NULL); |
1622 | 1976 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_PACKED)); |
1623 | 1977 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_DEPRECATED)); |
1624 | 1978 | |
1625 | f = protobuf_c_message_descriptor_get_field_by_name( | |
1626 | &foo__test_field_flags__descriptor, "no_flags2"); | |
1979 | f = protobuf_c_message_descriptor_get_field_by_name(desc, "no_flags2"); | |
1627 | 1980 | assert(f != NULL); |
1628 | 1981 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_PACKED)); |
1629 | 1982 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_DEPRECATED)); |
1630 | 1983 | |
1631 | f = protobuf_c_message_descriptor_get_field_by_name( | |
1632 | &foo__test_field_flags__descriptor, "no_flags3"); | |
1984 | f = protobuf_c_message_descriptor_get_field_by_name(desc, "no_flags3"); | |
1633 | 1985 | assert(f != NULL); |
1634 | 1986 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_PACKED)); |
1635 | 1987 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_DEPRECATED)); |
1636 | 1988 | |
1637 | f = protobuf_c_message_descriptor_get_field_by_name( | |
1638 | &foo__test_field_flags__descriptor, "packed"); | |
1989 | f = protobuf_c_message_descriptor_get_field_by_name(desc, "packed"); | |
1639 | 1990 | assert(f != NULL); |
1640 | 1991 | assert((f->flags & PROTOBUF_C_FIELD_FLAG_PACKED)); |
1641 | 1992 | assert(!(f->flags & PROTOBUF_C_FIELD_FLAG_DEPRECATED)); |
1642 | 1993 | |
1643 | f = protobuf_c_message_descriptor_get_field_by_name( | |
1644 | &foo__test_field_flags__descriptor, "packed_deprecated"); | |
1994 | f = protobuf_c_message_descriptor_get_field_by_name(desc, "packed_deprecated"); | |
1645 | 1995 | assert(f != NULL); |
1646 | 1996 | assert((f->flags & PROTOBUF_C_FIELD_FLAG_PACKED)); |
1647 | 1997 | assert((f->flags & PROTOBUF_C_FIELD_FLAG_DEPRECATED)); |
1671 | 2021 | /* test with required_string not set */ |
1672 | 2022 | m.required_string = NULL; |
1673 | 2023 | m.required_msg = &sm; |
1674 | m.required_bytes.data = str; m.required_bytes.len = 1; | |
2024 | m.required_bytes.data = (uint8_t *)str; m.required_bytes.len = 1; | |
1675 | 2025 | assert(0 == protobuf_c_message_check(&m.base)); |
1676 | 2026 | |
1677 | 2027 | /* test with required_msg not set */ |
1685 | 2035 | assert(0 == protobuf_c_message_check(&m.base)); |
1686 | 2036 | |
1687 | 2037 | /* test with all required fields set */ |
1688 | m.required_bytes.data = str; m.required_bytes.len = 1; | |
2038 | m.required_bytes.data = (uint8_t *)str; m.required_bytes.len = 1; | |
1689 | 2039 | assert(1 == protobuf_c_message_check(&m.base)); |
1690 | 2040 | |
1691 | 2041 | /* test with incomplete required submessage */ |
1710 | 2060 | assert(0 == protobuf_c_message_check(&m.base)); |
1711 | 2061 | |
1712 | 2062 | /* test with correct optional bytes */ |
1713 | m.optional_bytes.data = str; m.optional_bytes.len = 1; | |
2063 | m.optional_bytes.data = (uint8_t *)str; m.optional_bytes.len = 1; | |
1714 | 2064 | assert(1 == protobuf_c_message_check(&m.base)); |
1715 | 2065 | |
1716 | 2066 | /* test with repeated strings set incorrectly */ |
1745 | 2095 | assert(0 == protobuf_c_message_check(&m.base)); |
1746 | 2096 | |
1747 | 2097 | /* test with repeated bytes set correctly */ |
1748 | bd.data = str; | |
2098 | bd.data = (uint8_t *)str; | |
1749 | 2099 | assert(1 == protobuf_c_message_check(&m.base)); |
1750 | 2100 | |
1751 | 2101 | /* test with empty repeated string vector */ |
1820 | 2170 | { "test optional string", test_optional_string }, |
1821 | 2171 | { "test optional bytes", test_optional_bytes }, |
1822 | 2172 | { "test optional SubMess", test_optional_SubMess }, |
2173 | ||
2174 | { "test empty oneof" ,test_empty_oneof }, | |
2175 | { "test oneof int32", test_oneof_int32 }, | |
2176 | { "test oneof sint32", test_oneof_sint32 }, | |
2177 | { "test oneof sfixed32", test_oneof_sfixed32 }, | |
2178 | { "test oneof int64", test_oneof_int64 }, | |
2179 | { "test oneof sint64", test_oneof_sint64 }, | |
2180 | { "test oneof sfixed64", test_oneof_sfixed64 }, | |
2181 | { "test oneof uint32", test_oneof_uint32 }, | |
2182 | { "test oneof fixed32", test_oneof_fixed32 }, | |
2183 | { "test oneof uint64", test_oneof_uint64 }, | |
2184 | { "test oneof fixed64", test_oneof_fixed64 }, | |
2185 | { "test oneof float", test_oneof_float }, | |
2186 | { "test oneof double", test_oneof_double }, | |
2187 | { "test oneof bool", test_oneof_bool }, | |
2188 | { "test oneof TestEnumSmall", test_oneof_TestEnumSmall }, | |
2189 | { "test oneof TestEnum", test_oneof_TestEnum }, | |
2190 | { "test oneof string", test_oneof_string }, | |
2191 | { "test oneof bytes", test_oneof_bytes }, | |
2192 | { "test oneof SubMess", test_oneof_SubMess }, | |
2193 | { "test merged oneof unpack", test_oneof_merge }, | |
1823 | 2194 | |
1824 | 2195 | { "test empty repeated" ,test_empty_repeated }, |
1825 | 2196 | { "test repeated int32" ,test_repeated_int32 }, |
1868 | 2239 | { "test optional lowercase enum default value", test_optional_lowercase_enum_default_value }, |
1869 | 2240 | |
1870 | 2241 | { "test field merge", test_field_merge }, |
2242 | { "test submessage merge", test_submessage_merge }, | |
1871 | 2243 | |
1872 | 2244 | { "test free unpacked", test_alloc_free_all }, |
1873 | 2245 | { "test alloc failure", test_alloc_fail }, |
2246 | ||
2247 | { "test free unpacked input check for null message", test_free_unpacked_input_check_for_null_message }, | |
2248 | { "test free unpacked input check for null repeated field", test_free_unpacked_input_check_for_null_repeated_field }, | |
1874 | 2249 | |
1875 | 2250 | { "test required_fields_bitmap", test_required_fields_bitmap }, |
1876 | 2251 |
129 | 129 | optional string test_string = 16; |
130 | 130 | optional bytes test_bytes = 17; |
131 | 131 | optional SubMess test_message = 18; |
132 | } | |
133 | ||
134 | message TestMessOneof { | |
135 | oneof test_oneof { | |
136 | int32 test_int32 = 1; | |
137 | sint32 test_sint32 = 2; | |
138 | sfixed32 test_sfixed32 = 3; | |
139 | int64 test_int64 = 4; | |
140 | sint64 test_sint64 = 5; | |
141 | sfixed64 test_sfixed64 = 6; | |
142 | uint32 test_uint32 = 7; | |
143 | fixed32 test_fixed32 = 8; | |
144 | uint64 test_uint64 = 9; | |
145 | fixed64 test_fixed64 = 10; | |
146 | float test_float = 11; | |
147 | double test_double = 12; | |
148 | bool test_boolean = 13; | |
149 | TestEnumSmall test_enum_small = 14; | |
150 | TestEnum test_enum = 15; | |
151 | string test_string = 16; | |
152 | bytes test_bytes = 17; | |
153 | SubMess test_message = 18; | |
154 | } | |
155 | optional int32 opt_int = 19; | |
132 | 156 | } |
133 | 157 | |
134 | 158 | message TestMessRequiredInt32 { |
378 | 402 | optional bytes optional_bytes = 9; |
379 | 403 | } |
380 | 404 | |
405 | message TestMessSubMess { | |
406 | required TestMess rep_mess = 1; | |
407 | required TestMessOptional opt_mess = 2; | |
408 | required TestMessOneof oneof_mess = 3; | |
409 | required SubMess req_mess = 4; | |
410 | required DefaultOptionalValues def_mess = 5; | |
411 | } |