Skip to content

Commit

Permalink
clear_<field>has_<field> を追加
Browse files Browse the repository at this point in the history
  • Loading branch information
melpon committed Jan 19, 2024
1 parent 75ef89d commit ef24a0c
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 66 deletions.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@

## develop

## 0.12.0 (2024-01-19)

- [ADD] optional フィールドに `has_<field>` 関数を追加
- @melpon
- [ADD] oneof, optional フィールドに `clear_<field>` 関数を追加
- @melpon

## 0.11.0 (2024-01-19)

- [CHANGE] oneof の enum 値を `<FIELD_NAME>_CASE_NOT_SET` から `NOT_SET` に変更
Expand Down
38 changes: 38 additions & 0 deletions cmd/protoc-gen-jsonif-c/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,19 @@ func genDescriptor(desc *descriptorpb.DescriptorProto, pkg *string, parents []*d
}
cpp.Typedefs.P("")

// optional has_<field> declarations
// optional clear_<field> declarations
// oneof clear_<field> declarations
for _, field := range desc.Field {
fieldName := internal.ToSnakeCase(*field.Name)
if oneof := field.OneofIndex; oneof != nil {
if field.Proto3Optional != nil && *field.Proto3Optional {
cpp.Typedefs.P("bool %s_has_%s(const %s* v);", qName, fieldName, qName)
}
cpp.Typedefs.P("void %s_clear_%s(%s* v);", qName, fieldName, qName)
}
}

// oneof clear_<case> declarations
for _, oneof := range desc.OneofDecl {
fieldName := internal.ToSnakeCase(*oneof.Name) + "_case"
Expand Down Expand Up @@ -760,6 +773,31 @@ func genDescriptor(desc *descriptorpb.DescriptorProto, pkg *string, parents []*d
}
}

// optional has_<field>
// optional clear_<field>
// oneof clear_<field>
for _, field := range desc.Field {
fieldName := internal.ToSnakeCase(*field.Name)
if oneof := field.OneofIndex; oneof != nil {
oneofTypeName := internal.ToUpperCamel(*desc.OneofDecl[*oneof].Name) + "Case"
oneofFieldName := internal.ToSnakeCase(*desc.OneofDecl[*oneof].Name) + "_case"
oneofQName, err := toQualifiedName(oneofTypeName, pkg, append(parents, desc))
if err != nil {
return err
}
if field.Proto3Optional != nil && *field.Proto3Optional {
cpp.CImpl.PI("bool %s_has_%s(const %s* v) {", qName, fieldName, qName)
cpp.CImpl.P("return v->%s == %s_k%s;", oneofFieldName, oneofQName, internal.ToUpperCamel(*field.Name))
cpp.CImpl.PD("}")
}
cpp.CImpl.PI("void %s_clear_%s(%s* v) {", qName, fieldName, qName)
cpp.CImpl.PI("if (v->%s == %s_k%s) {", oneofFieldName, oneofQName, internal.ToUpperCamel(*field.Name))
cpp.CImpl.P("%s_clear_%s(v);", qName, oneofFieldName)
cpp.CImpl.PD("}")
cpp.CImpl.PD("}")
}
}

// oneof clear_<case>
for i, oneof := range desc.OneofDecl {
fieldName := internal.ToSnakeCase(*oneof.Name) + "_case"
Expand Down
10 changes: 10 additions & 0 deletions cmd/protoc-gen-jsonif-cpp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,16 @@ func genDescriptor(desc *descriptorpb.DescriptorProto, pkg *string, parents []*d
cpp.Typedefs.P("%s = %s::k%s;", oneofFieldName, oneofTypeName, internal.ToUpperCamel(fieldName))
cpp.Typedefs.P("this->%s = %s;", fieldName, fieldName)
cpp.Typedefs.PD("}")
if field.Proto3Optional != nil && *field.Proto3Optional {
cpp.Typedefs.PI("bool has_%s() const {", fieldName)
cpp.Typedefs.P("return %s == %s::k%s;", oneofFieldName, oneofTypeName, internal.ToUpperCamel(fieldName))
cpp.Typedefs.PD("}")
}
cpp.Typedefs.PI("void clear_%s() {", fieldName)
cpp.Typedefs.PI("if (%s == %s::k%s) {", oneofFieldName, oneofTypeName, internal.ToUpperCamel(fieldName))
cpp.Typedefs.P("clear_%s();", oneofFieldName)
cpp.Typedefs.PD("}")
cpp.Typedefs.PD("}")
}
}

Expand Down
11 changes: 11 additions & 0 deletions cmd/protoc-gen-jsonif-unity/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,17 @@ func genDescriptor(desc *descriptorpb.DescriptorProto, pkg *string, parents []*d
u.Typedefs.P("%s = %s.k%s;", oneofFieldName, oneofTypeName, internal.ToUpperCamel(fieldName))
u.Typedefs.P("this.%s = %s;", fieldName, fieldName)
u.Typedefs.PD("}")
u.Typedefs.P("public bool Has%s()", internal.ToUpperCamel(fieldName))
u.Typedefs.PI("{")
u.Typedefs.P("return %s == %s.k%s;", oneofFieldName, oneofTypeName, internal.ToUpperCamel(fieldName))
u.Typedefs.PD("}")
u.Typedefs.P("public void Clear%s()", internal.ToUpperCamel(fieldName))
u.Typedefs.PI("{")
u.Typedefs.P("if (%s == %s.k%s)", oneofFieldName, oneofTypeName, internal.ToUpperCamel(fieldName))
u.Typedefs.PI("{")
u.Typedefs.P("Clear%s();", oneofTypeName)
u.Typedefs.PD("}")
u.Typedefs.PD("}")
}
}

Expand Down
46 changes: 28 additions & 18 deletions test/c/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,22 @@ void test_message() {
message_Person_init(&a);
assert(a.name == NULL);
assert(a.name_len == 0);
assert(a.flag == false);
message_Person b;
message_Person_init(&b);
TEST_IDENTIFY(message_Person, &a, &b);
assert(b.name == NULL);
assert(b.name_len == 0);
assert(a.flag == false);

message_Person_set_name(&b, "foo");
message_Person_set_flag(&b, true);
message_Person c;
message_Person_init(&c);
TEST_IDENTIFY(message_Person, &b, &c);
assert(strcmp(c.name, "foo") == 0);
assert(c.name_len == 3);
assert(c.flag == true);

message_Person_destroy(&a);
message_Person_destroy(&b);
Expand Down Expand Up @@ -217,50 +221,56 @@ void test_optional() {
optional_Test_init(&a);
optional_Test b;
optional_Test_init(&b);
assert(a._a_case == optional_Test_ACase_NOT_SET);
assert(!optional_Test_has_a(&a));
assert(!optional_Test_has_b(&a));
assert(!optional_Test_has_c(&a));
assert(!optional_Test_has_d(&a));
TEST_IDENTIFY(optional_Test, &a, &b);
assert(b._a_case == optional_Test_ACase_NOT_SET);
assert(!optional_Test_has_a(&a));
assert(!optional_Test_has_b(&a));
assert(!optional_Test_has_c(&a));
assert(!optional_Test_has_d(&a));

optional_Test_set_a(&a, 1);
assert(a._a_case == optional_Test_ACase_kA);
assert(optional_Test_has_a(&a));
assert(a.a == 1);
TEST_IDENTIFY(optional_Test, &a, &b);
assert(b._a_case == optional_Test_ACase_kA);
assert(optional_Test_has_a(&b));
assert(b.a == 1);

optional_Test_set_b(&a, "foo");
assert(a._b_case == optional_Test_BCase_kB);
assert(optional_Test_has_b(&a));
assert(a.b_len == 3 && strcmp(a.b, "foo") == 0);
TEST_IDENTIFY(optional_Test, &a, &b);
assert(b._b_case == optional_Test_BCase_kB);
assert(optional_Test_has_b(&b));
assert(b.b_len == 3 && strcmp(b.b, "foo") == 0);

optional_Test_set_c(&a, optional_BAR);
assert(a._c_case == optional_Test_CCase_kC);
assert(optional_Test_has_c(&a));
assert(a.c == optional_BAR);
TEST_IDENTIFY(optional_Test, &a, &b);
assert(b._c_case == optional_Test_CCase_kC);
assert(optional_Test_has_c(&b));
assert(b.c == optional_BAR);

optional_Message m;
optional_Message_init(&m);
optional_Message_set_name(&m, "bar");
optional_Test_set_d(&a, &m);
optional_Message_destroy(&m);
assert(a._d_case == optional_Test_DCase_kD);
assert(optional_Test_has_d(&a));
assert(a.d.name_len == 3 && strcmp(a.d.name, "bar") == 0);
TEST_IDENTIFY(optional_Test, &a, &b);
assert(b._d_case == optional_Test_DCase_kD);
assert(optional_Test_has_d(&b));
assert(b.d.name_len == 3 && strcmp(b.d.name, "bar") == 0);

optional_Test_clear__a_case(&a);
assert(a._a_case == optional_Test_ACase_NOT_SET);
optional_Test_clear__b_case(&a);
assert(a._b_case == optional_Test_BCase_NOT_SET);
optional_Test_clear__c_case(&a);
assert(a._c_case == optional_Test_CCase_NOT_SET);
optional_Test_clear__d_case(&a);
assert(a._d_case == optional_Test_DCase_NOT_SET);
optional_Test_clear_a(&a);
assert(!optional_Test_has_a(&a));
optional_Test_clear_b(&a);
assert(!optional_Test_has_b(&a));
optional_Test_clear_c(&a);
assert(!optional_Test_has_c(&a));
optional_Test_clear_d(&a);
assert(!optional_Test_has_d(&a));

optional_Test_destroy(&a);
optional_Test_destroy(&b);
Expand Down
59 changes: 35 additions & 24 deletions test/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ void test_empty() {
void test_message() {
message::Person a;
assert(a.name == "");
assert(a.flag == false);
a = identify(a);
assert(a.name == "");
assert(a.flag == false);

a.name = "foo";
a.flag = true;
a = identify(a);
assert(a.name == "foo");
assert(a.flag == true);
}

void test_enumpb() {
Expand Down Expand Up @@ -135,58 +139,65 @@ void test_oneof() {
assert(a.test_oneof_case == oneof::Test::TestOneofCase::kD);
assert(a.d.name == "bar");

a.clear_c();
assert(a.d.name == "bar");
assert(a.test_oneof_case == oneof::Test::TestOneofCase::kD);
a.clear_d();
assert(a.test_oneof_case == oneof::Test::TestOneofCase::NOT_SET);

a.set_a(10);
a.clear_test_oneof_case();
assert(a.test_oneof_case == oneof::Test::TestOneofCase::NOT_SET);
}

void test_optional() {
optional::Test a;
assert(a._a_case == optional::Test::ACase::NOT_SET);
assert(a._b_case == optional::Test::BCase::NOT_SET);
assert(a._c_case == optional::Test::CCase::NOT_SET);
assert(a._d_case == optional::Test::DCase::NOT_SET);
assert(!a.has_a());
assert(!a.has_b());
assert(!a.has_c());
assert(!a.has_d());
a = identify(a);
assert(a._a_case == optional::Test::ACase::NOT_SET);
assert(a._b_case == optional::Test::BCase::NOT_SET);
assert(a._c_case == optional::Test::CCase::NOT_SET);
assert(a._d_case == optional::Test::DCase::NOT_SET);
assert(!a.has_a());
assert(!a.has_b());
assert(!a.has_c());
assert(!a.has_d());

a.set_a(1);
assert(a._a_case == optional::Test::ACase::kA);
assert(a.has_a());
assert(a.a == 1);
a = identify(a);
assert(a._a_case == optional::Test::ACase::kA);
assert(a.has_a());
assert(a.a == 1);

a.set_b("foo");
assert(a._b_case == optional::Test::BCase::kB);
assert(a.has_b());
assert(a.b == "foo");
a = identify(a);
assert(a._b_case == optional::Test::BCase::kB);
assert(a.has_b());
assert(a.b == "foo");

a.set_c(optional::BAR);
assert(a._c_case == optional::Test::CCase::kC);
assert(a.has_c());
assert(a.c == optional::BAR);
a = identify(a);
assert(a._c_case == optional::Test::CCase::kC);
assert(a.has_c());
assert(a.c == optional::BAR);

a.set_d(optional::Message{"bar"});
assert(a._d_case == optional::Test::DCase::kD);
assert(a.has_d());
assert(a.d.name == "bar");
a = identify(a);
assert(a._d_case == optional::Test::DCase::kD);
assert(a.has_d());
assert(a.d.name == "bar");

a.clear__a_case();
assert(a._a_case == optional::Test::ACase::NOT_SET);
a.clear__b_case();
assert(a._b_case == optional::Test::BCase::NOT_SET);
a.clear__c_case();
assert(a._c_case == optional::Test::CCase::NOT_SET);
a.clear__d_case();
assert(a._d_case == optional::Test::DCase::NOT_SET);
a.clear_a();
assert(!a.has_a());
a.clear_b();
assert(!a.has_b());
a.clear_c();
assert(!a.has_c());
a.clear_d();
assert(!a.has_d());
}

void test_importing() {
Expand Down
1 change: 1 addition & 0 deletions test/proto/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ package message;

message Person {
string name = 1;
bool flag = 2;
}
Loading

0 comments on commit ef24a0c

Please sign in to comment.