提交 d8cea7f7 编写于 作者: H hjchen2

revert batch size and protobuf-c

上级 69a0ecad
...@@ -33,11 +33,14 @@ namespace paddle_mobile { ...@@ -33,11 +33,14 @@ namespace paddle_mobile {
using framework::Variable; using framework::Variable;
template <typename Dtype, Precision P> template <typename Dtype, Precision P>
Executor<Dtype, P>::Executor(const framework::Program<Dtype> p, Executor<Dtype, P>::Executor(const framework::Program<Dtype> p, int batch_size,
const bool use_optimize, const bool loddable) const bool use_optimize, const bool loddable)
: program_(p), use_optimize_(use_optimize), loddable_(loddable) { : program_(p),
batch_size_(batch_size),
use_optimize_(use_optimize),
loddable_(loddable) {
Variable *variable_ptr = program_.scope->Var("batch_size"); Variable *variable_ptr = program_.scope->Var("batch_size");
variable_ptr->SetValue<int>(1); variable_ptr->SetValue<int>(batch_size);
to_predict_program_ = to_predict_program_ =
use_optimize_ ? program_.optimizeProgram : program_.originProgram; use_optimize_ ? program_.optimizeProgram : program_.originProgram;
PADDLE_MOBILE_ENFORCE(to_predict_program_ != nullptr, PADDLE_MOBILE_ENFORCE(to_predict_program_ != nullptr,
......
...@@ -35,7 +35,7 @@ class Executor { ...@@ -35,7 +35,7 @@ class Executor {
// @param program program converted from proto program in PaddlePaddle // @param program program converted from proto program in PaddlePaddle
// @param use_optimize bool whether use operator fusion to speed up or not // @param use_optimize bool whether use operator fusion to speed up or not
// @param loddable bool // @param loddable bool
Executor(const framework::Program<Dtype> program, Executor(const framework::Program<Dtype> program, int batch_size = 1,
const bool use_optimize = true, const bool loddable = false); const bool use_optimize = true, const bool loddable = false);
// predict with tensor input // predict with tensor input
...@@ -81,6 +81,7 @@ class Executor { ...@@ -81,6 +81,7 @@ class Executor {
framework::LoDTensor *tensor); framework::LoDTensor *tensor);
framework::Program<Dtype> program_; framework::Program<Dtype> program_;
int batch_size_ = 1;
std::shared_ptr<framework::ProgramDesc> to_predict_program_; std::shared_ptr<framework::ProgramDesc> to_predict_program_;
std::map<framework::BlockDesc, std::map<framework::BlockDesc,
std::vector<std::shared_ptr<framework::OperatorBase<Dtype>>>> std::vector<std::shared_ptr<framework::OperatorBase<Dtype>>>>
......
...@@ -25,7 +25,8 @@ void PaddleMobile<Dtype, P>::SetThreadNum(int num) { ...@@ -25,7 +25,8 @@ void PaddleMobile<Dtype, P>::SetThreadNum(int num) {
template <typename Dtype, Precision P> template <typename Dtype, Precision P>
bool PaddleMobile<Dtype, P>::Load(const std::string &dirname, bool optimize, bool PaddleMobile<Dtype, P>::Load(const std::string &dirname, bool optimize,
bool quantification, bool loddable) { bool quantification, int batch_size,
bool loddable) {
if (loader_.get() == nullptr) { if (loader_.get() == nullptr) {
loader_ = std::make_shared<Loader<Dtype, P>>(); loader_ = std::make_shared<Loader<Dtype, P>>();
} else { } else {
...@@ -34,7 +35,8 @@ bool PaddleMobile<Dtype, P>::Load(const std::string &dirname, bool optimize, ...@@ -34,7 +35,8 @@ bool PaddleMobile<Dtype, P>::Load(const std::string &dirname, bool optimize,
if (executor_.get() == nullptr) { if (executor_.get() == nullptr) {
executor_ = std::make_shared<Executor<Dtype, P>>( executor_ = std::make_shared<Executor<Dtype, P>>(
loader_->Load(dirname, optimize, quantification), optimize, loddable); loader_->Load(dirname, optimize, quantification), batch_size, optimize,
loddable);
} else { } else {
LOG(kLOG_INFO) << "executor inited"; LOG(kLOG_INFO) << "executor inited";
} }
...@@ -45,7 +47,8 @@ bool PaddleMobile<Dtype, P>::Load(const std::string &dirname, bool optimize, ...@@ -45,7 +47,8 @@ bool PaddleMobile<Dtype, P>::Load(const std::string &dirname, bool optimize,
template <typename Dtype, Precision P> template <typename Dtype, Precision P>
bool PaddleMobile<Dtype, P>::Load(const std::string &model_path, bool PaddleMobile<Dtype, P>::Load(const std::string &model_path,
const std::string &para_path, bool optimize, const std::string &para_path, bool optimize,
bool quantification, bool loddable) { bool quantification, int batch_size,
bool loddable) {
if (loader_.get() == nullptr) { if (loader_.get() == nullptr) {
loader_ = std::make_shared<Loader<Dtype, P>>(); loader_ = std::make_shared<Loader<Dtype, P>>();
} else { } else {
...@@ -55,7 +58,7 @@ bool PaddleMobile<Dtype, P>::Load(const std::string &model_path, ...@@ -55,7 +58,7 @@ bool PaddleMobile<Dtype, P>::Load(const std::string &model_path,
if (executor_.get() == nullptr) { if (executor_.get() == nullptr) {
executor_ = std::make_shared<Executor<Dtype, P>>( executor_ = std::make_shared<Executor<Dtype, P>>(
loader_->Load(model_path, para_path, optimize, quantification), loader_->Load(model_path, para_path, optimize, quantification),
optimize, loddable); batch_size, optimize, loddable);
} else { } else {
LOG(kLOG_INFO) << "executor inited"; LOG(kLOG_INFO) << "executor inited";
} }
...@@ -67,6 +70,7 @@ template <typename Dtype, Precision P> ...@@ -67,6 +70,7 @@ template <typename Dtype, Precision P>
bool PaddleMobile<Dtype, P>::LoadCombinedMemory( bool PaddleMobile<Dtype, P>::LoadCombinedMemory(
size_t model_len, const uint8_t *model_buf, size_t combined_params_len, size_t model_len, const uint8_t *model_buf, size_t combined_params_len,
const uint8_t *combined_params_buf) { const uint8_t *combined_params_buf) {
int batch_size = 1;
bool optimise = true; bool optimise = true;
bool quantification = false; bool quantification = false;
...@@ -81,7 +85,7 @@ bool PaddleMobile<Dtype, P>::LoadCombinedMemory( ...@@ -81,7 +85,7 @@ bool PaddleMobile<Dtype, P>::LoadCombinedMemory(
loader_->LoadCombinedMemory(model_len, model_buf, combined_params_len, loader_->LoadCombinedMemory(model_len, model_buf, combined_params_len,
combined_params_buf, optimise, combined_params_buf, optimise,
quantification), quantification),
optimise); batch_size, optimise);
} else { } else {
LOG(kLOG_INFO) << "executor inited"; LOG(kLOG_INFO) << "executor inited";
} }
......
...@@ -36,11 +36,12 @@ class PaddleMobile { ...@@ -36,11 +36,12 @@ class PaddleMobile {
public: public:
PaddleMobile() {} PaddleMobile() {}
bool Load(const std::string &dirname, bool optimize = false, bool Load(const std::string &dirname, bool optimize = false,
bool quantification = false, bool loddable = false); bool quantification = false, int batch_size = 1,
bool loddable = false);
bool Load(const std::string &model_path, const std::string &para_path, bool Load(const std::string &model_path, const std::string &para_path,
bool optimize = false, bool quantification = false, bool optimize = false, bool quantification = false,
bool loddable = false); int batch_size = 1, bool loddable = false);
std::shared_ptr<framework::Tensor> Predict(const framework::Tensor &t); std::shared_ptr<framework::Tensor> Predict(const framework::Tensor &t);
......
...@@ -712,1121 +712,121 @@ static inline size_t uint32_pack(uint32_t value, uint8_t *out) { ...@@ -712,1121 +712,121 @@ static inline size_t uint32_pack(uint32_t value, uint8_t *out) {
} }
/** /**
* Pack a signed 32-bit integer and return the number of bytes written. * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
* Negative numbers are encoded as two's complement 64-bit integers. * number of bytes written.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t int32_pack(int32_t value, uint8_t *out) {
if (value < 0) {
out[0] = value | 0x80;
out[1] = (value >> 7) | 0x80;
out[2] = (value >> 14) | 0x80;
out[3] = (value >> 21) | 0x80;
out[4] = (value >> 28) | 0x80;
out[5] = out[6] = out[7] = out[8] = 0xff;
out[9] = 0x01;
return 10;
} else {
return uint32_pack(value, out);
}
}
/**
* Pack a signed 32-bit integer using ZigZag encoding and return the number of
* bytes written.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t sint32_pack(int32_t value, uint8_t *out) {
return uint32_pack(zigzag32(value), out);
}
/**
* Pack a 64-bit unsigned integer using base-128 varint encoding and return the
* number of bytes written.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static size_t uint64_pack(uint64_t value, uint8_t *out) {
uint32_t hi = (uint32_t)(value >> 32);
uint32_t lo = (uint32_t)value;
unsigned rv;
if (hi == 0) return uint32_pack((uint32_t)lo, out);
out[0] = (lo) | 0x80;
out[1] = (lo >> 7) | 0x80;
out[2] = (lo >> 14) | 0x80;
out[3] = (lo >> 21) | 0x80;
if (hi < 8) {
out[4] = (hi << 4) | (lo >> 28);
return 5;
} else {
out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
hi >>= 3;
}
rv = 5;
while (hi >= 128) {
out[rv++] = hi | 0x80;
hi >>= 7;
}
out[rv++] = hi;
return rv;
}
/**
* Pack a 64-bit signed integer in ZigZag encoding and return the number of
* bytes written.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t sint64_pack(int64_t value, uint8_t *out) {
return uint64_pack(zigzag64(value), out);
}
/**
* Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
* types fixed32, sfixed32, float. Similar to "htole32".
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t fixed32_pack(uint32_t value, void *out) {
#if !defined(WORDS_BIGENDIAN)
memcpy(out, &value, 4);
#else
uint8_t *buf = out;
buf[0] = value;
buf[1] = value >> 8;
buf[2] = value >> 16;
buf[3] = value >> 24;
#endif
return 4;
}
/**
* Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
* types fixed64, sfixed64, double. Similar to "htole64".
*
* \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
* version would be appreciated, plus a way to decide to use 64-bit math where
* convenient.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t fixed64_pack(uint64_t value, void *out) {
#if !defined(WORDS_BIGENDIAN)
memcpy(out, &value, 8);
#else
fixed32_pack(value, out);
fixed32_pack(value >> 32, ((char *)out) + 4);
#endif
return 8;
}
/**
* Pack a boolean value as an integer and return the number of bytes written.
*
* \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
* that is idiomatic C++ in some STL implementations.
*
* \param value
* Value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t boolean_pack(protobuf_c_boolean value, uint8_t *out) {
*out = value ? TRUE : FALSE;
return 1;
}
/**
* Pack a NUL-terminated C string and return the number of bytes written. The
* output includes a length delimiter.
*
* The NULL pointer is treated as an empty string. This isn't really necessary,
* but it allows people to leave required strings blank. (See Issue #13 in the
* bug tracker for a little more explanation).
*
* \param str
* String to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t string_pack(const char *str, uint8_t *out) {
if (str == NULL) {
out[0] = 0;
return 1;
} else {
size_t len = strlen(str);
size_t rv = uint32_pack(len, out);
memcpy(out + rv, str, len);
return rv + len;
}
}
/**
* Pack a ProtobufCBinaryData and return the number of bytes written. The output
* includes a length delimiter.
*
* \param bd
* ProtobufCBinaryData to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static inline size_t binary_data_pack(const ProtobufCBinaryData *bd,
uint8_t *out) {
size_t len = bd->len;
size_t rv = uint32_pack(len, out);
memcpy(out + rv, bd->data, len);
return rv + len;
}
/**
* Pack a ProtobufCMessage and return the number of bytes written. The output
* includes a length delimiter.
*
* \param message
* ProtobufCMessage object to pack.
* \param[out] out
* Packed message.
* \return
* Number of bytes written to `out`.
*/
static inline size_t prefixed_message_pack(const ProtobufCMessage *message,
uint8_t *out) {
if (message == NULL) {
out[0] = 0;
return 1;
} else {
size_t rv = protobuf_c_message_pack(message, out + 1);
uint32_t rv_packed_size = uint32_size(rv);
if (rv_packed_size != 1) memmove(out + rv_packed_size, out + 1, rv);
return uint32_pack(rv, out) + rv;
}
}
/**
* Pack a field tag.
*
* Wire-type will be added in required_field_pack().
*
* \todo Just call uint64_pack on 64-bit platforms.
*
* \param id
* Tag value to encode.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static size_t tag_pack(uint32_t id, uint8_t *out) {
if (id < (1UL << (32 - 3)))
return uint32_pack(id << 3, out);
else
return uint64_pack(((uint64_t)id) << 3, out);
}
/**
* Pack a required field and return the number of bytes written.
*
* \param field
* Field descriptor.
* \param member
* The field member.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static size_t required_field_pack(const ProtobufCFieldDescriptor *field,
const void *member, uint8_t *out) {
size_t rv = tag_pack(field->id, out);
switch (field->type) {
case PROTOBUF_C_TYPE_SINT32:
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
return rv + sint32_pack(*(const int32_t *)member, out + rv);
case PROTOBUF_C_TYPE_ENUM:
case PROTOBUF_C_TYPE_INT32:
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
return rv + int32_pack(*(const int32_t *)member, out + rv);
case PROTOBUF_C_TYPE_UINT32:
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
return rv + uint32_pack(*(const uint32_t *)member, out + rv);
case PROTOBUF_C_TYPE_SINT64:
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
return rv + sint64_pack(*(const int64_t *)member, out + rv);
case PROTOBUF_C_TYPE_INT64:
case PROTOBUF_C_TYPE_UINT64:
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
return rv + uint64_pack(*(const uint64_t *)member, out + rv);
case PROTOBUF_C_TYPE_SFIXED32:
case PROTOBUF_C_TYPE_FIXED32:
case PROTOBUF_C_TYPE_FLOAT:
out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
return rv + fixed32_pack(*(const uint32_t *)member, out + rv);
case PROTOBUF_C_TYPE_SFIXED64:
case PROTOBUF_C_TYPE_FIXED64:
case PROTOBUF_C_TYPE_DOUBLE:
out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
return rv + fixed64_pack(*(const uint64_t *)member, out + rv);
case PROTOBUF_C_TYPE_BOOL:
out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
return rv + boolean_pack(*(const protobuf_c_boolean *)member, out + rv);
case PROTOBUF_C_TYPE_STRING:
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
return rv + string_pack(*(char *const *)member, out + rv);
case PROTOBUF_C_TYPE_BYTES:
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
return rv +
binary_data_pack((const ProtobufCBinaryData *)member, out + rv);
case PROTOBUF_C_TYPE_MESSAGE:
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
return rv + prefixed_message_pack(*(ProtobufCMessage *const *)member,
out + rv);
}
PROTOBUF_C__ASSERT_NOT_REACHED();
return 0;
}
/**
* Pack a oneof field and return the number of bytes written. Only packs the
* field that is selected by the case enum.
*
* \param field
* Field descriptor.
* \param oneof_case
* Enum value that selects the field in the oneof.
* \param member
* The field member.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static size_t oneof_field_pack(const ProtobufCFieldDescriptor *field,
uint32_t oneof_case, const void *member,
uint8_t *out) {
if (oneof_case != field->id) {
return 0;
}
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
field->type == PROTOBUF_C_TYPE_STRING) {
const void *ptr = *(const void *const *)member;
if (ptr == NULL || ptr == field->default_value) return 0;
}
return required_field_pack(field, member, out);
}
/**
* Pack an optional field and return the number of bytes written.
*
* \param field
* Field descriptor.
* \param has
* Whether the field is set.
* \param member
* The field member.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static size_t optional_field_pack(const ProtobufCFieldDescriptor *field,
const protobuf_c_boolean has,
const void *member, uint8_t *out) {
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
field->type == PROTOBUF_C_TYPE_STRING) {
const void *ptr = *(const void *const *)member;
if (ptr == NULL || ptr == field->default_value) return 0;
} else {
if (!has) return 0;
}
return required_field_pack(field, member, out);
}
/**
* Pack an unlabeled field and return the number of bytes written.
*
* \param field
* Field descriptor.
* \param member
* The field member.
* \param[out] out
* Packed value.
* \return
* Number of bytes written to `out`.
*/
static size_t unlabeled_field_pack(const ProtobufCFieldDescriptor *field,
const void *member, uint8_t *out) {
if (field_is_zeroish(field, member)) return 0;
return required_field_pack(field, member, out);
}
/**
* Given a field type, return the in-memory size.
*
* \todo Implement as a table lookup.
*
* \param type
* Field type.
* \return
* Size of the field.
*/
static inline size_t sizeof_elt_in_repeated_array(ProtobufCType type) {
switch (type) {
case PROTOBUF_C_TYPE_SINT32:
case PROTOBUF_C_TYPE_INT32:
case PROTOBUF_C_TYPE_UINT32:
case PROTOBUF_C_TYPE_SFIXED32:
case PROTOBUF_C_TYPE_FIXED32:
case PROTOBUF_C_TYPE_FLOAT:
case PROTOBUF_C_TYPE_ENUM:
return 4;
case PROTOBUF_C_TYPE_SINT64:
case PROTOBUF_C_TYPE_INT64:
case PROTOBUF_C_TYPE_UINT64:
case PROTOBUF_C_TYPE_SFIXED64:
case PROTOBUF_C_TYPE_FIXED64:
case PROTOBUF_C_TYPE_DOUBLE:
return 8;
case PROTOBUF_C_TYPE_BOOL:
return sizeof(protobuf_c_boolean);
case PROTOBUF_C_TYPE_STRING:
case PROTOBUF_C_TYPE_MESSAGE:
return sizeof(void *);
case PROTOBUF_C_TYPE_BYTES:
return sizeof(ProtobufCBinaryData);
}
PROTOBUF_C__ASSERT_NOT_REACHED();
return 0;
}
/**
* Pack an array of 32-bit quantities.
*
* \param[out] out
* Destination.
* \param[in] in
* Source.
* \param[in] n
* Number of elements in the source array.
*/
static void copy_to_little_endian_32(void *out, const void *in,
const unsigned n) {
#if !defined(WORDS_BIGENDIAN)
memcpy(out, in, n * 4);
#else
unsigned i;
const uint32_t *ini = in;
for (i = 0; i < n; i++) fixed32_pack(ini[i], (uint32_t *)out + i);
#endif
}
/**
* Pack an array of 64-bit quantities.
*
* \param[out] out
* Destination.
* \param[in] in
* Source.
* \param[in] n
* Number of elements in the source array.
*/
static void copy_to_little_endian_64(void *out, const void *in,
const unsigned n) {
#if !defined(WORDS_BIGENDIAN)
memcpy(out, in, n * 8);
#else
unsigned i;
const uint64_t *ini = in;
for (i = 0; i < n; i++) fixed64_pack(ini[i], (uint64_t *)out + i);
#endif
}
/**
* Get the minimum number of bytes required to pack a field value of a
* particular type.
*
* \param type
* Field type.
* \return
* Number of bytes.
*/
static unsigned get_type_min_size(ProtobufCType type) {
if (type == PROTOBUF_C_TYPE_SFIXED32 || type == PROTOBUF_C_TYPE_FIXED32 ||
type == PROTOBUF_C_TYPE_FLOAT) {
return 4;
}
if (type == PROTOBUF_C_TYPE_SFIXED64 || type == PROTOBUF_C_TYPE_FIXED64 ||
type == PROTOBUF_C_TYPE_DOUBLE) {
return 8;
}
return 1;
}
/**
* Packs the elements of a repeated field and returns the serialised field and
* its length.
*
* \param field
* Field descriptor.
* \param count
* Number of elements in the repeated field array.
* \param member
* Pointer to the elements for this repeated field.
* \param[out] out
* Serialised representation of the repeated field.
* \return
* Number of bytes serialised to `out`.
*/
static size_t repeated_field_pack(const ProtobufCFieldDescriptor *field,
size_t count, const void *member,
uint8_t *out) {
void *array = *(void *const *)member;
unsigned i;
if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
unsigned header_len;
unsigned len_start;
unsigned min_length;
unsigned payload_len;
unsigned length_size_min;
unsigned actual_length_size;
uint8_t *payload_at;
if (count == 0) return 0;
header_len = tag_pack(field->id, out);
out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
len_start = header_len;
min_length = get_type_min_size(field->type) * count;
length_size_min = uint32_size(min_length);
header_len += length_size_min;
payload_at = out + header_len;
switch (field->type) {
case PROTOBUF_C_TYPE_SFIXED32:
case PROTOBUF_C_TYPE_FIXED32:
case PROTOBUF_C_TYPE_FLOAT:
copy_to_little_endian_32(payload_at, array, count);
payload_at += count * 4;
break;
case PROTOBUF_C_TYPE_SFIXED64:
case PROTOBUF_C_TYPE_FIXED64:
case PROTOBUF_C_TYPE_DOUBLE:
copy_to_little_endian_64(payload_at, array, count);
payload_at += count * 8;
break;
case PROTOBUF_C_TYPE_ENUM:
case PROTOBUF_C_TYPE_INT32: {
const int32_t *arr = (const int32_t *)array;
for (i = 0; i < count; i++)
payload_at += int32_pack(arr[i], payload_at);
break;
}
case PROTOBUF_C_TYPE_SINT32: {
const int32_t *arr = (const int32_t *)array;
for (i = 0; i < count; i++)
payload_at += sint32_pack(arr[i], payload_at);
break;
}
case PROTOBUF_C_TYPE_SINT64: {
const int64_t *arr = (const int64_t *)array;
for (i = 0; i < count; i++)
payload_at += sint64_pack(arr[i], payload_at);
break;
}
case PROTOBUF_C_TYPE_UINT32: {
const uint32_t *arr = (const uint32_t *)array;
for (i = 0; i < count; i++)
payload_at += uint32_pack(arr[i], payload_at);
break;
}
case PROTOBUF_C_TYPE_INT64:
case PROTOBUF_C_TYPE_UINT64: {
const uint64_t *arr = (const uint64_t *)array;
for (i = 0; i < count; i++)
payload_at += uint64_pack(arr[i], payload_at);
break;
}
case PROTOBUF_C_TYPE_BOOL: {
const protobuf_c_boolean *arr = (const protobuf_c_boolean *)array;
for (i = 0; i < count; i++)
payload_at += boolean_pack(arr[i], payload_at);
break;
}
default:
PROTOBUF_C__ASSERT_NOT_REACHED();
}
payload_len = payload_at - (out + header_len);
actual_length_size = uint32_size(payload_len);
if (length_size_min != actual_length_size) {
assert(actual_length_size == length_size_min + 1);
memmove(out + header_len + 1, out + header_len, payload_len);
header_len++;
}
uint32_pack(payload_len, out + len_start);
return header_len + payload_len;
} else {
/* not "packed" cased */
/* CONSIDER: optimize this case a bit (by putting the loop inside the
* switch) */
size_t rv = 0;
unsigned siz = sizeof_elt_in_repeated_array(field->type);
for (i = 0; i < count; i++) {
rv += required_field_pack(field, array, out + rv);
array = (char *)array + siz;
}
return rv;
}
}
static size_t unknown_field_pack(const ProtobufCMessageUnknownField *field,
uint8_t *out) {
size_t rv = tag_pack(field->tag, out);
out[0] |= field->wire_type;
memcpy(out + rv, field->data, field->len);
return rv + field->len;
}
/**@}*/
size_t protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out) {
unsigned i;
size_t rv = 0;
ASSERT_IS_MESSAGE(message);
for (i = 0; i < message->descriptor->n_fields; i++) {
const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
const void *member = ((const char *)message) + field->offset;
/*
* It doesn't hurt to compute qmember (a pointer to the
* quantifier field of the structure), but the pointer is only
* valid if the field is:
* - a repeated field, or
* - a field that is part of a oneof
* - an optional field that isn't a pointer type
* (Meaning: not a message or a string).
*/
const void *qmember = ((const char *)message) + field->quantifier_offset;
if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
rv += required_field_pack(field, member, out + rv);
} else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
field->label == PROTOBUF_C_LABEL_NONE) &&
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
rv +=
oneof_field_pack(field, *(const uint32_t *)qmember, member, out + rv);
} else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
rv += optional_field_pack(field, *(const protobuf_c_boolean *)qmember,
member, out + rv);
} else if (field->label == PROTOBUF_C_LABEL_NONE) {
rv += unlabeled_field_pack(field, member, out + rv);
} else {
rv += repeated_field_pack(field, *(const size_t *)qmember, member,
out + rv);
}
}
for (i = 0; i < message->n_unknown_fields; i++)
rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
return rv;
}
/**
* \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
*
* Routines mainly used by protobuf_c_message_pack_to_buffer().
*
* \ingroup internal
* @{
*/
/**
* Pack a required field to a virtual buffer.
*
* \param field
* Field descriptor.
* \param member
* The element to be packed.
* \param[out] buffer
* Virtual buffer to append data to.
* \return
* Number of bytes packed.
*/
static size_t required_field_pack_to_buffer(
const ProtobufCFieldDescriptor *field, const void *member,
ProtobufCBuffer *buffer) {
size_t rv;
uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
rv = tag_pack(field->id, scratch);
switch (field->type) {
case PROTOBUF_C_TYPE_SINT32:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
rv += sint32_pack(*(const int32_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_ENUM:
case PROTOBUF_C_TYPE_INT32:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
rv += int32_pack(*(const int32_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_UINT32:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
rv += uint32_pack(*(const uint32_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_SINT64:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
rv += sint64_pack(*(const int64_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_INT64:
case PROTOBUF_C_TYPE_UINT64:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
rv += uint64_pack(*(const uint64_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_SFIXED32:
case PROTOBUF_C_TYPE_FIXED32:
case PROTOBUF_C_TYPE_FLOAT:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
rv += fixed32_pack(*(const uint32_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_SFIXED64:
case PROTOBUF_C_TYPE_FIXED64:
case PROTOBUF_C_TYPE_DOUBLE:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
rv += fixed64_pack(*(const uint64_t *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_BOOL:
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
rv += boolean_pack(*(const protobuf_c_boolean *)member, scratch + rv);
buffer->append(buffer, rv, scratch);
break;
case PROTOBUF_C_TYPE_STRING: {
const char *str = *(char *const *)member;
size_t sublen = str ? strlen(str) : 0;
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
rv += uint32_pack(sublen, scratch + rv);
buffer->append(buffer, rv, scratch);
buffer->append(buffer, sublen, (const uint8_t *)str);
rv += sublen;
break;
}
case PROTOBUF_C_TYPE_BYTES: {
const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *)member);
size_t sublen = bd->len;
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
rv += uint32_pack(sublen, scratch + rv);
buffer->append(buffer, rv, scratch);
buffer->append(buffer, sublen, bd->data);
rv += sublen;
break;
}
case PROTOBUF_C_TYPE_MESSAGE: {
uint8_t simple_buffer_scratch[256];
size_t sublen;
const ProtobufCMessage *msg = *(ProtobufCMessage *const *)member;
ProtobufCBufferSimple simple_buffer =
PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch);
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
if (msg == NULL)
sublen = 0;
else
sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base);
rv += uint32_pack(sublen, scratch + rv);
buffer->append(buffer, rv, scratch);
buffer->append(buffer, sublen, simple_buffer.data);
rv += sublen;
PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer);
break;
}
default:
PROTOBUF_C__ASSERT_NOT_REACHED();
}
return rv;
}
/**
* Pack a oneof field to a buffer. Only packs the field that is selected by the
* case enum.
*
* \param field
* Field descriptor.
* \param oneof_case
* Enum value that selects the field in the oneof.
* \param member
* The element to be packed.
* \param[out] buffer
* Virtual buffer to append data to.
* \return
* Number of bytes serialised to `buffer`.
*/
static size_t oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
uint32_t oneof_case,
const void *member,
ProtobufCBuffer *buffer) {
if (oneof_case != field->id) {
return 0;
}
if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
field->type == PROTOBUF_C_TYPE_STRING) {
const void *ptr = *(const void *const *)member;
if (ptr == NULL || ptr == field->default_value) return 0;
}
return required_field_pack_to_buffer(field, member, buffer);
}
/**
* Pack an optional field to a buffer.
* *
* \param field * \param value
* Field descriptor. * Value to encode.
* \param has * \param[out] out
* Whether the field is set. * Packed value.
* \param member
* The element to be packed.
* \param[out] buffer
* Virtual buffer to append data to.
* \return * \return
* Number of bytes serialised to `buffer`. * Number of bytes written to `out`.
*/ */
static size_t optional_field_pack_to_buffer( static size_t uint64_pack(uint64_t value, uint8_t *out) {
const ProtobufCFieldDescriptor *field, const protobuf_c_boolean has, uint32_t hi = (uint32_t)(value >> 32);
const void *member, ProtobufCBuffer *buffer) { uint32_t lo = (uint32_t)value;
if (field->type == PROTOBUF_C_TYPE_MESSAGE || unsigned rv;
field->type == PROTOBUF_C_TYPE_STRING) {
const void *ptr = *(const void *const *)member; if (hi == 0) return uint32_pack((uint32_t)lo, out);
if (ptr == NULL || ptr == field->default_value) return 0; out[0] = (lo) | 0x80;
out[1] = (lo >> 7) | 0x80;
out[2] = (lo >> 14) | 0x80;
out[3] = (lo >> 21) | 0x80;
if (hi < 8) {
out[4] = (hi << 4) | (lo >> 28);
return 5;
} else { } else {
if (!has) return 0; out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
hi >>= 3;
} }
return required_field_pack_to_buffer(field, member, buffer); rv = 5;
while (hi >= 128) {
out[rv++] = hi | 0x80;
hi >>= 7;
}
out[rv++] = hi;
return rv;
} }
/** /**
* Pack an unlabeled field to a buffer. * Pack a ProtobufCBinaryData and return the number of bytes written. The output
* includes a length delimiter.
* *
* \param field * \param bd
* Field descriptor. * ProtobufCBinaryData to encode.
* \param member * \param[out] out
* The element to be packed. * Packed value.
* \param[out] buffer
* Virtual buffer to append data to.
* \return * \return
* Number of bytes serialised to `buffer`. * Number of bytes written to `out`.
*/ */
static size_t unlabeled_field_pack_to_buffer( static inline size_t binary_data_pack(const ProtobufCBinaryData *bd,
const ProtobufCFieldDescriptor *field, const void *member, uint8_t *out) {
ProtobufCBuffer *buffer) { size_t len = bd->len;
if (field_is_zeroish(field, member)) return 0; size_t rv = uint32_pack(len, out);
return required_field_pack_to_buffer(field, member, buffer); memcpy(out + rv, bd->data, len);
return rv + len;
} }
/** /**
* Get the packed size of an array of same field type. * Pack a field tag.
* *
* \param field * Wire-type will be added in required_field_pack().
* Field descriptor. *
* \param count * \todo Just call uint64_pack on 64-bit platforms.
* Number of elements of this type. *
* \param array * \param id
* The elements to get the size of. * Tag value to encode.
* \param[out] out
* Packed value.
* \return * \return
* Number of bytes required. * Number of bytes written to `out`.
*/ */
static size_t get_packed_payload_length(const ProtobufCFieldDescriptor *field, static size_t tag_pack(uint32_t id, uint8_t *out) {
unsigned count, const void *array) { if (id < (1UL << (32 - 3)))
unsigned rv = 0; return uint32_pack(id << 3, out);
unsigned i; else
return uint64_pack(((uint64_t)id) << 3, out);
switch (field->type) {
case PROTOBUF_C_TYPE_SFIXED32:
case PROTOBUF_C_TYPE_FIXED32:
case PROTOBUF_C_TYPE_FLOAT:
return count * 4;
case PROTOBUF_C_TYPE_SFIXED64:
case PROTOBUF_C_TYPE_FIXED64:
case PROTOBUF_C_TYPE_DOUBLE:
return count * 8;
case PROTOBUF_C_TYPE_ENUM:
case PROTOBUF_C_TYPE_INT32: {
const int32_t *arr = (const int32_t *)array;
for (i = 0; i < count; i++) rv += int32_size(arr[i]);
break;
}
case PROTOBUF_C_TYPE_SINT32: {
const int32_t *arr = (const int32_t *)array;
for (i = 0; i < count; i++) rv += sint32_size(arr[i]);
break;
}
case PROTOBUF_C_TYPE_UINT32: {
const uint32_t *arr = (const uint32_t *)array;
for (i = 0; i < count; i++) rv += uint32_size(arr[i]);
break;
}
case PROTOBUF_C_TYPE_SINT64: {
const int64_t *arr = (const int64_t *)array;
for (i = 0; i < count; i++) rv += sint64_size(arr[i]);
break;
}
case PROTOBUF_C_TYPE_INT64:
case PROTOBUF_C_TYPE_UINT64: {
const uint64_t *arr = (const uint64_t *)array;
for (i = 0; i < count; i++) rv += uint64_size(arr[i]);
break;
}
case PROTOBUF_C_TYPE_BOOL:
return count;
default:
PROTOBUF_C__ASSERT_NOT_REACHED();
}
return rv;
} }
/** /**
* Pack an array of same field type to a virtual buffer. * Given a field type, return the in-memory size.
* *
* \param field * \todo Implement as a table lookup.
* Field descriptor. *
* \param count * \param type
* Number of elements of this type. * Field type.
* \param array
* The elements to get the size of.
* \param[out] buffer
* Virtual buffer to append data to.
* \return * \return
* Number of bytes packed. * Size of the field.
*/ */
static size_t pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field, static inline size_t sizeof_elt_in_repeated_array(ProtobufCType type) {
unsigned count, const void *array, switch (type) {
ProtobufCBuffer *buffer) { case PROTOBUF_C_TYPE_SINT32:
uint8_t scratch[16]; case PROTOBUF_C_TYPE_INT32:
size_t rv = 0; case PROTOBUF_C_TYPE_UINT32:
unsigned i;
switch (field->type) {
case PROTOBUF_C_TYPE_SFIXED32: case PROTOBUF_C_TYPE_SFIXED32:
case PROTOBUF_C_TYPE_FIXED32: case PROTOBUF_C_TYPE_FIXED32:
case PROTOBUF_C_TYPE_FLOAT: case PROTOBUF_C_TYPE_FLOAT:
#if !defined(WORDS_BIGENDIAN)
rv = count * 4;
goto no_packing_needed;
#else
for (i = 0; i < count; i++) {
unsigned len = fixed32_pack(((uint32_t *)array)[i], scratch);
buffer->append(buffer, len, scratch);
rv += len;
}
break;
#endif
case PROTOBUF_C_TYPE_SFIXED64:
case PROTOBUF_C_TYPE_FIXED64:
case PROTOBUF_C_TYPE_DOUBLE:
#if !defined(WORDS_BIGENDIAN)
rv = count * 8;
goto no_packing_needed;
#else
for (i = 0; i < count; i++) {
unsigned len = fixed64_pack(((uint64_t *)array)[i], scratch);
buffer->append(buffer, len, scratch);
rv += len;
}
break;
#endif
case PROTOBUF_C_TYPE_ENUM: case PROTOBUF_C_TYPE_ENUM:
case PROTOBUF_C_TYPE_INT32: return 4;
for (i = 0; i < count; i++) {
unsigned len = int32_pack(((int32_t *)array)[i], scratch);
buffer->append(buffer, len, scratch);
rv += len;
}
break;
case PROTOBUF_C_TYPE_SINT32:
for (i = 0; i < count; i++) {
unsigned len = sint32_pack(((int32_t *)array)[i], scratch);
buffer->append(buffer, len, scratch);
rv += len;
}
break;
case PROTOBUF_C_TYPE_UINT32:
for (i = 0; i < count; i++) {
unsigned len = uint32_pack(((uint32_t *)array)[i], scratch);
buffer->append(buffer, len, scratch);
rv += len;
}
break;
case PROTOBUF_C_TYPE_SINT64: case PROTOBUF_C_TYPE_SINT64:
for (i = 0; i < count; i++) {
unsigned len = sint64_pack(((int64_t *)array)[i], scratch);
buffer->append(buffer, len, scratch);
rv += len;
}
break;
case PROTOBUF_C_TYPE_INT64: case PROTOBUF_C_TYPE_INT64:
case PROTOBUF_C_TYPE_UINT64: case PROTOBUF_C_TYPE_UINT64:
for (i = 0; i < count; i++) { case PROTOBUF_C_TYPE_SFIXED64:
unsigned len = uint64_pack(((uint64_t *)array)[i], scratch); case PROTOBUF_C_TYPE_FIXED64:
buffer->append(buffer, len, scratch); case PROTOBUF_C_TYPE_DOUBLE:
rv += len; return 8;
}
break;
case PROTOBUF_C_TYPE_BOOL: case PROTOBUF_C_TYPE_BOOL:
for (i = 0; i < count; i++) { return sizeof(protobuf_c_boolean);
unsigned len = boolean_pack(((protobuf_c_boolean *)array)[i], scratch); case PROTOBUF_C_TYPE_STRING:
buffer->append(buffer, len, scratch); case PROTOBUF_C_TYPE_MESSAGE:
rv += len; return sizeof(void *);
} case PROTOBUF_C_TYPE_BYTES:
return count; return sizeof(ProtobufCBinaryData);
default:
PROTOBUF_C__ASSERT_NOT_REACHED();
}
return rv;
#if !defined(WORDS_BIGENDIAN)
no_packing_needed:
buffer->append(buffer, rv, array);
return rv;
#endif
}
static size_t repeated_field_pack_to_buffer(
const ProtobufCFieldDescriptor *field, unsigned count, const void *member,
ProtobufCBuffer *buffer) {
char *array = *(char *const *)member;
if (count == 0) return 0;
if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
size_t rv = tag_pack(field->id, scratch);
size_t payload_len = get_packed_payload_length(field, count, array);
size_t tmp;
scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
rv += uint32_pack(payload_len, scratch + rv);
buffer->append(buffer, rv, scratch);
tmp = pack_buffer_packed_payload(field, count, array, buffer);
assert(tmp == payload_len);
return rv + payload_len;
} else {
size_t siz;
unsigned i;
/* CONSIDER: optimize this case a bit (by putting the loop inside the
* switch) */
unsigned rv = 0;
siz = sizeof_elt_in_repeated_array(field->type);
for (i = 0; i < count; i++) {
rv += required_field_pack_to_buffer(field, array, buffer);
array += siz;
}
return rv;
}
}
static size_t unknown_field_pack_to_buffer(
const ProtobufCMessageUnknownField *field, ProtobufCBuffer *buffer) {
uint8_t header[MAX_UINT64_ENCODED_SIZE];
size_t rv = tag_pack(field->tag, header);
header[0] |= field->wire_type;
buffer->append(buffer, rv, header);
buffer->append(buffer, field->len, field->data);
return rv + field->len;
}
/**@}*/
size_t protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
ProtobufCBuffer *buffer) {
unsigned i;
size_t rv = 0;
ASSERT_IS_MESSAGE(message);
for (i = 0; i < message->descriptor->n_fields; i++) {
const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
const void *member = ((const char *)message) + field->offset;
const void *qmember = ((const char *)message) + field->quantifier_offset;
if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
rv += required_field_pack_to_buffer(field, member, buffer);
} else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
field->label == PROTOBUF_C_LABEL_NONE) &&
(0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
rv += oneof_field_pack_to_buffer(field, *(const uint32_t *)qmember,
member, buffer);
} else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
rv += optional_field_pack_to_buffer(
field, *(const protobuf_c_boolean *)qmember, member, buffer);
} else if (field->label == PROTOBUF_C_LABEL_NONE) {
rv += unlabeled_field_pack_to_buffer(field, member, buffer);
} else {
rv += repeated_field_pack_to_buffer(field, *(const size_t *)qmember,
member, buffer);
}
} }
for (i = 0; i < message->n_unknown_fields; i++) PROTOBUF_C__ASSERT_NOT_REACHED();
rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer); return 0;
return rv;
} }
/**
* \defgroup unpack unpacking implementation
*
* Routines mainly used by the unpacking functions.
*
* \ingroup internal
* @{
*/
static inline int int_range_lookup(unsigned n_ranges, static inline int int_range_lookup(unsigned n_ranges,
const ProtobufCIntRange *ranges, int value) { const ProtobufCIntRange *ranges, int value) {
unsigned n; unsigned n;
...@@ -2010,7 +1010,6 @@ static protobuf_c_boolean merge_messages(ProtobufCMessage *earlier_msg, ...@@ -2010,7 +1010,6 @@ static protobuf_c_boolean merge_messages(ProtobufCMessage *earlier_msg,
int field_index = int_range_lookup( int field_index = int_range_lookup(
latter_msg->descriptor->n_field_ranges, latter_msg->descriptor->n_field_ranges,
latter_msg->descriptor->field_ranges, *earlier_case_p); latter_msg->descriptor->field_ranges, *earlier_case_p);
if (field_index < 0) return FALSE;
field = latter_msg->descriptor->fields + field_index; field = latter_msg->descriptor->fields + field_index;
} else { } else {
/* Oneof is present in the latter message, move on */ /* Oneof is present in the latter message, move on */
...@@ -2346,7 +1345,6 @@ static protobuf_c_boolean parse_oneof_member(ScannedMember *scanned_member, ...@@ -2346,7 +1345,6 @@ static protobuf_c_boolean parse_oneof_member(ScannedMember *scanned_member,
int field_index = int field_index =
int_range_lookup(message->descriptor->n_field_ranges, int_range_lookup(message->descriptor->n_field_ranges,
message->descriptor->field_ranges, *oneof_case); message->descriptor->field_ranges, *oneof_case);
if (field_index < 0) return FALSE;
const ProtobufCFieldDescriptor *old_field = const ProtobufCFieldDescriptor *old_field =
message->descriptor->fields + field_index; message->descriptor->fields + field_index;
size_t el_size = sizeof_elt_in_repeated_array(old_field->type); size_t el_size = sizeof_elt_in_repeated_array(old_field->type);
...@@ -3098,147 +2096,3 @@ protobuf_c_boolean protobuf_c_message_check(const ProtobufCMessage *message) { ...@@ -3098,147 +2096,3 @@ protobuf_c_boolean protobuf_c_message_check(const ProtobufCMessage *message) {
typedef void (*GenericHandler)(void *service, const ProtobufCMessage *input, typedef void (*GenericHandler)(void *service, const ProtobufCMessage *input,
ProtobufCClosure closure, void *closure_data); ProtobufCClosure closure, void *closure_data);
void protobuf_c_service_invoke_internal(ProtobufCService *service,
unsigned method_index,
const ProtobufCMessage *input,
ProtobufCClosure closure,
void *closure_data) {
GenericHandler *handlers;
GenericHandler handler;
/*
* Verify that method_index is within range. If this fails, you are
* likely invoking a newly added method on an old service. (Although
* other memory corruption bugs can cause this assertion too.)
*/
assert(method_index < service->descriptor->n_methods);
/*
* Get the array of virtual methods (which are enumerated by the
* generated code).
*/
handlers = (GenericHandler *)(service + 1);
/*
* Get our method and invoke it.
* \todo Seems like handler == NULL is a situation that needs handling.
*/
handler = handlers[method_index];
(*handler)(service, input, closure, closure_data);
}
void protobuf_c_service_generated_init(
ProtobufCService *service, const ProtobufCServiceDescriptor *descriptor,
ProtobufCServiceDestroy destroy) {
ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
service->descriptor = descriptor;
service->destroy = destroy;
service->invoke = protobuf_c_service_invoke_internal;
memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler));
}
void protobuf_c_service_destroy(ProtobufCService *service) {
service->destroy(service);
}
/* --- querying the descriptors --- */
const ProtobufCEnumValue *protobuf_c_enum_descriptor_get_value_by_name(
const ProtobufCEnumDescriptor *desc, const char *name) {
unsigned start = 0;
unsigned count;
if (desc == NULL || desc->values_by_name == NULL) return NULL;
count = desc->n_value_names;
while (count > 1) {
unsigned mid = start + count / 2;
int rv = strcmp(desc->values_by_name[mid].name, name);
if (rv == 0)
return desc->values + desc->values_by_name[mid].index;
else if (rv < 0) {
count = start + count - (mid + 1);
start = mid + 1;
} else
count = mid - start;
}
if (count == 0) return NULL;
if (strcmp(desc->values_by_name[start].name, name) == 0)
return desc->values + desc->values_by_name[start].index;
return NULL;
}
const ProtobufCEnumValue *protobuf_c_enum_descriptor_get_value(
const ProtobufCEnumDescriptor *desc, int value) {
int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
if (rv < 0) return NULL;
return desc->values + rv;
}
const ProtobufCFieldDescriptor *protobuf_c_message_descriptor_get_field_by_name(
const ProtobufCMessageDescriptor *desc, const char *name) {
unsigned start = 0;
unsigned count;
const ProtobufCFieldDescriptor *field;
if (desc == NULL || desc->fields_sorted_by_name == NULL) return NULL;
count = desc->n_fields;
while (count > 1) {
unsigned mid = start + count / 2;
int rv;
field = desc->fields + desc->fields_sorted_by_name[mid];
rv = strcmp(field->name, name);
if (rv == 0)
return field;
else if (rv < 0) {
count = start + count - (mid + 1);
start = mid + 1;
} else
count = mid - start;
}
if (count == 0) return NULL;
field = desc->fields + desc->fields_sorted_by_name[start];
if (strcmp(field->name, name) == 0) return field;
return NULL;
}
const ProtobufCFieldDescriptor *protobuf_c_message_descriptor_get_field(
const ProtobufCMessageDescriptor *desc, unsigned value) {
int rv = int_range_lookup(desc->n_field_ranges, desc->field_ranges, value);
if (rv < 0) return NULL;
return desc->fields + rv;
}
const ProtobufCMethodDescriptor *
protobuf_c_service_descriptor_get_method_by_name(
const ProtobufCServiceDescriptor *desc, const char *name) {
unsigned start = 0;
unsigned count;
if (desc == NULL || desc->method_indices_by_name == NULL) return NULL;
count = desc->n_methods;
while (count > 1) {
unsigned mid = start + count / 2;
unsigned mid_index = desc->method_indices_by_name[mid];
const char *mid_name = desc->methods[mid_index].name;
int rv = strcmp(mid_name, name);
if (rv == 0) return desc->methods + desc->method_indices_by_name[mid];
if (rv < 0) {
count = start + count - (mid + 1);
start = mid + 1;
} else {
count = mid - start;
}
}
if (count == 0) return NULL;
if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) ==
0)
return desc->methods + desc->method_indices_by_name[start];
return NULL;
}
/* /*
* Copyright (c) 2008-2018, Dave Benson and the protobuf-c authors. * Copyright (c) 2008-2017, Dave Benson and the protobuf-c authors.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -784,13 +784,13 @@ uint32_t protobuf_c_version_number(void); ...@@ -784,13 +784,13 @@ uint32_t protobuf_c_version_number(void);
* The version of the protobuf-c headers, represented as a string using the same * The version of the protobuf-c headers, represented as a string using the same
* format as protobuf_c_version(). * format as protobuf_c_version().
*/ */
#define PROTOBUF_C_VERSION "1.3.1" #define PROTOBUF_C_VERSION "1.3.0"
/** /**
* The version of the protobuf-c headers, represented as an integer using the * The version of the protobuf-c headers, represented as an integer using the
* same format as protobuf_c_version_number(). * same format as protobuf_c_version_number().
*/ */
#define PROTOBUF_C_VERSION_NUMBER 1003001 #define PROTOBUF_C_VERSION_NUMBER 1003000
/** /**
* The minimum protoc-c version which works with the current version of the * The minimum protoc-c version which works with the current version of the
...@@ -798,76 +798,6 @@ uint32_t protobuf_c_version_number(void); ...@@ -798,76 +798,6 @@ uint32_t protobuf_c_version_number(void);
*/ */
#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000 #define PROTOBUF_C_MIN_COMPILER_VERSION 1000000
/**
* Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name.
*
* \param desc
* The `ProtobufCEnumDescriptor` object.
* \param name
* The `name` field from the corresponding `ProtobufCEnumValue` object to
* match.
* \return
* A `ProtobufCEnumValue` object.
* \retval NULL
* If not found or if the optimize_for = CODE_SIZE option was set.
*/
PROTOBUF_C__API
const ProtobufCEnumValue *protobuf_c_enum_descriptor_get_value_by_name(
const ProtobufCEnumDescriptor *desc, const char *name);
/**
* Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric
* value.
*
* \param desc
* The `ProtobufCEnumDescriptor` object.
* \param value
* The `value` field from the corresponding `ProtobufCEnumValue` object to
* match.
*
* \return
* A `ProtobufCEnumValue` object.
* \retval NULL
* If not found.
*/
PROTOBUF_C__API
const ProtobufCEnumValue *protobuf_c_enum_descriptor_get_value(
const ProtobufCEnumDescriptor *desc, int value);
/**
* Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
* the name of the field.
*
* \param desc
* The `ProtobufCMessageDescriptor` object.
* \param name
* The name of the field.
* \return
* A `ProtobufCFieldDescriptor` object.
* \retval NULL
* If not found or if the optimize_for = CODE_SIZE option was set.
*/
PROTOBUF_C__API
const ProtobufCFieldDescriptor *protobuf_c_message_descriptor_get_field_by_name(
const ProtobufCMessageDescriptor *desc, const char *name);
/**
* Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
* the tag value of the field.
*
* \param desc
* The `ProtobufCMessageDescriptor` object.
* \param value
* The tag value of the field.
* \return
* A `ProtobufCFieldDescriptor` object.
* \retval NULL
* If not found.
*/
PROTOBUF_C__API
const ProtobufCFieldDescriptor *protobuf_c_message_descriptor_get_field(
const ProtobufCMessageDescriptor *desc, unsigned value);
/** /**
* Determine the number of bytes required to store the serialised message. * Determine the number of bytes required to store the serialised message.
* *
...@@ -879,42 +809,6 @@ const ProtobufCFieldDescriptor *protobuf_c_message_descriptor_get_field( ...@@ -879,42 +809,6 @@ const ProtobufCFieldDescriptor *protobuf_c_message_descriptor_get_field(
PROTOBUF_C__API PROTOBUF_C__API
size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message); size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
/**
* Serialise a message from its in-memory representation.
*
* This function stores the serialised bytes of the message in a pre-allocated
* buffer.
*
* \param message
* The message object to serialise.
* \param[out] out
* Buffer to store the bytes of the serialised message. This buffer must
* have enough space to store the packed message. Use
* protobuf_c_message_get_packed_size() to determine the number of bytes
* required.
* \return
* Number of bytes stored in `out`.
*/
PROTOBUF_C__API
size_t protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out);
/**
* Serialise a message from its in-memory representation to a virtual buffer.
*
* This function calls the `append` method of a `ProtobufCBuffer` object to
* consume the bytes generated by the serialiser.
*
* \param message
* The message object to serialise.
* \param buffer
* The virtual buffer object.
* \return
* Number of bytes passed to the virtual buffer.
*/
PROTOBUF_C__API
size_t protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
ProtobufCBuffer *buffer);
/** /**
* Unpack a serialised message into an in-memory representation. * Unpack a serialised message into an in-memory representation.
* *
...@@ -983,33 +877,6 @@ PROTOBUF_C__API ...@@ -983,33 +877,6 @@ PROTOBUF_C__API
void protobuf_c_message_init(const ProtobufCMessageDescriptor *descriptor, void protobuf_c_message_init(const ProtobufCMessageDescriptor *descriptor,
void *message); void *message);
/**
* Free a service.
*
* \param service
* The service object to free.
*/
PROTOBUF_C__API
void protobuf_c_service_destroy(ProtobufCService *service);
/**
* Look up a `ProtobufCMethodDescriptor` by name.
*
* \param desc
* Service descriptor.
* \param name
* Name of the method.
*
* \return
* A `ProtobufCMethodDescriptor` object.
* \retval NULL
* If not found or if the optimize_for = CODE_SIZE option was set.
*/
PROTOBUF_C__API
const ProtobufCMethodDescriptor *
protobuf_c_service_descriptor_get_method_by_name(
const ProtobufCServiceDescriptor *desc, const char *name);
/** /**
* Initialise a `ProtobufCBufferSimple` object. * Initialise a `ProtobufCBufferSimple` object.
*/ */
...@@ -1047,18 +914,6 @@ PROTOBUF_C__API ...@@ -1047,18 +914,6 @@ PROTOBUF_C__API
void protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, size_t len, void protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, size_t len,
const unsigned char *data); const unsigned char *data);
PROTOBUF_C__API
void protobuf_c_service_generated_init(
ProtobufCService *service, const ProtobufCServiceDescriptor *descriptor,
ProtobufCServiceDestroy destroy);
PROTOBUF_C__API
void protobuf_c_service_invoke_internal(ProtobufCService *service,
unsigned method_index,
const ProtobufCMessage *input,
ProtobufCClosure closure,
void *closure_data);
/**@}*/ /**@}*/
PROTOBUF_C__END_DECLS PROTOBUF_C__END_DECLS
......
...@@ -23,7 +23,7 @@ int main() { ...@@ -23,7 +23,7 @@ int main() {
// auto isok = paddle_mobile.Load(std::string(g_mobilenet_detect) + "/model", // auto isok = paddle_mobile.Load(std::string(g_mobilenet_detect) + "/model",
// std::string(g_mobilenet_detect) + "/params", true); // std::string(g_mobilenet_detect) + "/params", true);
auto isok = paddle_mobile.Load(g_nlp, true, false, true); auto isok = paddle_mobile.Load(g_nlp, true, false, 1, true);
// auto isok = paddle_mobile.Load(std::string(g_nlp) + "/model", // auto isok = paddle_mobile.Load(std::string(g_nlp) + "/model",
// std::string(g_nlp) + "/params", false); // std::string(g_nlp) + "/params", false);
......
...@@ -4,7 +4,8 @@ TOTAL_ERRORS=0 ...@@ -4,7 +4,8 @@ TOTAL_ERRORS=0
# The trick to remove deleted files: https://stackoverflow.com/a/2413151 # The trick to remove deleted files: https://stackoverflow.com/a/2413151
for file in $(git diff --cached --name-status | awk '$1 != "D" {print $2}' | \ for file in $(git diff --cached --name-status | awk '$1 != "D" {print $2}' | \
grep -v ".pb.cpp" | grep -v ".pb.h" | grep -v ".pb-c.h" | grep -v ".pb-c.c"); do grep -v ".pb.cpp" | grep -v ".pb.h" | grep -v ".pb-c.h" | grep -v ".pb-c.c" | \
grep -v "protobuf-c.h" | grep -v "protobuf-c.c"); do
cpplint $file; cpplint $file;
TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?); TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?);
done done
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册