sf_serialize_unpack integer and string impl
parent
186d41fafe
commit
c529c5ab8c
|
|
@ -26,3 +26,176 @@
|
||||||
#include "fastcommon/shared_func.h"
|
#include "fastcommon/shared_func.h"
|
||||||
#include "fastcommon/logger.h"
|
#include "fastcommon/logger.h"
|
||||||
#include "sf_serialize.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)
|
#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 {
|
typedef struct sf_serialize_field_value {
|
||||||
unsigned char fid;
|
unsigned char fid;
|
||||||
SFSerializeValueType type;
|
SFSerializeValueType type;
|
||||||
|
|
@ -100,6 +94,18 @@ typedef struct sf_serialize_field_value {
|
||||||
} value;
|
} value;
|
||||||
} SFSerializeFieldValue;
|
} 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -321,13 +327,27 @@ static inline void sf_serialize_pack_end(FastBuffer *buffer)
|
||||||
int2buff(crc32, header->crc32);
|
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_unpack(SFSerializeIterator *it, const string_t *content);
|
||||||
|
|
||||||
int sf_serialize_next(SFSerializeIterator *it, SFSerializeFieldValue *field);
|
const SFSerializeFieldValue *sf_serialize_next(SFSerializeIterator *it);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue