sf_serialize_unpack integer and string impl
parent
186d41fafe
commit
c529c5ab8c
|
|
@ -26,3 +26,176 @@
|
|||
#include "fastcommon/shared_func.h"
|
||||
#include "fastcommon/logger.h"
|
||||
#include "sf_serialize.h"
|
||||
|
||||
int sf_serialize_unpack(SFSerializeIterator *it, const string_t *content)
|
||||
{
|
||||
SFSerializePackHeader *header;
|
||||
int length;
|
||||
int calc_crc32;
|
||||
int header_crc32;
|
||||
|
||||
if (content->len < sizeof(SFSerializePackHeader)) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"content length: %d is too small which < %d",
|
||||
content->len, (int)sizeof(SFSerializePackHeader));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
header = (SFSerializePackHeader *)content->str;
|
||||
length = buff2int(header->length);
|
||||
if (content->len != length + sizeof(SFSerializePackHeader)) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"content length: %d != %d", content->len,
|
||||
(int)(length + sizeof(SFSerializePackHeader)));
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
calc_crc32 = CRC32(header + 1, length);
|
||||
header_crc32 = buff2int(header->crc32);
|
||||
if (header_crc32 != calc_crc32) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"header crc32: %d != calculated: %d",
|
||||
header_crc32, calc_crc32);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
it->p = (const char *)(header + 1);
|
||||
it->end = content->str + content->len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_field_type(SFSerializeIterator *it,
|
||||
const int remain_len, const SFSerializeValueType type)
|
||||
{
|
||||
int min_size;
|
||||
|
||||
switch (type) {
|
||||
case sf_serialize_value_type_int8:
|
||||
min_size = sizeof(SFSerializePackFieldInt8);
|
||||
break;
|
||||
case sf_serialize_value_type_int16:
|
||||
min_size = sizeof(SFSerializePackFieldInt16);
|
||||
break;
|
||||
case sf_serialize_value_type_int32:
|
||||
min_size = sizeof(SFSerializePackFieldInt32);
|
||||
break;
|
||||
case sf_serialize_value_type_int64:
|
||||
min_size = sizeof(SFSerializePackFieldInt64);
|
||||
break;
|
||||
case sf_serialize_value_type_string:
|
||||
min_size = sizeof(SFSerializePackFieldString);
|
||||
break;
|
||||
case sf_serialize_value_type_int32_array:
|
||||
case sf_serialize_value_type_int64_array:
|
||||
case sf_serialize_value_type_map:
|
||||
min_size = sizeof(SFSerializePackFieldArray);
|
||||
break;
|
||||
default:
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"unknown type: %d", type);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (remain_len < min_size) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"remain length: %d is too small which < %d",
|
||||
remain_len, min_size);
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_string_value(SFSerializeIterator *it,
|
||||
const int remain_len, const string_t *s)
|
||||
{
|
||||
if (s->len < 0) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"invalid string length: %d < 0", s->len);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (s->len > remain_len) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"string length: %d is too large > remain length: %d",
|
||||
s->len, remain_len);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const SFSerializeFieldValue *sf_serialize_next(SFSerializeIterator *it)
|
||||
{
|
||||
int remain_len;
|
||||
SFSerializePackFieldInfo *field;
|
||||
SFSerializePackFieldString *fs;
|
||||
|
||||
remain_len = it->end - it->p;
|
||||
if (remain_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (remain_len <= sizeof(SFSerializePackFieldInfo)) {
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"remain length: %d is too small which <= %d",
|
||||
remain_len, (int)sizeof(SFSerializePackFieldInfo));
|
||||
it->error_no = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
field = (SFSerializePackFieldInfo *)it->p;
|
||||
|
||||
it->field.fid = field->id;
|
||||
it->field.type = field->type;
|
||||
if ((it->error_no=check_field_type(it, remain_len, field->type)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (field->type) {
|
||||
case sf_serialize_value_type_int8:
|
||||
it->field.value.n = ((SFSerializePackFieldInt8 *)it->p)->value;
|
||||
it->p += sizeof(SFSerializePackFieldInt8);
|
||||
break;
|
||||
case sf_serialize_value_type_int16:
|
||||
it->field.value.n = buff2short(
|
||||
((SFSerializePackFieldInt16 *)
|
||||
it->p)->value);
|
||||
it->p += sizeof(SFSerializePackFieldInt16);
|
||||
break;
|
||||
case sf_serialize_value_type_int32:
|
||||
it->field.value.n = buff2int(
|
||||
((SFSerializePackFieldInt32 *)
|
||||
it->p)->value);
|
||||
it->p += sizeof(SFSerializePackFieldInt32);
|
||||
break;
|
||||
case sf_serialize_value_type_int64:
|
||||
it->field.value.n = buff2long(
|
||||
((SFSerializePackFieldInt64 *)
|
||||
it->p)->value);
|
||||
it->p += sizeof(SFSerializePackFieldInt64);
|
||||
break;
|
||||
case sf_serialize_value_type_string:
|
||||
fs = (SFSerializePackFieldString *)it->p;
|
||||
it->field.value.s.len = buff2int(fs->value.len);
|
||||
it->field.value.s.str = fs->value.str;
|
||||
if ((it->error_no=check_string_value(it, remain_len -
|
||||
sizeof(SFSerializePackFieldString),
|
||||
&it->field.value.s)) != 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
it->p += sizeof(SFSerializePackFieldString) +
|
||||
it->field.value.s.len;
|
||||
break;
|
||||
case sf_serialize_value_type_int32_array:
|
||||
case sf_serialize_value_type_int64_array:
|
||||
case sf_serialize_value_type_map:
|
||||
default:
|
||||
snprintf(it->error_info, sizeof(it->error_info),
|
||||
"unknown type: %d", field->type);
|
||||
it->error_no = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &it->field;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,12 +83,6 @@ typedef struct sf_serialize_pack_field_array {
|
|||
|
||||
#define SF_SERIALIZE_PACK_HEADER_SIZE sizeof(SFSerializePackHeader)
|
||||
|
||||
typedef struct sf_serialize_iterator {
|
||||
const char *p;
|
||||
int64_array_t int_array;
|
||||
key_value_array_t kv_array;
|
||||
} SFSerializeIterator;
|
||||
|
||||
typedef struct sf_serialize_field_value {
|
||||
unsigned char fid;
|
||||
SFSerializeValueType type;
|
||||
|
|
@ -100,6 +94,18 @@ typedef struct sf_serialize_field_value {
|
|||
} value;
|
||||
} SFSerializeFieldValue;
|
||||
|
||||
typedef struct sf_serialize_iterator {
|
||||
const char *p;
|
||||
const char *end;
|
||||
int64_array_t int_array;
|
||||
key_value_array_t kv_array;
|
||||
int int_array_alloc;
|
||||
int kv_array_alloc;
|
||||
SFSerializeFieldValue field;
|
||||
int error_no;
|
||||
char error_info[256];
|
||||
} SFSerializeIterator;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -321,13 +327,27 @@ static inline void sf_serialize_pack_end(FastBuffer *buffer)
|
|||
int2buff(crc32, header->crc32);
|
||||
}
|
||||
|
||||
int sf_serialize_iterator_init(SFSerializeIterator *it);
|
||||
static inline void sf_serialize_iterator_init(SFSerializeIterator *it)
|
||||
{
|
||||
memset(it, 0, sizeof(SFSerializeIterator));
|
||||
}
|
||||
|
||||
void sf_serialize_iterator_destroy(SFSerializeIterator *it);
|
||||
static inline void sf_serialize_iterator_destroy(SFSerializeIterator *it)
|
||||
{
|
||||
if (it->int_array.values != NULL) {
|
||||
free(it->int_array.values);
|
||||
it->int_array_alloc = 0;
|
||||
}
|
||||
|
||||
if (it->kv_array.kv_pairs != NULL) {
|
||||
free(it->kv_array.kv_pairs);
|
||||
it->kv_array_alloc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int sf_serialize_unpack(SFSerializeIterator *it, const string_t *content);
|
||||
|
||||
int sf_serialize_next(SFSerializeIterator *it, SFSerializeFieldValue *field);
|
||||
const SFSerializeFieldValue *sf_serialize_next(SFSerializeIterator *it);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue