blob: 5534562296f0ba3c4e3c5b8360dc3f2766e7682c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//
// Created by furture on 2017/8/4.
//
#include "wson.h"
#include <stdio.h>
union double_number{
double d;
uint64_t l;
int64_t i64;
};
union float_number{
float f;
uint32_t i;
};
#define WSON_BUFFER_SIZE 1024
#define WSON_BUFFER_ENSURE_SIZE(size) {if((buffer->length) < (buffer->position + (size))){\
msg_buffer_resize(buffer, (uint32_t)(size));\
}}
static inline void msg_buffer_resize(wson_buffer* buffer, uint32_t size){
if(size < buffer->length){
if(buffer->length < 1024*16){
size = 1024*16;
}else{
size = buffer->length;
}
}else{
size +=WSON_BUFFER_SIZE;
}
size += buffer->length;
buffer->data = realloc(buffer->data, size);
buffer->length = size;
}
static inline int32_t msg_buffer_varint_Zag(uint32_t ziggedValue)
{
int32_t value = (int32_t)ziggedValue;
return (-(value & 0x01)) ^ ((value >> 1) & ~( 1<< 31));
}
static inline uint32_t msg_buffer_varint_Zig(int32_t value)
{
return (uint32_t)((value << 1) ^ (value >> 31));
}
wson_buffer* wson_buffer_new(void){
wson_buffer* ptr = malloc(sizeof(wson_buffer));
ptr->data = malloc(sizeof(int8_t)*WSON_BUFFER_SIZE);
ptr->position = 0;
ptr->length = WSON_BUFFER_SIZE;
return ptr;
}
wson_buffer* wson_buffer_from(void* data, uint32_t length){
wson_buffer* ptr = malloc(sizeof(wson_buffer));
ptr->data = data;
ptr->position = 0;
ptr->length = length;
return ptr;
}
inline void wson_buffer_require(wson_buffer *buffer, size_t size){
WSON_BUFFER_ENSURE_SIZE(size*sizeof(uint8_t));
}
inline void wson_push_int(wson_buffer *buffer, int32_t value){
uint32_t num = msg_buffer_varint_Zig(value);
wson_push_uint(buffer, num);
}
inline void wson_push_uint(wson_buffer *buffer, uint32_t num){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint32_t) + sizeof(uint8_t));
uint8_t * data = ((uint8_t*)buffer->data + buffer->position);
int size =0;
do{
data[size] = (uint8_t)((num & 0x7F) | 0x80);
size++;
}while((num >>= 7) != 0);
data[size - 1] &=0x7F;
buffer->position += size;
}
inline void wson_push_byte(wson_buffer *buffer, uint8_t bt){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = bt;
buffer->position += sizeof(uint8_t);
}
inline void wson_push_type(wson_buffer *buffer, uint8_t bt){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = bt;
buffer->position += sizeof(uint8_t);
}
inline void wson_push_type_boolean(wson_buffer *buffer, uint8_t value){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t) + sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
if(value){
*data = WSON_BOOLEAN_TYPE_TRUE;
}else{
*data = WSON_BOOLEAN_TYPE_FALSE;
}
buffer->position += sizeof(uint8_t);
}
inline void wson_push_type_int(wson_buffer *buffer, int32_t num){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_NUMBER_INT_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_int(buffer, num);
}
inline void wson_push_type_double(wson_buffer *buffer, double num){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_NUMBER_DOUBLE_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_double(buffer, num);
}
inline void wson_push_type_float(wson_buffer *buffer, float num) {
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_NUMBER_FLOAT_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_float(buffer, num);
}
inline void wson_push_type_long(wson_buffer *buffer, int64_t num){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_NUMBER_LONG_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_ulong(buffer, num);
}
inline void wson_push_type_string(wson_buffer *buffer, const void *src, int32_t length){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_STRING_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_uint(buffer, length);
wson_push_bytes(buffer, src, length);
}
inline void wson_push_type_uint8_string(wson_buffer *buffer, const uint8_t *src, int32_t length){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_UINT8_STRING_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_uint(buffer, length);
wson_push_bytes(buffer, src, length);
}
inline void wson_push_property(wson_buffer *buffer, const void *src, int32_t length){
wson_push_uint(buffer, length);
wson_push_bytes(buffer, src, length);
}
inline void wson_push_type_string_length(wson_buffer *buffer, int32_t length){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_STRING_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_uint(buffer, length);
}
inline void wson_push_type_null(wson_buffer *buffer){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_NULL_TYPE;
buffer->position += (sizeof(uint8_t));
}
inline void wson_push_type_map(wson_buffer *buffer, uint32_t size){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_MAP_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_uint(buffer, size);
}
inline void wson_push_type_array(wson_buffer *buffer, uint32_t size){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_ARRAY_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_uint(buffer, size);
}
inline void wson_push_type_extend(wson_buffer *buffer, const void *src, int32_t length){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
*data = WSON_EXTEND_TYPE;
buffer->position += (sizeof(uint8_t));
wson_push_uint(buffer, length);
wson_push_bytes(buffer, src, length);
}
inline void wson_push_ensure_size(wson_buffer *buffer, uint32_t dataSize){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint8_t)*dataSize);
}
inline void wson_push_ulong(wson_buffer *buffer, uint64_t num){
WSON_BUFFER_ENSURE_SIZE(sizeof(uint64_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
data[7] = (uint8_t)(num & 0xFF);
data[6] = (uint8_t)((num >> 8) & 0xFF);
data[5] = (uint8_t)((num >> 16) & 0xFF);
data[4] = (uint8_t)((num >> 24) & 0xFF);
data[3] = (uint8_t)((num >> 32) & 0xFF);
data[2] = (uint8_t)((num >> 40) & 0xFF);
data[1] = (uint8_t)((num >> 48) & 0xFF);
data[0] = (uint8_t)((num >> 56) & 0xFF);
buffer->position += sizeof(uint64_t);
}
void wson_push_double(wson_buffer *buffer, double num){
union double_number ld;
ld.d = num;
wson_push_ulong(buffer, ld.l);
}
void wson_push_float(wson_buffer *buffer, float f){
union float_number fn;
fn.f = f;
uint32_t num = fn.i;
WSON_BUFFER_ENSURE_SIZE(sizeof(uint32_t));
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
data[3] = (uint8_t)(num & 0xFF);
data[2] = (uint8_t)((num >> 8) & 0xFF);
data[1] = (uint8_t)((num >> 16) & 0xFF);
data[0] = (uint8_t)((num >> 24) & 0xFF);
buffer->position += sizeof(uint32_t);
}
inline void wson_push_bytes(wson_buffer *buffer, const void *src, int32_t length){
WSON_BUFFER_ENSURE_SIZE(length);
void* dst = ((uint8_t*)buffer->data + buffer->position);
memcpy(dst, src, length);
buffer->position += length;
}
inline int8_t wson_next_type(wson_buffer *buffer){
int8_t* ptr = (int8_t*)((uint8_t*)buffer->data + buffer->position);
buffer->position += sizeof(int8_t);
return *ptr;
}
inline int8_t wson_next_byte(wson_buffer *buffer){
int8_t* ptr = (int8_t*)(((uint8_t*)buffer->data + buffer->position));
buffer->position += sizeof(int8_t);
return *ptr;
}
int32_t wson_next_int(wson_buffer *buffer){
return msg_buffer_varint_Zag(wson_next_uint(buffer));
}
uint32_t wson_next_uint(wson_buffer *buffer){
uint8_t * ptr = ((uint8_t*)buffer->data + buffer->position);
uint32_t num = *ptr;
if((num & 0x80) == 0){
buffer->position +=1;
return num;
}
num &=0x7F;
uint8_t chunk = ptr[1];
num |= (chunk & 0x7F) << 7;
if((chunk & 0x80) == 0){
buffer->position += 2;
return num;
}
chunk = ptr[2];
num |= (chunk & 0x7F) << 14;
if((chunk & 0x80) == 0){
buffer->position += 3;
return num;
}
chunk = ptr[3];
num |= (chunk & 0x7F) << 21;
if((chunk & 0x80) == 0){
buffer->position += 4;
return num;
}
chunk = ptr[4];
num |= (chunk & 0x0F) << 28;
buffer->position += 5;
return num;
}
int64_t wson_next_long(wson_buffer *buffer){
return wson_next_ulong(buffer);
}
inline uint64_t wson_next_ulong(wson_buffer *buffer){
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
buffer->position += sizeof(uint64_t);
return (((uint64_t)data[7]) & 0xFF)
+ ((((uint64_t)data[6]) & 0xFF) << 8)
+ ((((uint64_t)data[5]) & 0xFF) << 16)
+ ((((uint64_t)data[4]) & 0xFF) << 24)
+ ((((uint64_t)data[3]) & 0xFF) << 32)
+ ((((uint64_t)data[2]) & 0xFF) << 40)
+ ((((uint64_t)data[1]) & 0xFF) << 48)
+ ((((uint64_t)data[0]) & 0xFF) << 56);
}
double wson_next_double(wson_buffer *buffer){
union double_number ld;
ld.l = wson_next_long(buffer);
return ld.d;
}
inline float wson_next_float(wson_buffer *buffer){
union float_number fn;
uint8_t* data = ((uint8_t*)buffer->data + buffer->position);
fn.i = ((data[3]) & 0xFF)
+ (((data[2]) & 0xFF) << 8)
+ (((data[1]) & 0xFF) << 16)
+ (((data[0]) & 0xFF) << 24);
buffer->position += sizeof(uint32_t);
return fn.f;
}
inline uint8_t* wson_next_bts(wson_buffer *buffer, uint32_t length){
uint8_t * ptr = ((uint8_t*)buffer->data + buffer->position);
buffer->position += length;
return ptr;
}
void wson_buffer_free(wson_buffer *buffer){
if(buffer->data){
free(buffer->data);
buffer->data = NULL;
}
if(buffer){
free(buffer);
buffer = NULL;
}
}