summaryrefslogtreecommitdiff
path: root/include/lib/ubjson/ubj_internal.h
blob: fc6169793432418d1e09bc3adbdddfad63f47f0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#ifndef UBJ_INTERNAL_H
#define UBJ_INTERNAL_H

#include "ubj.h"
#include <stdlib.h>
#include <string.h>

#if _MSC_VER
#define inline __inline
#endif


static const uint8_t UBJI_TYPEC_convert[UBJ_NUM_TYPES] = "\x00ZNTFCSHiUIlLdD[{";

static const int UBJI_TYPE_size[UBJ_NUM_TYPES] =
	{ -1,	 //MIXED
	0,	 //NULLTYPE
	0,	 //NOOP
	0,   //BOOL_TRUE
	0,   //BOOL_FALSE
	1,   //CHAR
	sizeof(const char*), //STRING
	sizeof(const char*), //high-precision
	1,					//INT8
	1,					//UINT8
	2,					//int16
	4,					//int32
	8,					//int64
	4,					//float32
	8,					//float64
	-1,					//array
	-1					//object
	};

static const size_t UBJR_TYPE_localsize[UBJ_NUM_TYPES] =
{
	sizeof(ubjr_dynamic_t),	 //MIXED
	0,	 //NULLTYPE
	0,	 //NOOP
	0,   //BOOL_TRUE
	0,   //BOOL_FALSE
	sizeof(ubjr_string_t),   //CHAR
	sizeof(ubjr_string_t), //STRING
	sizeof(ubjr_string_t), //high-precision
	sizeof(int8_t),					//INT8
	sizeof(uint8_t),					//UINT8
	sizeof(int16_t),					//int16
	sizeof(int32_t),					//int32
	sizeof(int64_t),					//int64
	sizeof(float),					//float32
	sizeof(double),					//float64
	sizeof(ubjr_array_t),					//array
	sizeof(ubjr_object_t)					//object
};

static inline void _to_bigendian16(uint8_t* outbuffer, uint16_t input)
{
	*outbuffer++ = (input >> 8); // Get top order byte (guaranteed endian-independent since machine registers)
	*outbuffer++ = input & 0xFF; // Get bottom order byte
}
static inline void _to_bigendian32(uint8_t* outbuffer, uint32_t input)
{
	_to_bigendian16(outbuffer, (uint16_t)(input >> 16)); // Get top order 2 bytes
	_to_bigendian16(outbuffer + 2, (uint16_t)(input & 0xFFFF)); // Get bottom order 2 bytes
}
static inline void _to_bigendian64(uint8_t* outbuffer, uint64_t input)
{
	_to_bigendian32(outbuffer, (uint32_t)(input >> 32));
	_to_bigendian32(outbuffer + 4, (uint32_t)(input & 0xFFFFFFFF));
}

static inline uint8_t _is_bigendian()
{
	int i = 1;
	char *low = (char*)&i;
	return *low ? 0 : 1;
}

#define BUF_BIG_ENDIAN_SWAP(type,func,ptr,num)  \
	{											\
		size_t i;type* d = (type*)ptr; 					\
		for (i = 0; i < num; i++)				\
		{										\
			func((uint8_t*)&d[i], d[i]);		\
		}										\
	}											\

static inline void buf_endian_swap(uint8_t* buf, size_t sz, size_t n)
{
	if (!_is_bigendian())
	{
		switch (sz)
		{
		case 1:
		case 0:
			break;
		case 2:
			BUF_BIG_ENDIAN_SWAP(uint16_t, _to_bigendian16,buf,n);
			break;
		case 4:
			BUF_BIG_ENDIAN_SWAP(uint32_t, _to_bigendian32,buf,n);
			break;
		case 8:
			BUF_BIG_ENDIAN_SWAP(uint64_t, _to_bigendian64,buf,n);
			break;
		};
	}
}

//warning...null-terminated strings are assumed...when this is not necessarily valid. FIXED: we don't use null-terminated strings in the reader (NOT FIXED...string type is awkward)
static inline ubjr_dynamic_t priv_ubjr_pointer_to_dynamic(UBJ_TYPE typ, const void* dat)
{
	ubjr_dynamic_t outdyn;
	outdyn.type = typ;
	size_t n = 1;
	switch (typ)
	{
	case UBJ_NULLTYPE:
	case UBJ_NOOP:
		break;
	case UBJ_BOOL_TRUE:
	case UBJ_BOOL_FALSE:
		outdyn.boolean = (typ == UBJ_BOOL_TRUE ? 1 : 0);
		break;
	case UBJ_HIGH_PRECISION:
	case UBJ_STRING:
	case UBJ_CHAR://possibly if char allocate, otherwise don't
		outdyn.string = *(const ubjr_string_t*)dat;
		break;
	case UBJ_INT8:
		outdyn.integer = *(const int8_t*)dat;
		break;
	case UBJ_UINT8:
		outdyn.integer = *(const uint8_t*)dat;
		break;
	case UBJ_INT16:
		outdyn.integer = *(const int16_t*)dat;
		break;
	case UBJ_INT32:
		outdyn.integer = *(const int32_t*)dat;
		break;
	case UBJ_INT64:
		outdyn.integer = *(const int64_t*)dat;
		break;
	case UBJ_FLOAT32:
		outdyn.real = *(const float*)dat;
		break;
	case UBJ_FLOAT64:
		outdyn.real = *(const double*)dat;
		break;
	case UBJ_ARRAY:
		outdyn.container_array = *(const ubjr_array_t*)dat;
		break;
	case UBJ_OBJECT:
		outdyn.container_object = *(const ubjr_object_t*)dat;
		break;
	case UBJ_MIXED:
		outdyn = *(const ubjr_dynamic_t*)dat;
	};
	return outdyn;
}

#endif