Files
nanopb/pb_field.c

99 lines
3.7 KiB
C

#include "pb_field.h"
#ifdef __GNUC__
/* Verify that we remember to check all return values for proper error propagation */
#define checkreturn __attribute__((warn_unused_result))
#else
#define checkreturn
#endif
/**
* pb_common_aligned_field_info array holds the common field info that can be shared
* by any numeric fields whose previous field is memory aligned
*/
const pb_field_t pb_common_aligned_field_info[NUM_COMMON_FIELD_INFO] = {
/* REQUIRED bool */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_VARINT, 0, 0, sizeof(bool), 0, 0},
/* OPTIONAL bool */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_VARINT, 1, -1, sizeof(bool), 0, 0},
/* REQUIRED int32, uint32, enum */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_VARINT, 0, 0, sizeof(uint32_t), 0, 0},
/* OPTIONAL int32, uint32, enum */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_VARINT, 4, -4, sizeof(uint32_t), 0, 0},
/* REQUIRED int64, uint64 */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_VARINT, 0, 0, sizeof(uint64_t), 0, 0},
/* OPTIONAL int64, uint64 */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_VARINT, 4, -4, sizeof(uint64_t), 0, 0},
/* REQUIRED sint32 */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_SVARINT, 0, 0, sizeof(int32_t), 0, 0},
/* OPTIONAL sint32 */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_SVARINT, 4, -4, sizeof(int32_t), 0, 0},
/* REQUIRED sint64 */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_SVARINT, 0, 0, sizeof(int64_t), 0, 0},
/* OPTIONAL sint64 */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_SVARINT, 4, -4, sizeof(int64_t), 0, 0},
/* REQUIRED fixed32, sfixed32, float */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_FIXED32, 0, 0, sizeof(uint32_t), 0, 0},
/* OPTIONAL fixed32, sfixed32, float */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_FIXED32, 4, -4, sizeof(uint32_t), 0, 0},
/* REQUIRED fixed64, sfixed64, double */
{0, PB_HTYPE_REQUIRED | PB_LTYPE_FIXED64, 0, 0, sizeof(uint64_t), 0, 0},
/* OPTIONAL fixed64, sfixed64, double */
{0, PB_HTYPE_OPTIONAL | PB_LTYPE_FIXED64, 4, -4, sizeof(uint64_t), 0, 0}
};
void pb_field_init(pb_field_iterator_t *iter, const pb_field_info_t *fields, void *dest_struct)
{
if (fields->field_keys == NULL) return;
iter->start_key = iter->current_key = fields->field_keys;
iter->field_info = fields->field_info;
iter->current = *(PB_FIELD_INFO(iter->current_key, iter->field_info));
iter->current.tag = PB_TAG_VAL(iter->current_key);
iter->field_index = 0;
iter->pData = (char*)dest_struct + iter->current.data_offset;
iter->pSize = (char*)iter->pData + iter->current.size_offset;
iter->dest_struct = dest_struct;
}
bool pb_field_next(pb_field_iterator_t *iter)
{
bool notwrapped = true;
size_t prev_size = iter->current.data_size;
if (PB_HTYPE(iter->current.type) == PB_HTYPE_ARRAY)
prev_size *= iter->current.array_size;
iter->field_index++;
if (PB_IS_LAST(iter->current_key))
{
iter->current_key = iter->start_key;
iter->current = *(PB_FIELD_INFO(iter->current_key, iter->field_info));
iter->current.tag = PB_TAG_VAL(iter->current_key);
iter->field_index = 0;
iter->pData = iter->dest_struct;
prev_size = 0;
notwrapped = false;
} else {
iter->current_key++;
iter->current = *(PB_FIELD_INFO(iter->current_key, iter->field_info));
iter->current.tag = PB_TAG_VAL(iter->current_key);
}
iter->pData = (char*)iter->pData + prev_size + iter->current.data_offset;
iter->pSize = (char*)iter->pData + iter->current.size_offset;
return notwrapped;
}
bool checkreturn pb_field_find(pb_field_iterator_t *iter, int tag)
{
int start = iter->field_index;
do {
if (iter->current.tag == tag)
return true;
pb_field_next(iter);
} while (iter->field_index != start);
return false;
}