/*
* Copyright (c) 2020 YuQing <384681@qq.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
//sf_serialize.h
#ifndef _SF_SERIALIZE_H
#define _SF_SERIALIZE_H
#include "fastcommon/common_define.h"
#include "fastcommon/fast_buffer.h"
#include "fastcommon/hash.h"
#define SF_SERIALIZE_VALUE_TYPE_COUNT 8
typedef enum {
sf_serialize_value_type_int8 = 0,
sf_serialize_value_type_int16,
sf_serialize_value_type_int32,
sf_serialize_value_type_int64,
sf_serialize_value_type_string,
sf_serialize_value_type_int32_array,
sf_serialize_value_type_int64_array,
sf_serialize_value_type_map
} SFSerializeValueType;
typedef struct sf_serialize_pack_header {
char length[4];
char crc32[4];
} SFSerializePackHeader;
typedef struct sf_serialize_pack_field_info {
unsigned char id;
unsigned char type;
} SFSerializePackFieldInfo;
typedef struct sf_serialize_pack_field_int8 {
SFSerializePackFieldInfo field;
char value;
} SFSerializePackFieldInt8;
typedef struct sf_serialize_pack_field_int16 {
SFSerializePackFieldInfo field;
char value[2];
} SFSerializePackFieldInt16;
typedef struct sf_serialize_pack_field_int32 {
SFSerializePackFieldInfo field;
char value[4];
} SFSerializePackFieldInt32;
typedef struct sf_serialize_pack_field_int64 {
SFSerializePackFieldInfo field;
char value[8];
} SFSerializePackFieldInt64;
typedef struct sf_serialize_pack_string_value {
char len[4];
char str[0];
} SFSerializePackStringValue;
typedef struct sf_serialize_pack_field_string {
SFSerializePackFieldInfo field;
SFSerializePackStringValue value;
} SFSerializePackFieldString;
typedef struct sf_serialize_pack_field_array {
SFSerializePackFieldInfo field;
struct {
char count[4];
char ptr[0];
} value;
} SFSerializePackFieldArray;
#define SF_SERIALIZE_PACK_HEADER_SIZE sizeof(SFSerializePackHeader)
typedef struct sf_serialize_field_value {
unsigned char fid;
SFSerializeValueType type;
union {
int64_t n;
string_t s;
int64_array_t int_array;
key_value_array_t kv_array;
} 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
static inline void sf_serialize_pack_begin(FastBuffer *buffer)
{
buffer->length = SF_SERIALIZE_PACK_HEADER_SIZE;
}
static inline int sf_serialize_pack_int8(FastBuffer *buffer,
const unsigned char fid, const int8_t value)
{
int result;
SFSerializePackFieldInt8 *obj;
if ((result=fast_buffer_check_inc_size(buffer,
sizeof(SFSerializePackFieldInt8))) != 0)
{
return result;
}
obj = (SFSerializePackFieldInt8 *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_int8;
obj->value = value;
buffer->length += sizeof(SFSerializePackFieldInt8);
return 0;
}
static inline int sf_serialize_pack_int16(FastBuffer *buffer,
const unsigned char fid, const int16_t value)
{
int result;
SFSerializePackFieldInt16 *obj;
if ((result=fast_buffer_check_inc_size(buffer,
sizeof(SFSerializePackFieldInt16))) != 0)
{
return result;
}
obj = (SFSerializePackFieldInt16 *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_int16;
short2buff(value, obj->value);
buffer->length += sizeof(SFSerializePackFieldInt16);
return 0;
}
static inline int sf_serialize_pack_int32(FastBuffer *buffer,
const unsigned char fid, const int32_t value)
{
int result;
SFSerializePackFieldInt32 *obj;
if ((result=fast_buffer_check_inc_size(buffer,
sizeof(SFSerializePackFieldInt32))) != 0)
{
return result;
}
obj = (SFSerializePackFieldInt32 *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_int32;
int2buff(value, obj->value);
buffer->length += sizeof(SFSerializePackFieldInt32);
return 0;
}
static inline int sf_serialize_pack_int64(FastBuffer *buffer,
const unsigned char fid, const int64_t value)
{
int result;
SFSerializePackFieldInt64 *obj;
if ((result=fast_buffer_check_inc_size(buffer,
sizeof(SFSerializePackFieldInt64))) != 0)
{
return result;
}
obj = (SFSerializePackFieldInt64 *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_int64;
long2buff(value, obj->value);
buffer->length += sizeof(SFSerializePackFieldInt64);
return 0;
}
#define SF_SERIALIZE_PACK_STRING(ps, value) \
int2buff((value)->len, (ps)->len); \
memcpy((ps)->str, (value)->str, (value)->len)
#define SF_SERIALIZE_PACK_STRING_AND_MOVE_PTR(ps, value) \
SF_SERIALIZE_PACK_STRING(ps, value); \
ps = (SFSerializePackStringValue *)(((char *)ps) + sizeof( \
SFSerializePackStringValue) + (value)->len)
static inline int sf_serialize_pack_string(FastBuffer *buffer,
const unsigned char fid, const string_t *value)
{
int result;
int length;
SFSerializePackFieldString *obj;
length = sizeof(SFSerializePackFieldString) + value->len;
if ((result=fast_buffer_check_inc_size(buffer, length)) != 0) {
return result;
}
obj = (SFSerializePackFieldString *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_string;
SF_SERIALIZE_PACK_STRING(&obj->value, value);
buffer->length += length;
return 0;
}
static inline int sf_serialize_pack_int32_array(FastBuffer *buffer,
const unsigned char fid, const int32_t *array, const int count)
{
int result;
int length;
SFSerializePackFieldArray *obj;
const int32_t *pn;
const int32_t *end;
char *ps;
length = sizeof(SFSerializePackFieldArray) + count * 4;
if ((result=fast_buffer_check_inc_size(buffer, length)) != 0) {
return result;
}
obj = (SFSerializePackFieldArray *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_int32_array;
int2buff(count, obj->value.count);
end = array + count;
for (pn=array, ps=obj->value.ptr; pnlength += length;
return 0;
}
static inline int sf_serialize_pack_int64_array(FastBuffer *buffer,
const unsigned char fid, const int64_t *array, const int count)
{
int result;
int length;
SFSerializePackFieldArray *obj;
const int64_t *pn;
const int64_t *end;
char *ps;
length = sizeof(SFSerializePackFieldArray) + count * 8;
if ((result=fast_buffer_check_inc_size(buffer, length)) != 0) {
return result;
}
obj = (SFSerializePackFieldArray *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_int64_array;
long2buff(count, obj->value.count);
end = array + count;
for (pn=array, ps=obj->value.ptr; pnlength += length;
return 0;
}
static inline int sf_serialize_pack_map(FastBuffer *buffer,
const unsigned char fid, const key_value_pair_t *kv_pairs,
const int count)
{
int result;
int length;
SFSerializePackFieldArray *obj;
const key_value_pair_t *pair;
const key_value_pair_t *end;
SFSerializePackStringValue *ps;
length = sizeof(SFSerializePackFieldArray);
end = kv_pairs + count;
for (pair=kv_pairs; pairkey.len + pair->value.len;
}
if ((result=fast_buffer_check_inc_size(buffer, length)) != 0) {
return result;
}
obj = (SFSerializePackFieldArray *)(buffer->data + buffer->length);
obj->field.id = fid;
obj->field.type = sf_serialize_value_type_map;
long2buff(count, obj->value.count);
ps = (SFSerializePackStringValue *)obj->value.ptr;
for (pair=kv_pairs; pairkey);
SF_SERIALIZE_PACK_STRING_AND_MOVE_PTR(ps, &pair->value);
}
buffer->length += length;
return 0;
}
static inline void sf_serialize_pack_end(FastBuffer *buffer)
{
SFSerializePackHeader *header;
int length;
int crc32;
header = (SFSerializePackHeader *)buffer->data;
length = buffer->length - sizeof(SFSerializePackHeader);
crc32 = CRC32(header + 1, length);
int2buff(length, header->length);
int2buff(crc32, header->crc32);
}
static inline void sf_serialize_iterator_init(SFSerializeIterator *it)
{
memset(it, 0, sizeof(SFSerializeIterator));
}
static inline void sf_serialize_iterator_destroy(SFSerializeIterator *it)
{
if (it->int_array.elts != NULL) {
free(it->int_array.elts);
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);
const SFSerializeFieldValue *sf_serialize_next(SFSerializeIterator *it);
#ifdef __cplusplus
}
#endif
#endif