1 /*
2 * This file Copyright (C) 2008-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 */
8
9 #pragma once
10
11 #ifdef __cplusplus
12 extern "C"
13 {
14 #endif
15
16 #include <inttypes.h> /* for int64_t */
17 #include "quark.h"
18
19 struct evbuffer;
20
21 struct tr_error;
22
23 /**
24 * @addtogroup tr_variant Variant
25 *
26 * An object that acts like a union for
27 * integers, strings, lists, dictionaries, booleans, and floating-point numbers.
28 * The structure is named tr_variant due to the historical reason that it was
29 * originally tightly coupled with bencoded data. It currently supports
30 * being parsed from, and serialized to, both bencoded notation and json notation.
31 *
32 * @{
33 */
34
35 typedef enum
36 {
37 TR_STRING_TYPE_QUARK,
38 TR_STRING_TYPE_HEAP,
39 TR_STRING_TYPE_BUF
40 }
41 tr_string_type;
42
43 /* these are PRIVATE IMPLEMENTATION details that should not be touched.
44 * I'll probably change them just to break your code! HA HA HA!
45 * it's included in the header for inlining and composition */
46 struct tr_variant_string
47 {
48 tr_string_type type;
49 tr_quark quark;
50 size_t len;
51 union
52 {
53 char buf[16];
54 char const* str;
55 }
56 str;
57 };
58
59 /* these are PRIVATE IMPLEMENTATION details that should not be touched.
60 * I'll probably change them just to break your code! HA HA HA!
61 * it's included in the header for inlining and composition */
62 enum
63 {
64 TR_VARIANT_TYPE_INT = 1,
65 TR_VARIANT_TYPE_STR = 2,
66 TR_VARIANT_TYPE_LIST = 4,
67 TR_VARIANT_TYPE_DICT = 8,
68 TR_VARIANT_TYPE_BOOL = 16,
69 TR_VARIANT_TYPE_REAL = 32
70 };
71
72 /* These are PRIVATE IMPLEMENTATION details that should not be touched.
73 * I'll probably change them just to break your code! HA HA HA!
74 * it's included in the header for inlining and composition */
75 typedef struct tr_variant
76 {
77 char type;
78
79 tr_quark key;
80
81 union
82 {
83 bool b;
84
85 double d;
86
87 int64_t i;
88
89 struct tr_variant_string s;
90
91 struct
92 {
93 size_t alloc;
94 size_t count;
95 struct tr_variant* vals;
96 } l;
97 }
98 val;
99 }
100 tr_variant;
101
102 void tr_variantFree(tr_variant*);
103
104 /***
105 **** Serialization / Deserialization
106 ***/
107
108 typedef enum
109 {
110 TR_VARIANT_FMT_BENC,
111 TR_VARIANT_FMT_JSON,
112 TR_VARIANT_FMT_JSON_LEAN /* saves bandwidth by omitting all whitespace. */
113 }
114 tr_variant_fmt;
115
116 int tr_variantToFile(tr_variant const* variant, tr_variant_fmt fmt, char const* filename);
117
118 char* tr_variantToStr(tr_variant const* variant, tr_variant_fmt fmt, size_t* len);
119
120 struct evbuffer* tr_variantToBuf(tr_variant const* variant, tr_variant_fmt fmt);
121
122 /* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
123 bool tr_variantFromFile(tr_variant* setme, tr_variant_fmt fmt, char const* filename, struct tr_error** error);
124
125 /* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
126 int tr_variantFromBuf(tr_variant* setme, tr_variant_fmt fmt, void const* buf, size_t buflen, char const* optional_source,
127 char const** setme_end);
128
tr_variantFromBenc(tr_variant * setme,void const * buf,size_t buflen)129 static inline int tr_variantFromBenc(tr_variant* setme, void const* buf, size_t buflen)
130 {
131 return tr_variantFromBuf(setme, TR_VARIANT_FMT_BENC, buf, buflen, NULL, NULL);
132 }
133
tr_variantFromBencFull(tr_variant * setme,void const * buf,size_t buflen,char const * source,char const ** setme_end)134 static inline int tr_variantFromBencFull(tr_variant* setme, void const* buf, size_t buflen, char const* source,
135 char const** setme_end)
136 {
137 return tr_variantFromBuf(setme, TR_VARIANT_FMT_BENC, buf, buflen, source, setme_end);
138 }
139
tr_variantFromJsonFull(tr_variant * setme,void const * buf,size_t buflen,char const * source,char const ** setme_end)140 static inline int tr_variantFromJsonFull(tr_variant* setme, void const* buf, size_t buflen, char const* source,
141 char const** setme_end)
142 {
143 return tr_variantFromBuf(setme, TR_VARIANT_FMT_JSON, buf, buflen, source, setme_end);
144 }
145
tr_variantFromJson(tr_variant * setme,void const * buf,size_t buflen)146 static inline int tr_variantFromJson(tr_variant* setme, void const* buf, size_t buflen)
147 {
148 return tr_variantFromBuf(setme, TR_VARIANT_FMT_JSON, buf, buflen, NULL, NULL);
149 }
150
tr_variantIsType(tr_variant const * b,int type)151 static inline bool tr_variantIsType(tr_variant const* b, int type)
152 {
153 return b != NULL && b->type == type;
154 }
155
156 /***
157 **** Strings
158 ***/
159
tr_variantIsString(tr_variant const * b)160 static inline bool tr_variantIsString(tr_variant const* b)
161 {
162 return b != NULL && b->type == TR_VARIANT_TYPE_STR;
163 }
164
165 bool tr_variantGetStr(tr_variant const* variant, char const** setme_str, size_t* setme_len);
166
167 void tr_variantInitStr(tr_variant* initme, void const* str, size_t str_len);
168 void tr_variantInitQuark(tr_variant* initme, tr_quark const quark);
169 void tr_variantInitRaw(tr_variant* initme, void const* raw, size_t raw_len);
170
171 bool tr_variantGetRaw(tr_variant const* variant, uint8_t const** raw_setme, size_t* len_setme);
172
173 /***
174 **** Real Numbers
175 ***/
176
tr_variantIsReal(tr_variant const * v)177 static inline bool tr_variantIsReal(tr_variant const* v)
178 {
179 return v != NULL && v->type == TR_VARIANT_TYPE_REAL;
180 }
181
182 void tr_variantInitReal(tr_variant* initme, double value);
183 bool tr_variantGetReal(tr_variant const* variant, double* value_setme);
184
185 /***
186 **** Booleans
187 ***/
188
tr_variantIsBool(tr_variant const * v)189 static inline bool tr_variantIsBool(tr_variant const* v)
190 {
191 return v != NULL && v->type == TR_VARIANT_TYPE_BOOL;
192 }
193
194 void tr_variantInitBool(tr_variant* initme, bool value);
195 bool tr_variantGetBool(tr_variant const* variant, bool* setme);
196
197 /***
198 **** Ints
199 ***/
200
tr_variantIsInt(tr_variant const * v)201 static inline bool tr_variantIsInt(tr_variant const* v)
202 {
203 return v != NULL && v->type == TR_VARIANT_TYPE_INT;
204 }
205
206 void tr_variantInitInt(tr_variant* variant, int64_t value);
207 bool tr_variantGetInt(tr_variant const* val, int64_t* setme);
208
209 /***
210 **** Lists
211 ***/
212
tr_variantIsList(tr_variant const * v)213 static inline bool tr_variantIsList(tr_variant const* v)
214 {
215 return v != NULL && v->type == TR_VARIANT_TYPE_LIST;
216 }
217
218 void tr_variantInitList(tr_variant* list, size_t reserve_count);
219 void tr_variantListReserve(tr_variant* list, size_t reserve_count);
220
221 tr_variant* tr_variantListAdd(tr_variant* list);
222 tr_variant* tr_variantListAddBool(tr_variant* list, bool addme);
223 tr_variant* tr_variantListAddInt(tr_variant* list, int64_t addme);
224 tr_variant* tr_variantListAddReal(tr_variant* list, double addme);
225 tr_variant* tr_variantListAddStr(tr_variant* list, char const* addme);
226 tr_variant* tr_variantListAddQuark(tr_variant* list, tr_quark const addme);
227 tr_variant* tr_variantListAddRaw(tr_variant* list, void const* addme_value, size_t addme_len);
228 tr_variant* tr_variantListAddList(tr_variant* list, size_t reserve_count);
229 tr_variant* tr_variantListAddDict(tr_variant* list, size_t reserve_count);
230 tr_variant* tr_variantListChild(tr_variant* list, size_t pos);
231
232 bool tr_variantListRemove(tr_variant* list, size_t pos);
233 size_t tr_variantListSize(tr_variant const* list);
234
235 /***
236 **** Dictionaries
237 ***/
238
tr_variantIsDict(tr_variant const * v)239 static inline bool tr_variantIsDict(tr_variant const* v)
240 {
241 return v != NULL && v->type == TR_VARIANT_TYPE_DICT;
242 }
243
244 void tr_variantInitDict(tr_variant* initme, size_t reserve_count);
245 void tr_variantDictReserve(tr_variant* dict, size_t reserve_count);
246 bool tr_variantDictRemove(tr_variant* dict, tr_quark const key);
247
248 tr_variant* tr_variantDictAdd(tr_variant* dict, tr_quark const key);
249 tr_variant* tr_variantDictAddReal(tr_variant* dict, tr_quark const key, double value);
250 tr_variant* tr_variantDictAddInt(tr_variant* dict, tr_quark const key, int64_t value);
251 tr_variant* tr_variantDictAddBool(tr_variant* dict, tr_quark const key, bool value);
252 tr_variant* tr_variantDictAddStr(tr_variant* dict, tr_quark const key, char const* value);
253 tr_variant* tr_variantDictAddQuark(tr_variant* dict, tr_quark const key, tr_quark const val);
254 tr_variant* tr_variantDictAddList(tr_variant* dict, tr_quark const key, size_t reserve_count);
255 tr_variant* tr_variantDictAddDict(tr_variant* dict, tr_quark const key, size_t reserve_count);
256 tr_variant* tr_variantDictSteal(tr_variant* dict, tr_quark const key, tr_variant* value);
257 tr_variant* tr_variantDictAddRaw(tr_variant* dict, tr_quark const key, void const* value, size_t len);
258
259 bool tr_variantDictChild(tr_variant* dict, size_t pos, tr_quark* setme_key, tr_variant** setme_value);
260 tr_variant* tr_variantDictFind(tr_variant* dict, tr_quark const key);
261 bool tr_variantDictFindList(tr_variant* dict, tr_quark const key, tr_variant** setme);
262 bool tr_variantDictFindDict(tr_variant* dict, tr_quark const key, tr_variant** setme_value);
263 bool tr_variantDictFindInt(tr_variant* dict, tr_quark const key, int64_t* setme);
264 bool tr_variantDictFindReal(tr_variant* dict, tr_quark const key, double* setme);
265 bool tr_variantDictFindBool(tr_variant* dict, tr_quark const key, bool* setme);
266 bool tr_variantDictFindStr(tr_variant* dict, tr_quark const key, char const** setme, size_t* len);
267 bool tr_variantDictFindRaw(tr_variant* dict, tr_quark const key, uint8_t const** setme_raw, size_t* setme_len);
268
269 /* this is only quasi-supported. don't rely on it too heavily outside of libT */
270 void tr_variantMergeDicts(tr_variant* dict_target, tr_variant const* dict_source);
271
272 /***
273 ****
274 ****
275 ***/
276
277 /**
278 ***
279 **/
280
281 /* @} */
282
283 #ifdef __cplusplus
284 }
285 #endif
286