1/* 2 * This file Copyright (C) Mnemosyne LLC 3 * 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. 9 * 10 * $Id: bencode.h 12391 2011-04-27 21:22:08Z jordan $ 11 */ 12 13#ifndef TR_BENCODE_H 14#define TR_BENCODE_H 1 15 16#ifdef __cplusplus 17extern "C" { 18#endif 19 20#include <inttypes.h> /* for int64_t */ 21 22struct evbuffer; 23 24/** 25 * @addtogroup tr_benc Variant 26 * 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. 32 * 33 * @{ 34 */ 35 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 */ 39enum 40{ 41 TR_TYPE_INT = 1, 42 TR_TYPE_STR = 2, 43 TR_TYPE_LIST = 4, 44 TR_TYPE_DICT = 8, 45 TR_TYPE_BOOL = 16, 46 TR_TYPE_REAL = 32 47}; 48 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 */ 52typedef struct tr_benc 53{ 54 union 55 { 56 uint8_t b; /* bool type */ 57 58 double d; /* double type */ 59 60 int64_t i; /* int type */ 61 62 struct /* string type */ 63 { 64 size_t len; /* the string length */ 65 union { 66 char buf[16]; /* local buffer for short strings */ 67 char * ptr; /* alloc'ed pointer for long strings */ 68 } str; 69 } s; 70 71 struct /* list & dict types */ 72 { 73 struct tr_benc * vals; /* nodes */ 74 size_t alloc; /* nodes allocated */ 75 size_t count; /* nodes used */ 76 } l; 77 } val; 78 79 char type; 80} tr_benc; 81 82/*** 83**** 84***/ 85 86int tr_bencParse( const void * buf, 87 const void * bufend, 88 tr_benc * setme_benc, 89 const uint8_t ** setme_end ); 90 91int tr_bencLoad( const void * buf, 92 size_t buflen, 93 tr_benc * setme_benc, 94 char ** setme_end ); 95 96void tr_bencFree( tr_benc * ); 97 98void tr_bencInitStr( tr_benc *, const void * str, int str_len ); 99 100void tr_bencInitRaw( tr_benc *, const void * raw, size_t raw_len ); 101 102void tr_bencInitInt( tr_benc *, int64_t num ); 103 104int tr_bencInitDict( tr_benc *, size_t reserveCount ); 105 106int tr_bencInitList( tr_benc *, size_t reserveCount ); 107 108void tr_bencInitBool( tr_benc *, int value ); 109 110void tr_bencInitReal( tr_benc *, double value ); 111 112/*** 113**** Serialization / Deserialization 114***/ 115 116typedef enum 117{ 118 TR_FMT_BENC, 119 TR_FMT_JSON, 120 TR_FMT_JSON_LEAN /* saves bandwidth by omitting all whitespace. */ 121} 122tr_fmt_mode; 123 124int tr_bencToFile( const tr_benc *, tr_fmt_mode, const char * filename ); 125 126char* tr_bencToStr( const tr_benc *, tr_fmt_mode, int * len ); 127 128struct evbuffer * tr_bencToBuf( const tr_benc *, tr_fmt_mode ); 129 130/* TR_FMT_JSON_LEAN and TR_FMT_JSON are equivalent in this function. */ 131int tr_bencLoadFile( tr_benc * setme, tr_fmt_mode, const char * filename ); 132 133/*** 134**** 135***/ 136 137int tr_bencListReserve( tr_benc *, size_t reserveCount ); 138 139tr_benc * tr_bencListAdd( tr_benc * ); 140 141tr_benc * tr_bencListAddBool( tr_benc *, bool val ); 142 143tr_benc * tr_bencListAddInt( tr_benc *, int64_t val ); 144 145tr_benc * tr_bencListAddReal( tr_benc *, double val ); 146 147tr_benc * tr_bencListAddStr( tr_benc *, const char * val ); 148 149tr_benc * tr_bencListAddRaw( tr_benc *, const uint8_t * val, size_t len ); 150 151tr_benc * tr_bencListAddList( tr_benc *, size_t reserveCount ); 152 153tr_benc * tr_bencListAddDict( tr_benc *, size_t reserveCount ); 154 155size_t tr_bencListSize( const tr_benc * list ); 156 157tr_benc * tr_bencListChild( tr_benc * list, size_t n ); 158 159int tr_bencListRemove( tr_benc *, size_t n ); 160 161/*** 162**** 163***/ 164 165int tr_bencDictReserve( tr_benc *, size_t reserveCount ); 166 167int tr_bencDictRemove( tr_benc *, const char * key ); 168 169tr_benc * tr_bencDictAdd( tr_benc *, const char * key ); 170 171tr_benc * tr_bencDictAddReal( tr_benc *, const char * key, double ); 172 173tr_benc * tr_bencDictAddInt( tr_benc *, const char * key, int64_t ); 174 175tr_benc * tr_bencDictAddBool( tr_benc *, const char * key, bool ); 176 177tr_benc * tr_bencDictAddStr( tr_benc *, const char * key, const char * ); 178 179tr_benc * tr_bencDictAddList( tr_benc *, const char * key, size_t reserve ); 180 181tr_benc * tr_bencDictAddDict( tr_benc *, const char * key, size_t reserve ); 182 183tr_benc * tr_bencDictAddRaw( tr_benc *, const char * key, 184 const void * raw, size_t rawlen ); 185 186bool tr_bencDictChild( tr_benc *, size_t i, const char ** key, tr_benc ** val ); 187 188tr_benc* tr_bencDictFind( tr_benc *, const char * key ); 189 190bool tr_bencDictFindList( tr_benc *, const char * key, tr_benc ** setme ); 191 192bool tr_bencDictFindDict( tr_benc *, const char * key, tr_benc ** setme ); 193 194bool tr_bencDictFindInt( tr_benc *, const char * key, int64_t * setme ); 195 196bool tr_bencDictFindReal( tr_benc *, const char * key, double * setme ); 197 198bool tr_bencDictFindBool( tr_benc *, const char * key, bool * setme ); 199 200bool tr_bencDictFindStr( tr_benc *, const char * key, const char ** setme ); 201 202bool tr_bencDictFindRaw( tr_benc *, const char * key, 203 const uint8_t ** setme_raw, size_t * setme_len ); 204 205/*** 206**** 207***/ 208 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 */ 211bool tr_bencGetInt( const tr_benc * val, int64_t * setme ); 212 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 */ 215bool tr_bencGetStr( const tr_benc * val, const char ** setme ); 216 217/** @brief Get a raw byte array from a variant object 218 @return true if successful, or false if the variant could not be represented as a raw byte array */ 219bool tr_bencGetRaw( const tr_benc * val, const uint8_t ** setme_raw, size_t * setme_len ); 220 221/** @brief Get a boolean from a variant object 222 @return true if successful, or false if the variant could not be represented as a boolean */ 223bool tr_bencGetBool( const tr_benc * val, bool * setme ); 224 225/** @brief Get a floating-point number from a variant object 226 @return true if successful, or false if the variant could not be represented as a floating-point number */ 227bool tr_bencGetReal( const tr_benc * val, double * setme ); 228 229static inline bool tr_bencIsType ( const tr_benc * b, int type ) { return ( b != NULL ) && ( b->type == type ); } 230 231static inline bool tr_bencIsInt ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_INT ); } 232static inline bool tr_bencIsDict ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_DICT ); } 233static inline bool tr_bencIsList ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_LIST ); } 234static inline bool tr_bencIsString( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_STR ); } 235static inline bool tr_bencIsBool ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_BOOL ); } 236static inline bool tr_bencIsReal ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_REAL ); } 237 238/** @brief Private function that's exposed here only for unit tests */ 239int tr_bencParseInt( const uint8_t * buf, 240 const uint8_t * bufend, 241 const uint8_t ** setme_end, 242 int64_t * setme_val ); 243 244/** @brief Private function that's exposed here only for unit tests */ 245int tr_bencParseStr( const uint8_t * buf, 246 const uint8_t * bufend, 247 const uint8_t ** setme_end, 248 const uint8_t ** setme_str, 249 size_t * setme_strlen ); 250 251/** 252*** 253**/ 254 255/* this is only quasi-supported. don't rely on it too heavily outside of libT */ 256void tr_bencMergeDicts( tr_benc * target, const tr_benc * source ); 257 258/* @} */ 259 260#ifdef __cplusplus 261} 262#endif 263 264#endif 265