bad char
[vg.git] / vg_msg.h
1 #pragma once
2 /*
3 * Example data:
4 * kvstr "someinfo"
5 * kvint 200
6 * frame "person"{
7 * name "jeff"
8 * country "england"
9 * }
10 * frame "building"{
11 * capacity 1000
12 * }
13 * frame "person"{
14 * country "wales"
15 * name "micheal"
16 * }
17 *
18 * Creating the data in code:
19 * -----------------------------------------------------------------------------
20 * u8 data_buf[512];
21 * vg_msg data;
22 * vg_msg_init( &data, data_buf, 512 );
23 *
24 * vg_msg_wkvstr( &data, "kvstr", "someinfo" );
25 * vg_msg_wkvu32( &data, "kvint", 200 );
26 *
27 * vg_msg_frame( &data, "person" );
28 * vg_msg_wkvstr( &data, "name", "jeff" );
29 * vg_msg_wkvstr( &data, "country", "england" );
30 * vg_msg_end_frame( &data );
31 *
32 * vg_msg_frame( &data, "building" );
33 * vg_msg_wkvu32( &data, "capacity", 1000 );
34 * vg_msg_end_frame( &data );
35 *
36 * vg_msg_frame( &data, "person" );
37 * vg_msg_wkvstr( &data, "country", "wales" );
38 * vg_msg_wkvstr( &data, "name", "micheal" );
39 * vg_msg_end_frame( &data );
40 *
41 * Saving the data out
42 * -----------------------------------------------------------------------------
43 *
44 * if( data.error == k_vg_msg_error_OK ){
45 * // write data_buf, for length data.cur
46 * }
47 *
48 * Load the data
49 * -----------------------------------------------------------------------------
50 *
51 * u8 data_buf[512];
52 * u32 data_len;
53 *
54 * // read data_buf and data_len
55 *
56 * vg_msg data;
57 * vg_msg_init( &data, data_buf, data_len );
58 *
59 *
60 * Reading data
61 * -----------------------------------------------------------------------------
62 *
63 * if( vg_msg_seekframe( &msg, "rows" ) ){
64 * while( vg_msg_seekframe( &msg, NULL ) ){
65 * vg_warn( "%s\n", vg_msg_readkvstr( &msg, "yedo" ) );
66 * vg_msg_skip_frame( &msg );
67 * }
68 * }
69 *
70 * Reading back the stream linearly
71 * -----------------------------------------------------------------------------
72 *
73 * vg_msg_cmd cmd;
74 * while( vg_msg_next( &data, &cmd ) ){
75 * if( cmd.code == k_vg_msg_frame ) printf( "{" );
76 * else if( cmd.code == k_vg_msg_endframe ) printf( "}" );
77 * esle if( cmd.code == k_vg_msg_kvstring )
78 * printf( "string: %s\n", cmd.value._buf );
79 * }
80 */
81
82 enum vg_msg_code{
83 /* low types */
84 k_vg_msg_end = 0,
85 k_vg_msg_frame = 1,
86 k_vg_msg_endframe = 2,
87 k_vg_msg_kv = 10,
88 k_vg_msg_kvstring = 11,
89 k_vg_msg_kvbin = 12,
90
91 /* variable sized types */
92 k_vg_msg_float = 0x40,
93 k_vg_msg_unsigned = 0x80,
94 k_vg_msg_signed = 0xC0,
95
96 /* masks */
97 k_vg_msg_array_count_bits = 0x3C,
98 k_vg_msg_type_size_bits = 0x03,
99 k_vg_msg_type_base_bits = 0xC0,
100 k_vg_msg_type_bits = k_vg_msg_type_base_bits|k_vg_msg_type_size_bits,
101
102 /* sizes */
103 k_vg_msg_8b = 0x00,
104 k_vg_msg_16b = 0x01,
105 k_vg_msg_32b = 0x02,
106 k_vg_msg_64b = 0x03,
107
108 /* common types */
109 k_vg_msg_u8 = k_vg_msg_unsigned|k_vg_msg_8b,
110 k_vg_msg_u16 = k_vg_msg_unsigned|k_vg_msg_16b,
111 k_vg_msg_u32 = k_vg_msg_unsigned|k_vg_msg_32b,
112 k_vg_msg_u64 = k_vg_msg_unsigned|k_vg_msg_64b,
113 k_vg_msg_i8 = k_vg_msg_signed |k_vg_msg_8b,
114 k_vg_msg_i16 = k_vg_msg_signed |k_vg_msg_16b,
115 k_vg_msg_i32 = k_vg_msg_signed |k_vg_msg_32b,
116 k_vg_msg_i64 = k_vg_msg_signed |k_vg_msg_64b,
117 k_vg_msg_f32 = k_vg_msg_float |k_vg_msg_32b,
118 k_vg_msg_f64 = k_vg_msg_float |k_vg_msg_64b,
119
120 k_vg_msg_v2f = k_vg_msg_float |k_vg_msg_32b | (1<<2),
121 k_vg_msg_v3f = k_vg_msg_float |k_vg_msg_32b | (2<<2),
122 k_vg_msg_v4f = k_vg_msg_float |k_vg_msg_32b | (3<<2)
123 };
124
125 typedef struct vg_msg vg_msg;
126 typedef struct vg_msg_cmd vg_msg_cmd;
127 typedef struct vg_msg_cursor vg_msg_cursor;
128 struct vg_msg
129 {
130 u32 max;
131 u8 *buf;
132
133 /* reading */
134 struct vg_msg_cursor
135 {
136 u32 co, depth;
137 }
138 cur;
139
140 enum vg_msg_error
141 {
142 k_vg_msg_error_OK,
143 k_vg_msg_error_unbalanced,
144 k_vg_msg_error_overflow,
145 k_vg_msg_error_unhandled_cmd
146 }
147 error;
148 };
149
150 struct vg_msg_cmd
151 {
152 u8 code;
153
154 const char *key;
155 u32 key_djb2;
156
157 const void *value;
158 u32 value_djb2;
159
160 u32 len; /* set if binary type */
161 };
162
163 void vg_msg_wbuf( vg_msg *msg, u8 *buf, u32 len );
164 void vg_msg_rbuf( vg_msg *msg, u8 *buf, u32 len );
165 void vg_msg_wstr( vg_msg *msg, const char *str );
166 const char *vg_msg_rstr( vg_msg *msg, u32 *djb2 );
167 void vg_msg_frame( vg_msg *msg, const char *name );
168 void vg_msg_end_frame( vg_msg *msg );
169 void vg_msg_wkvstr( vg_msg *msg, const char *key, const char *value );
170 void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len );
171 void vg_msg_wkvnum( vg_msg *msg, const char *key,
172 u8 type, u8 count, void *data );
173 u32 vg_msg_cmd_array_count( u8 code );
174 u32 vg_msg_cmd_type_size( u8 code );
175 u32 vg_msg_cmd_bytecount( u8 code );
176 u8 vg_msg_count_bits( u32 count );
177
178 void vg_msg_init( vg_msg *msg, u8 *buffer, u32 len );
179 int vg_msg_next( vg_msg *msg, vg_msg_cmd *cmd );
180 int vg_msg_skip_frame( vg_msg *msg );
181 int vg_msg_seekframe( vg_msg *msg, const char *name );
182 u64 vg_msg_cast_to_u64( const void *src, u8 src_base, u8 src_size );
183 i64 vg_msg_cast_to_i64( const void *src, u8 src_base, u8 src_size );
184 f64 vg_msg_cast_to_f64( const void *src, u8 src_base, u8 src_size );
185 void vg_msg_cast( const void *src, u8 src_code, void *dst, u8 dst_code );
186
187 int vg_msg_getkvcmd( vg_msg *msg, const char *key, vg_msg_cmd *cmd );
188
189 /*
190 * Read a integral KV out to dst, and perform conversion if needed
191 */
192 int vg_msg_getkvintg( vg_msg *msg, const char *key, u8 type, void *dst,
193 void *default_value );
194
195 /* helper for reading string kvs. returns NULL if not found */
196 const char *vg_msg_getkvstr( vg_msg *msg, const char *key );
197 int vg_msg_getkvvecf( vg_msg *msg, const char *key, u8 type,
198 void *v, void *default_value );
199 void vg_msg_print( vg_msg *msg, u32 len );