2008-08-21 14:57:59 +00:00
|
|
|
/*
|
2011-01-19 13:48:47 +00:00
|
|
|
* This file Copyright (C) Mnemosyne LLC
|
2006-07-16 19:39:23 +00:00
|
|
|
*
|
2010-12-27 19:18:17 +00:00
|
|
|
* This file is licensed by the GPL version 2. Works owned by the
|
2008-08-21 14:57:59 +00:00
|
|
|
* Transmission project are granted a special exemption to clause 2(b)
|
2008-09-23 19:11:04 +00:00
|
|
|
* so that the bulk of its code can remain under the MIT license.
|
2008-08-21 14:57:59 +00:00
|
|
|
* This exemption does not extend to derived works not owned by
|
|
|
|
* the Transmission project.
|
2006-07-16 19:39:23 +00:00
|
|
|
*
|
2008-08-21 14:57:59 +00:00
|
|
|
* $Id$
|
|
|
|
*/
|
2006-07-16 19:39:23 +00:00
|
|
|
|
|
|
|
#ifndef TR_BENCODE_H
|
|
|
|
#define TR_BENCODE_H 1
|
|
|
|
|
2009-04-05 17:52:21 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2007-06-14 11:41:09 +00:00
|
|
|
#include <inttypes.h> /* for int64_t */
|
2007-05-28 15:23:28 +00:00
|
|
|
|
2008-12-30 22:07:39 +00:00
|
|
|
struct evbuffer;
|
|
|
|
|
2009-05-29 19:17:12 +00:00
|
|
|
/**
|
|
|
|
* @addtogroup tr_benc Variant
|
|
|
|
*
|
|
|
|
* An object that acts like a union for
|
|
|
|
* integers, strings, lists, dictionaries, booleans, and floating-point numbers.
|
2009-08-10 20:04:08 +00:00
|
|
|
* The structure is named tr_benc due to the historical reason that it was
|
2010-12-27 19:18:17 +00:00
|
|
|
* originally tightly coupled with bencoded data. It currently supports
|
2009-05-29 19:17:12 +00:00
|
|
|
* being parsed from, and serialized to, both bencoded notation and json notation.
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2009-04-21 16:52:28 +00:00
|
|
|
/* these are PRIVATE IMPLEMENTATION details that should not be touched.
|
2009-06-02 18:21:23 +00:00
|
|
|
* I'll probably change them just to break your code! HA HA HA!
|
2009-04-21 16:52:28 +00:00
|
|
|
* it's included in the header for inlining and composition */
|
2008-08-21 14:57:59 +00:00
|
|
|
enum
|
|
|
|
{
|
2009-04-05 18:02:11 +00:00
|
|
|
TR_TYPE_INT = 1,
|
|
|
|
TR_TYPE_STR = 2,
|
|
|
|
TR_TYPE_LIST = 4,
|
|
|
|
TR_TYPE_DICT = 8,
|
|
|
|
TR_TYPE_BOOL = 16,
|
|
|
|
TR_TYPE_REAL = 32
|
2008-08-21 14:57:59 +00:00
|
|
|
};
|
2009-08-10 20:04:08 +00:00
|
|
|
|
2009-06-02 18:21:23 +00:00
|
|
|
/* These are PRIVATE IMPLEMENTATION details that should not be touched.
|
|
|
|
* I'll probably change them just to break your code! HA HA HA!
|
2009-04-21 16:52:28 +00:00
|
|
|
* it's included in the header for inlining and composition */
|
2008-02-26 21:58:58 +00:00
|
|
|
typedef struct tr_benc
|
2006-07-16 19:39:23 +00:00
|
|
|
{
|
|
|
|
union
|
|
|
|
{
|
2009-04-05 17:52:21 +00:00
|
|
|
uint8_t b; /* bool type */
|
|
|
|
|
|
|
|
double d; /* double type */
|
|
|
|
|
|
|
|
int64_t i; /* int type */
|
|
|
|
|
|
|
|
struct /* string type */
|
2006-07-16 19:39:23 +00:00
|
|
|
{
|
2009-06-01 22:15:50 +00:00
|
|
|
size_t len; /* the string length */
|
|
|
|
union {
|
2009-06-02 18:21:23 +00:00
|
|
|
char buf[16]; /* local buffer for short strings */
|
|
|
|
char * ptr; /* alloc'ed pointer for long strings */
|
2009-06-01 22:15:50 +00:00
|
|
|
} str;
|
2006-07-16 19:39:23 +00:00
|
|
|
} s;
|
2009-04-05 17:52:21 +00:00
|
|
|
|
|
|
|
struct /* list & dict types */
|
2006-07-16 19:39:23 +00:00
|
|
|
{
|
2009-06-01 22:15:50 +00:00
|
|
|
struct tr_benc * vals; /* nodes */
|
2009-04-21 16:52:28 +00:00
|
|
|
size_t alloc; /* nodes allocated */
|
|
|
|
size_t count; /* nodes used */
|
2006-07-16 19:39:23 +00:00
|
|
|
} l;
|
|
|
|
} val;
|
2009-06-01 22:15:50 +00:00
|
|
|
|
|
|
|
char type;
|
2008-02-26 21:58:58 +00:00
|
|
|
} tr_benc;
|
2006-07-16 19:39:23 +00:00
|
|
|
|
2008-08-21 14:57:59 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
2008-01-30 15:39:41 +00:00
|
|
|
|
2009-04-21 16:52:28 +00:00
|
|
|
int tr_bencParse( const void * buf,
|
|
|
|
const void * bufend,
|
|
|
|
tr_benc * setme_benc,
|
2008-09-23 19:11:04 +00:00
|
|
|
const uint8_t ** setme_end );
|
|
|
|
|
2009-04-21 16:52:28 +00:00
|
|
|
int tr_bencLoad( const void * buf,
|
|
|
|
size_t buflen,
|
|
|
|
tr_benc * setme_benc,
|
|
|
|
char ** setme_end );
|
2008-01-31 02:24:43 +00:00
|
|
|
|
2008-09-23 19:11:04 +00:00
|
|
|
void tr_bencFree( tr_benc * );
|
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
void tr_bencInitStr( tr_benc *, const void * str, int str_len );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
void tr_bencInitRaw( tr_benc *, const void * raw, size_t raw_len );
|
2007-03-23 08:28:01 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
void tr_bencInitInt( tr_benc *, int64_t num );
|
2008-08-21 14:57:59 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
int tr_bencInitDict( tr_benc *, size_t reserveCount );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
int tr_bencInitList( tr_benc *, size_t reserveCount );
|
2008-08-21 14:57:59 +00:00
|
|
|
|
2009-04-05 17:52:21 +00:00
|
|
|
void tr_bencInitBool( tr_benc *, int value );
|
|
|
|
|
|
|
|
void tr_bencInitReal( tr_benc *, double value );
|
|
|
|
|
2008-08-21 14:57:59 +00:00
|
|
|
/***
|
2009-06-02 18:21:23 +00:00
|
|
|
**** Serialization / Deserialization
|
2008-08-21 14:57:59 +00:00
|
|
|
***/
|
|
|
|
|
2009-06-02 01:48:48 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
TR_FMT_BENC,
|
|
|
|
TR_FMT_JSON,
|
|
|
|
TR_FMT_JSON_LEAN /* saves bandwidth by omitting all whitespace. */
|
|
|
|
}
|
|
|
|
tr_fmt_mode;
|
|
|
|
|
|
|
|
int tr_bencToFile( const tr_benc *, tr_fmt_mode, const char * filename );
|
|
|
|
|
|
|
|
char* tr_bencToStr( const tr_benc *, tr_fmt_mode, int * len );
|
|
|
|
|
2009-06-02 18:21:23 +00:00
|
|
|
void tr_bencToBuf( const tr_benc *, tr_fmt_mode, struct evbuffer * );
|
2009-06-02 01:48:48 +00:00
|
|
|
|
|
|
|
/* TR_FMT_JSON_LEAN and TR_FMT_JSON are equivalent in this function. */
|
|
|
|
int tr_bencLoadFile( tr_benc * setme, tr_fmt_mode, const char * filename );
|
|
|
|
|
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
|
|
|
int tr_bencListReserve( tr_benc *, size_t reserveCount );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-08-21 14:57:59 +00:00
|
|
|
tr_benc * tr_bencListAdd( tr_benc * );
|
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
tr_benc * tr_bencListAddBool( tr_benc *, bool val );
|
2010-02-02 22:45:22 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencListAddInt( tr_benc *, int64_t val );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2010-02-02 22:45:22 +00:00
|
|
|
tr_benc * tr_bencListAddReal( tr_benc *, double val );
|
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencListAddStr( tr_benc *, const char * val );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2010-02-02 22:45:22 +00:00
|
|
|
tr_benc * tr_bencListAddRaw( tr_benc *, const uint8_t * val, size_t len );
|
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencListAddList( tr_benc *, size_t reserveCount );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencListAddDict( tr_benc *, size_t reserveCount );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
|
|
|
size_t tr_bencListSize( const tr_benc * list );
|
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencListChild( tr_benc * list, size_t n );
|
2008-08-21 14:57:59 +00:00
|
|
|
|
2010-06-16 14:27:24 +00:00
|
|
|
int tr_bencListRemove( tr_benc *, size_t n );
|
|
|
|
|
2008-08-21 14:57:59 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
int tr_bencDictReserve( tr_benc *, size_t reserveCount );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
int tr_bencDictRemove( tr_benc *, const char * key );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencDictAdd( tr_benc *, const char * key );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2009-03-29 23:05:32 +00:00
|
|
|
tr_benc * tr_bencDictAddReal( tr_benc *, const char * key, double );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencDictAddInt( tr_benc *, const char * key, int64_t );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
tr_benc * tr_bencDictAddBool( tr_benc *, const char * key, bool );
|
2009-03-29 18:45:35 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencDictAddStr( tr_benc *, const char * key, const char * );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencDictAddList( tr_benc *, const char * key, size_t reserve );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencDictAddDict( tr_benc *, const char * key, size_t reserve );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc * tr_bencDictAddRaw( tr_benc *, const char * key,
|
|
|
|
const void * raw, size_t rawlen );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictChild( tr_benc *, size_t i, const char ** key, tr_benc ** val );
|
2009-06-01 18:12:36 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
tr_benc* tr_bencDictFind( tr_benc *, const char * key );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindList( tr_benc *, const char * key, tr_benc ** setme );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindDict( tr_benc *, const char * key, tr_benc ** setme );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindInt( tr_benc *, const char * key, int64_t * setme );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindReal( tr_benc *, const char * key, double * setme );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindBool( tr_benc *, const char * key, bool * setme );
|
2009-03-29 18:45:35 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindStr( tr_benc *, const char * key, const char ** setme );
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
bool tr_bencDictFindRaw( tr_benc *, const char * key,
|
2008-12-12 02:12:17 +00:00
|
|
|
const uint8_t ** setme_raw, size_t * setme_len );
|
2008-08-21 14:57:59 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
2008-03-04 19:29:51 +00:00
|
|
|
|
2010-01-19 19:37:00 +00:00
|
|
|
/** @brief Get an int64_t from a variant object
|
2011-03-22 15:19:54 +00:00
|
|
|
@return true if successful, or false if the variant could not be represented as an int64_t */
|
|
|
|
bool tr_bencGetInt( const tr_benc * val, int64_t * setme );
|
2010-01-19 19:37:00 +00:00
|
|
|
|
|
|
|
/** @brief Get an string from a variant object
|
2011-03-22 15:19:54 +00:00
|
|
|
@return true if successful, or false if the variant could not be represented as a string */
|
|
|
|
bool tr_bencGetStr( const tr_benc * val, const char ** setme );
|
2010-01-19 19:37:00 +00:00
|
|
|
|
2011-02-23 03:54:04 +00:00
|
|
|
/** @brief Get a raw byte array from a variant object
|
2011-03-22 15:19:54 +00:00
|
|
|
@return true if successful, or false if the variant could not be represented as a raw byte array */
|
|
|
|
bool tr_bencGetRaw( const tr_benc * val, const uint8_t ** setme_raw, size_t * setme_len );
|
2011-02-23 03:54:04 +00:00
|
|
|
|
2010-01-19 19:37:00 +00:00
|
|
|
/** @brief Get a boolean from a variant object
|
2011-03-22 15:19:54 +00:00
|
|
|
@return true if successful, or false if the variant could not be represented as a boolean */
|
|
|
|
bool tr_bencGetBool( const tr_benc * val, bool * setme );
|
2010-01-19 19:37:00 +00:00
|
|
|
|
|
|
|
/** @brief Get a floating-point number from a variant object
|
2011-03-22 15:19:54 +00:00
|
|
|
@return true if successful, or false if the variant could not be represented as a floating-point number */
|
|
|
|
bool tr_bencGetReal( const tr_benc * val, double * setme );
|
2008-12-12 02:12:17 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
static inline bool tr_bencIsType ( const tr_benc * b, int type ) { return ( b != NULL ) && ( b->type == type ); }
|
2010-01-19 19:37:00 +00:00
|
|
|
|
2011-03-22 15:19:54 +00:00
|
|
|
static inline bool tr_bencIsInt ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_INT ); }
|
|
|
|
static inline bool tr_bencIsDict ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_DICT ); }
|
|
|
|
static inline bool tr_bencIsList ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_LIST ); }
|
|
|
|
static inline bool tr_bencIsString( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_STR ); }
|
|
|
|
static inline bool tr_bencIsBool ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_BOOL ); }
|
|
|
|
static inline bool tr_bencIsReal ( const tr_benc * b ) { return tr_bencIsType( b, TR_TYPE_REAL ); }
|
2008-01-30 15:39:41 +00:00
|
|
|
|
2010-01-19 19:37:00 +00:00
|
|
|
/** @brief Private function that's exposed here only for unit tests */
|
2008-09-23 19:11:04 +00:00
|
|
|
int tr_bencParseInt( const uint8_t * buf,
|
|
|
|
const uint8_t * bufend,
|
|
|
|
const uint8_t ** setme_end,
|
|
|
|
int64_t * setme_val );
|
2008-01-30 15:39:41 +00:00
|
|
|
|
2010-01-19 19:37:00 +00:00
|
|
|
/** @brief Private function that's exposed here only for unit tests */
|
2008-09-23 19:11:04 +00:00
|
|
|
int tr_bencParseStr( const uint8_t * buf,
|
|
|
|
const uint8_t * bufend,
|
|
|
|
const uint8_t ** setme_end,
|
|
|
|
const uint8_t ** setme_str,
|
|
|
|
size_t * setme_strlen );
|
2008-01-30 15:39:41 +00:00
|
|
|
|
2008-12-12 02:12:17 +00:00
|
|
|
/**
|
|
|
|
***
|
|
|
|
**/
|
|
|
|
|
2010-12-27 19:18:17 +00:00
|
|
|
/* this is only quasi-supported. don't rely on it too heavily outside of libT */
|
2008-12-13 23:17:36 +00:00
|
|
|
void tr_bencMergeDicts( tr_benc * target, const tr_benc * source );
|
2008-12-12 02:12:17 +00:00
|
|
|
|
2009-05-29 19:17:12 +00:00
|
|
|
/* @} */
|
|
|
|
|
2009-01-11 17:02:04 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-07-16 19:39:23 +00:00
|
|
|
#endif
|