2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: bencode.h 11709 2011-01-19 13:48:47Z jordan $
14 #define TR_BENCODE_H 1
20 #include <inttypes.h> /* for int64_t */
25 * @addtogroup tr_benc Variant
27 * An object that acts like a union for
28 * integers, strings, lists, dictionaries, booleans, and floating-point numbers.
29 * The structure is named tr_benc due to the historical reason that it was
30 * originally tightly coupled with bencoded data. It currently supports
31 * being parsed from, and serialized to, both bencoded notation and json notation.
36 /* these are PRIVATE IMPLEMENTATION details that should not be touched.
37 * I'll probably change them just to break your code! HA HA HA!
38 * it's included in the header for inlining and composition */
49 /* These are PRIVATE IMPLEMENTATION details that should not be touched.
50 * I'll probably change them just to break your code! HA HA HA!
51 * it's included in the header for inlining and composition */
52 typedef struct tr_benc
56 uint8_t b
; /* bool type */
58 double d
; /* double type */
60 int64_t i
; /* int type */
62 struct /* string type */
64 size_t len
; /* the string length */
66 char buf
[16]; /* local buffer for short strings */
67 char * ptr
; /* alloc'ed pointer for long strings */
71 struct /* list & dict types */
73 struct tr_benc
* vals
; /* nodes */
74 size_t alloc
; /* nodes allocated */
75 size_t count
; /* nodes used */
86 int tr_bencParse( const void * buf
,
89 const uint8_t ** setme_end
);
91 int tr_bencLoad( const void * buf
,
96 void tr_bencFree( tr_benc
* );
98 void tr_bencInitStr( tr_benc
*, const void * str
, int str_len
);
100 void tr_bencInitRaw( tr_benc
*, const void * raw
, size_t raw_len
);
102 void tr_bencInitInt( tr_benc
*, int64_t num
);
104 int tr_bencInitDict( tr_benc
*, size_t reserveCount
);
106 int tr_bencInitList( tr_benc
*, size_t reserveCount
);
108 void tr_bencInitBool( tr_benc
*, int value
);
110 void tr_bencInitReal( tr_benc
*, double value
);
113 **** Serialization / Deserialization
120 TR_FMT_JSON_LEAN
/* saves bandwidth by omitting all whitespace. */
124 int tr_bencToFile( const tr_benc
*, tr_fmt_mode
, const char * filename
);
126 char* tr_bencToStr( const tr_benc
*, tr_fmt_mode
, int * len
);
128 void tr_bencToBuf( const tr_benc
*, tr_fmt_mode
, struct evbuffer
* );
130 /* TR_FMT_JSON_LEAN and TR_FMT_JSON are equivalent in this function. */
131 int tr_bencLoadFile( tr_benc
* setme
, tr_fmt_mode
, const char * filename
);
137 int tr_bencListReserve( tr_benc
*, size_t reserveCount
);
139 tr_benc
* tr_bencListAdd( tr_benc
* );
141 tr_benc
* tr_bencListAddBool( tr_benc
*, tr_bool val
);
143 tr_benc
* tr_bencListAddInt( tr_benc
*, int64_t val
);
145 tr_benc
* tr_bencListAddReal( tr_benc
*, double val
);
147 tr_benc
* tr_bencListAddStr( tr_benc
*, const char * val
);
149 tr_benc
* tr_bencListAddRaw( tr_benc
*, const uint8_t * val
, size_t len
);
151 tr_benc
* tr_bencListAddList( tr_benc
*, size_t reserveCount
);
153 tr_benc
* tr_bencListAddDict( tr_benc
*, size_t reserveCount
);
155 size_t tr_bencListSize( const tr_benc
* list
);
157 tr_benc
* tr_bencListChild( tr_benc
* list
, size_t n
);
159 int tr_bencListRemove( tr_benc
*, size_t n
);
165 int tr_bencDictReserve( tr_benc
*, size_t reserveCount
);
167 int tr_bencDictRemove( tr_benc
*, const char * key
);
169 tr_benc
* tr_bencDictAdd( tr_benc
*, const char * key
);
171 tr_benc
* tr_bencDictAddReal( tr_benc
*, const char * key
, double );
173 tr_benc
* tr_bencDictAddInt( tr_benc
*, const char * key
, int64_t );
175 tr_benc
* tr_bencDictAddBool( tr_benc
*, const char * key
, tr_bool
);
177 tr_benc
* tr_bencDictAddStr( tr_benc
*, const char * key
, const char * );
179 tr_benc
* tr_bencDictAddList( tr_benc
*, const char * key
, size_t reserve
);
181 tr_benc
* tr_bencDictAddDict( tr_benc
*, const char * key
, size_t reserve
);
183 tr_benc
* tr_bencDictAddRaw( tr_benc
*, const char * key
,
184 const void * raw
, size_t rawlen
);
186 tr_bool
tr_bencDictChild( tr_benc
*, size_t i
, const char ** key
, tr_benc
** val
);
188 tr_benc
* tr_bencDictFind( tr_benc
*, const char * key
);
190 tr_bool
tr_bencDictFindList( tr_benc
*, const char * key
, tr_benc
** setme
);
192 tr_bool
tr_bencDictFindDict( tr_benc
*, const char * key
, tr_benc
** setme
);
194 tr_bool
tr_bencDictFindInt( tr_benc
*, const char * key
, int64_t * setme
);
196 tr_bool
tr_bencDictFindReal( tr_benc
*, const char * key
, double * setme
);
198 tr_bool
tr_bencDictFindBool( tr_benc
*, const char * key
, tr_bool
* setme
);
200 tr_bool
tr_bencDictFindStr( tr_benc
*, const char * key
, const char ** setme
);
202 tr_bool
tr_bencDictFindRaw( tr_benc
*, const char * key
,
203 const uint8_t ** setme_raw
, size_t * setme_len
);
209 /** @brief Get an int64_t from a variant object
210 @return TRUE if successful, or FALSE if the variant could not be represented as an int64_t */
211 tr_bool
tr_bencGetInt( const tr_benc
* val
, int64_t * setme
);
213 /** @brief Get an string from a variant object
214 @return TRUE if successful, or FALSE if the variant could not be represented as a string */
215 tr_bool
tr_bencGetStr( const tr_benc
* val
, const char ** setme
);
217 /** @brief Get a boolean from a variant object
218 @return TRUE if successful, or FALSE if the variant could not be represented as a boolean */
219 tr_bool
tr_bencGetBool( const tr_benc
* val
, tr_bool
* setme
);
221 /** @brief Get a floating-point number from a variant object
222 @return TRUE if successful, or FALSE if the variant could not be represented as a floating-point number */
223 tr_bool
tr_bencGetReal( const tr_benc
* val
, double * setme
);
225 static inline tr_bool
tr_bencIsType ( const tr_benc
* b
, int type
) { return ( b
!= NULL
) && ( b
->type
== type
); }
227 static inline tr_bool
tr_bencIsInt ( const tr_benc
* b
) { return tr_bencIsType( b
, TR_TYPE_INT
); }
228 static inline tr_bool
tr_bencIsDict ( const tr_benc
* b
) { return tr_bencIsType( b
, TR_TYPE_DICT
); }
229 static inline tr_bool
tr_bencIsList ( const tr_benc
* b
) { return tr_bencIsType( b
, TR_TYPE_LIST
); }
230 static inline tr_bool
tr_bencIsString( const tr_benc
* b
) { return tr_bencIsType( b
, TR_TYPE_STR
); }
231 static inline tr_bool
tr_bencIsBool ( const tr_benc
* b
) { return tr_bencIsType( b
, TR_TYPE_BOOL
); }
232 static inline tr_bool
tr_bencIsReal ( const tr_benc
* b
) { return tr_bencIsType( b
, TR_TYPE_REAL
); }
234 /** @brief Private function that's exposed here only for unit tests */
235 int tr_bencParseInt( const uint8_t * buf
,
236 const uint8_t * bufend
,
237 const uint8_t ** setme_end
,
238 int64_t * setme_val
);
240 /** @brief Private function that's exposed here only for unit tests */
241 int tr_bencParseStr( const uint8_t * buf
,
242 const uint8_t * bufend
,
243 const uint8_t ** setme_end
,
244 const uint8_t ** setme_str
,
245 size_t * setme_strlen
);
251 /* this is only quasi-supported. don't rely on it too heavily outside of libT */
252 void tr_bencMergeDicts( tr_benc
* target
, const tr_benc
* source
);