mirror of
https://github.com/protobuf-c/protobuf-c.git
synced 2024-12-26 21:04:23 +08:00
proto3: make strings default to "" instead of NULL
The spec talks about "empty string" and other languages like C# return a zero length string and not null. This is useful because when moving from proto2's "required string" to a proto3's plain string we will be guaranteed that we never get a null pointer. The tradeoff is adding a special case to the library but avoiding a lot of null checks in the calling code. The current code is already special casing "" in pack_string.
This commit is contained in:
parent
a8921fe7dc
commit
2a46af4278
@ -21,3 +21,8 @@ global:
|
|||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LIBPROTOBUF_C_1.3.0 {
|
||||||
|
global:
|
||||||
|
protobuf_c_empty_string;
|
||||||
|
} LIBPROTOBUF_C_1.0.0;
|
||||||
|
@ -84,6 +84,8 @@
|
|||||||
# define PROTOBUF_C_UNPACK_ERROR(...)
|
# define PROTOBUF_C_UNPACK_ERROR(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const char protobuf_c_empty_string[] = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal `ProtobufCMessage` manipulation macro.
|
* Internal `ProtobufCMessage` manipulation macro.
|
||||||
*
|
*
|
||||||
@ -554,6 +556,9 @@ field_is_zeroish(const ProtobufCFieldDescriptor *field,
|
|||||||
ret = (0 == *(const double *) member);
|
ret = (0 == *(const double *) member);
|
||||||
break;
|
break;
|
||||||
case PROTOBUF_C_TYPE_STRING:
|
case PROTOBUF_C_TYPE_STRING:
|
||||||
|
ret = (NULL == *(const char * const *) member) ||
|
||||||
|
('\0' == **(const char * const *) member);
|
||||||
|
break;
|
||||||
case PROTOBUF_C_TYPE_BYTES:
|
case PROTOBUF_C_TYPE_BYTES:
|
||||||
case PROTOBUF_C_TYPE_MESSAGE:
|
case PROTOBUF_C_TYPE_MESSAGE:
|
||||||
ret = (NULL == *(const void * const *) member);
|
ret = (NULL == *(const void * const *) member);
|
||||||
|
@ -237,6 +237,9 @@ PROTOBUF_C__BEGIN_DECLS
|
|||||||
#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9
|
#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9
|
||||||
#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af
|
#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af
|
||||||
|
|
||||||
|
/* Empty string used for initializers */
|
||||||
|
extern const char protobuf_c_empty_string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \defgroup api Public API
|
* \defgroup api Public API
|
||||||
*
|
*
|
||||||
|
@ -129,6 +129,9 @@ void FieldGenerator::GenerateDescriptorInitializerGeneric(io::Printer* printer,
|
|||||||
variables["default_value"] = string("&")
|
variables["default_value"] = string("&")
|
||||||
+ FullNameToLower(descriptor_->full_name())
|
+ FullNameToLower(descriptor_->full_name())
|
||||||
+ "__default_value";
|
+ "__default_value";
|
||||||
|
} else if (FieldSyntax(descriptor_) == 3 &&
|
||||||
|
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||||
|
variables["default_value"] = "&protobuf_c_empty_string";
|
||||||
} else {
|
} else {
|
||||||
variables["default_value"] = "NULL";
|
variables["default_value"] = "NULL";
|
||||||
}
|
}
|
||||||
|
@ -125,8 +125,10 @@ void StringFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
|||||||
std::map<string, string> vars;
|
std::map<string, string> vars;
|
||||||
if (descriptor_->has_default_value()) {
|
if (descriptor_->has_default_value()) {
|
||||||
vars["default"] = GetDefaultValue();
|
vars["default"] = GetDefaultValue();
|
||||||
} else {
|
} else if (FieldSyntax(descriptor_) == 2) {
|
||||||
vars["default"] = "NULL";
|
vars["default"] = "NULL";
|
||||||
|
} else {
|
||||||
|
vars["default"] = "(char *)protobuf_c_empty_string";
|
||||||
}
|
}
|
||||||
switch (descriptor_->label()) {
|
switch (descriptor_->label()) {
|
||||||
case FieldDescriptor::LABEL_REQUIRED:
|
case FieldDescriptor::LABEL_REQUIRED:
|
||||||
|
@ -51,6 +51,11 @@ int main(void)
|
|||||||
person2 = foo__person__unpack (NULL, size, packed);
|
person2 = foo__person__unpack (NULL, size, packed);
|
||||||
assert (person2 != NULL);
|
assert (person2 != NULL);
|
||||||
assert (person2->id == 42);
|
assert (person2->id == 42);
|
||||||
|
#ifndef PROTO3
|
||||||
|
assert (person2->email == NULL);
|
||||||
|
#else
|
||||||
|
assert (strcmp (person2->email, "") == 0);
|
||||||
|
#endif
|
||||||
assert (strcmp (person2->name, "dave b") == 0);
|
assert (strcmp (person2->name, "dave b") == 0);
|
||||||
assert (person2->n_phone == 1);
|
assert (person2->n_phone == 1);
|
||||||
assert (strcmp (person2->phone[0]->number, "1234") == 0);
|
assert (strcmp (person2->phone[0]->number, "1234") == 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user