/* pb_decode.c -- decode a protobuf using minimal resources
*
* 2011 Petteri Aimonen <jpa@kapsi.fi>
*/
/* Use the GCC warn_unused_result attribute to check that all return values
* are propagated correctly. On other compilers and gcc before 3.4.0 just
* ignore the annotation.
*/
#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
#define checkreturn
#else
#define checkreturn __attribute__((warn_unused_result))
#endif
#include "pb.h"
#include "pb_decode.h"
#include "pb_common.h"
/**************************************
* Declarations internal to this file *
**************************************/
static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof);
static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size);
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension);
static bool pb_field_set_to_default(pb_field_iter_t *field);
static bool pb_message_set_to_defaults(pb_field_iter_t *iter);
static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field);
static bool checkreturn pb_skip_varint(pb_istream_t *stream);
static bool checkreturn pb_skip_string(pb_istream_t *stream);
#ifdef PB_ENABLE_MALLOC
static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size);
static void initialize_pointer_field(void *pItem, pb_field_iter_t *field);
static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field);
static void pb_release_single_field(pb_field_iter_t *field);
#endif
#ifdef PB_WITHOUT_64BIT
#define pb_int64_t int32_t
#define pb_uint64_t uint32_t
#else
#define pb_int64_t int64_t
#define pb_uint64_t uint64_t
#endif
typedef struct {
uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32];
} pb_fields_seen_t;
/*******************************
* pb_istream_t implementation *
*******************************/
static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
{
const pb_byte_t *source = (const pb_byte_t*)stream->state;
stream->state = (pb_byte_t*)stream->state + count;
if (buf != NULL)
{
memcpy(buf, source, count * sizeof(pb_byte_t));
}
return true;
}
bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
{
if (count == 0)
return true;
#ifndef PB_BUFFER_ONLY
if (buf == NULL && stream->callback != buf_read)
{
/* Skip input bytes */
pb_byte_t tmp[16];
while (count > 16)
{
if (!pb_read(stream, tmp, 16))
return false;
count -= 16;
}
return pb_read(stream, tmp, count);
}
#endif
if (stream->bytes_left < count)
PB_RETURN_ERROR(stream, "end-of-stream");
#ifndef PB_BUFFER_ONLY
if (!stream->callback(stream, buf, count))
PB_RETURN_ERROR(stream, "io error");
#else
if (!buf_read(stream, buf, count))
return false;
#endif
if (stream->bytes_left < count)
stream->bytes_left = 0;
else
stream->bytes_left -= count;
return true;
}
/* Read a single byte from input stream. buf may not be NULL.
* This is an optimization for the varint decoding. */
static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
{
if (stream->bytes_left == 0)
PB_RETURN_ERROR(stream, "end-of-stream");
#ifndef PB_BUFFER_ONLY
if (!stream->callback(stream, buf, 1))
PB_RETURN_ERROR(stream, "io error");
#else
*buf = *(const pb_byte_t*)stream->state;
stream->state = (pb_byte_t*)stream->state + 1;
#endif
stream->bytes_left--;
return true;
}
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen)
{
pb_istream_t stream;
/* Cast away the const from buf without a compiler error. We are
* careful to use it only in a const manner in the callbacks.
*/
union {
void *state;
const void *c_state;
} state;
#ifdef PB_BUFFER_ONLY
stream.callback = NULL;
#else
stream.callback = &buf_read;
#endif
state.c_state = buf;
stream.state = state.state;
stream.bytes_left = msglen;
#ifndef PB_NO_ERRMSG
stream.errmsg = NULL;
#endif
return stream;
}
/********************
* Helper functions *
********************/
static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof)
{
pb_byte_t byte;
uint32_t result;
if (!pb_readbyte(stream, &byte))
{
if (stream->bytes_left == 0)
{
if (eof)
{
*eof = true;
}
}
return false;
}
if ((byte & 0x80) == 0)
{
/* Quick case, 1 byte value */
result = byte;
}
else
{
/* Multibyte case */
uint_fast8_t bitpos = 7;
result = byte & 0x7F;
do
{
if (!pb_readbyte(stream, &byte))
return false;
if (bitpos >= 32)
{
/* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */
pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01;
bool valid_extension = ((byte & 0x7F) == 0x00 ||
((result >> 31) != 0 && byte == sign_extension));
if (bitpos >= 64 || !valid_extension)
{
PB_RETURN_ERROR(stream, "varint overflow");
}
}
else if (bitpos == 28)
{
if ((byte & 0x70) != 0 && (byte & 0x78) != 0x78)
{
PB_RETURN_ERROR(stream, "varint overflow");
}
result |= (uint32_t)(byte & 0x0F) << bitpos;
}
else
{
result |= (uint32_t)(byte & 0x7F) << bitpos;
}
bitpos = (uint_fast8_t)(bitpos + 7);
} while (byte & 0x80);
}
*dest = result;
return true;
}
bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
{
return pb_decode_varint32_eof(stream, dest, NULL);
}
#ifndef PB_WITHOUT_64BIT
bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
{
pb_byte_t byte;
uint_fast8_t bitpos = 0;
uint64_t result = 0;
do
{
if (!pb_readbyte(str
没有合适的资源?快使用搜索试试~ 我知道了~
详解protobuf-c之在C语言中如何使用repeated生成数组和字符串(包含配置pb-callback-t)
共55个文件
c:20个
h:20个
proto:4个
0 下载量 41 浏览量
2024-05-22
17:40:06
上传
评论
收藏 62KB 7Z 举报
温馨提示
测试用例
资源推荐
资源详情
资源评论
收起资源包目录
Protobuf_pb_callback_t.7z (55个子文件)
Protobuf_pb_callback_t
float
.vscode
settings.json 246B
pb_decode.c 54KB
pb_decode.h 7KB
student.pb.c 581B
pb.h 44KB
student.proto 170B
pb_common.c 12KB
student.options 31B
main.exe 66KB
student.pb.h 2KB
pb_encode.c 31KB
pb_encode.h 7KB
main.c 5KB
pb_common.h 2KB
int
.vscode
settings.json 246B
pb_decode.c 54KB
pb_decode.h 7KB
student.pb.c 276B
pb.h 44KB
student.proto 163B
pb_common.c 12KB
student.options 31B
main.exe 66KB
student.pb.h 2KB
pb_encode.c 31KB
pb_encode.h 7KB
main.c 5KB
pb_common.h 2KB
string
.vscode
settings.json 246B
pb_decode.c 54KB
pb_decode.h 7KB
student.pb.c 276B
pb.h 44KB
student.proto 130B
pb_common.c 12KB
main.exe 66KB
student.pb.h 2KB
pb_encode.c 31KB
pb_encode.h 7KB
main.c 4KB
pb_common.h 2KB
struct
.vscode
settings.json 246B
pb_decode.c 54KB
pb_decode.h 7KB
student.pb.c 326B
pb.h 44KB
student.proto 237B
pb_common.c 12KB
student.options 67B
main.exe 66KB
student.pb.h 2KB
pb_encode.c 31KB
pb_encode.h 7KB
main.c 5KB
pb_common.h 2KB
共 55 条
- 1
资源评论
Troubadour~
- 粉丝: 88
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功