From dfb6e300fab0aec0093eeed4e7416795091f6e5f Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Sun, 21 Mar 2021 14:57:27 -0700 Subject: [PATCH] protoc-c: add const_strings option Keep default as false to preserve backwards compatibility. Fixes #239 --- protobuf-c/protobuf-c.proto | 3 +++ protoc-c/c_string_field.cc | 9 +++++++++ t/generated-code2/common-test-arrays.h | 8 ++++---- t/generated-code2/test-generated-code2.c | 6 +++--- t/test-full.proto | 2 ++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/protobuf-c/protobuf-c.proto b/protobuf-c/protobuf-c.proto index 6cb73d7..644f851 100644 --- a/protobuf-c/protobuf-c.proto +++ b/protobuf-c/protobuf-c.proto @@ -45,6 +45,9 @@ message ProtobufCFileOptions { // Generate helper init message functions? optional bool gen_init_helpers = 3 [default = true]; + + // Use const char * instead of char * for string fields + optional bool const_strings = 4 [default = false]; } extend google.protobuf.FileOptions { diff --git a/protoc-c/c_string_field.cc b/protoc-c/c_string_field.cc index c8ad4eb..4fb42f7 100644 --- a/protoc-c/c_string_field.cc +++ b/protoc-c/c_string_field.cc @@ -93,13 +93,19 @@ StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator::GenerateStructMembers(io::Printer* printer) const { + const ProtobufCFileOptions opt = descriptor_->file()->options().GetExtension(pb_c_file); + switch (descriptor_->label()) { case FieldDescriptor::LABEL_REQUIRED: case FieldDescriptor::LABEL_OPTIONAL: + if (opt.const_strings()) + printer->Print(variables_, "const "); printer->Print(variables_, "char *$name$$deprecated$;\n"); break; case FieldDescriptor::LABEL_REPEATED: printer->Print(variables_, "size_t n_$name$$deprecated$;\n"); + if (opt.const_strings()) + printer->Print(variables_, "const "); printer->Print(variables_, "char **$name$$deprecated$;\n"); break; } @@ -123,10 +129,13 @@ std::string StringFieldGenerator::GetDefaultValue(void) const void StringFieldGenerator::GenerateStaticInit(io::Printer* printer) const { std::map vars; + const ProtobufCFileOptions opt = descriptor_->file()->options().GetExtension(pb_c_file); if (descriptor_->has_default_value()) { vars["default"] = GetDefaultValue(); } else if (FieldSyntax(descriptor_) == 2) { vars["default"] = "NULL"; + } else if (opt.const_strings()) { + vars["default"] = "(const char *)protobuf_c_empty_string"; } else { vars["default"] = "(char *)protobuf_c_empty_string"; } diff --git a/t/generated-code2/common-test-arrays.h b/t/generated-code2/common-test-arrays.h index 1535d38..c5e3722 100644 --- a/t/generated-code2/common-test-arrays.h +++ b/t/generated-code2/common-test-arrays.h @@ -56,7 +56,7 @@ TEST_ENUM_TYPE_NAME enum_random[] = { T(0), T(2097152), T(268435455), T(127), T(16383), T(16384) }; #undef T -char *repeated_strings_0[] = { (char*)"onestring" }; -char *repeated_strings_1[] = { (char*)"two", (char*)"string" }; -char *repeated_strings_2[] = { (char*)"many", (char*)"tiny", (char*)"little", (char*)"strings", (char*)"should", (char*)"be", (char*)"handled" }; -char *repeated_strings_3[] = { (char*)"one very long strings XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }; +const char *repeated_strings_0[] = { "onestring" }; +const char *repeated_strings_1[] = { "two", "string" }; +const char *repeated_strings_2[] = { "many", "tiny", "little", "strings", "should", "be", "handled" }; +const char *repeated_strings_3[] = { "one very long strings XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }; diff --git a/t/generated-code2/test-generated-code2.c b/t/generated-code2/test-generated-code2.c index 2aa3a9c..15f5dc8 100755 --- a/t/generated-code2/test-generated-code2.c +++ b/t/generated-code2/test-generated-code2.c @@ -1274,7 +1274,7 @@ static void test_repeated_string (void) { #define DO_TEST(static_array, example_packed_data) \ - DO_TEST_REPEATED(test_string, (char **), \ + DO_TEST_REPEATED(test_string, (const char **), \ static_array, example_packed_data, \ STRING_EQUALS) @@ -2109,8 +2109,8 @@ test_message_check(void) Foo__TestMessageCheck__SubMessage sm = FOO__TEST_MESSAGE_CHECK__SUB_MESSAGE__INIT; Foo__TestMessageCheck__SubMessage sm2 = FOO__TEST_MESSAGE_CHECK__SUB_MESSAGE__INIT; Foo__TestMessageCheck m = FOO__TEST_MESSAGE_CHECK__INIT; - char *null = NULL; - char *str = ""; + const char *null = NULL; + const char *str = ""; Foo__TestMessageCheck__SubMessage *sm_p; ProtobufCBinaryData bd; diff --git a/t/test-full.proto b/t/test-full.proto index 3481e97..e723200 100644 --- a/t/test-full.proto +++ b/t/test-full.proto @@ -2,6 +2,8 @@ package foo; import "protobuf-c/protobuf-c.proto"; +option (pb_c_file).const_strings = true; + message SubMess { required int32 test = 4;