435 lines
14 KiB
C
435 lines
14 KiB
C
/*
|
|
* This file Copyright (C) Mnemosyne LLC
|
|
*
|
|
* This file is licensed by the GPL version 2. Works owned by the
|
|
* Transmission project are granted a special exemption to clause 2 (b)
|
|
* so that the bulk of its code can remain under the MIT license.
|
|
* This exemption does not extend to derived works not owned by
|
|
* the Transmission project.
|
|
*
|
|
* $Id:$
|
|
*/
|
|
|
|
#ifndef TR_VARIANT_H
|
|
#define TR_VARIANT_H 1
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <inttypes.h> /* for int64_t */
|
|
#include "quark.h"
|
|
|
|
struct evbuffer;
|
|
|
|
/**
|
|
* @addtogroup tr_variant Variant
|
|
*
|
|
* An object that acts like a union for
|
|
* integers, strings, lists, dictionaries, booleans, and floating-point numbers.
|
|
* The structure is named tr_variant due to the historical reason that it was
|
|
* originally tightly coupled with bencoded data. It currently supports
|
|
* being parsed from, and serialized to, both bencoded notation and json notation.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
typedef enum
|
|
{
|
|
TR_STRING_TYPE_QUARK,
|
|
TR_STRING_TYPE_HEAP,
|
|
TR_STRING_TYPE_BUF
|
|
}
|
|
tr_string_type;
|
|
|
|
/* these are PRIVATE IMPLEMENTATION details that should not be touched.
|
|
* I'll probably change them just to break your code! HA HA HA!
|
|
* it's included in the header for inlining and composition */
|
|
struct tr_variant_string
|
|
{
|
|
tr_string_type type;
|
|
tr_quark quark;
|
|
size_t len;
|
|
union { char buf[16]; const char * str; } str;
|
|
};
|
|
|
|
|
|
/* these are PRIVATE IMPLEMENTATION details that should not be touched.
|
|
* I'll probably change them just to break your code! HA HA HA!
|
|
* it's included in the header for inlining and composition */
|
|
enum
|
|
{
|
|
TR_VARIANT_TYPE_INT = 1,
|
|
TR_VARIANT_TYPE_STR = 2,
|
|
TR_VARIANT_TYPE_LIST = 4,
|
|
TR_VARIANT_TYPE_DICT = 8,
|
|
TR_VARIANT_TYPE_BOOL = 16,
|
|
TR_VARIANT_TYPE_REAL = 32
|
|
};
|
|
|
|
/* These are PRIVATE IMPLEMENTATION details that should not be touched.
|
|
* I'll probably change them just to break your code! HA HA HA!
|
|
* it's included in the header for inlining and composition */
|
|
typedef struct tr_variant
|
|
{
|
|
char type;
|
|
|
|
tr_quark key;
|
|
|
|
union
|
|
{
|
|
bool b;
|
|
|
|
double d;
|
|
|
|
int64_t i;
|
|
|
|
struct tr_variant_string s;
|
|
|
|
struct
|
|
{
|
|
size_t alloc;
|
|
size_t count;
|
|
struct tr_variant * vals;
|
|
} l;
|
|
}
|
|
val;
|
|
}
|
|
tr_variant;
|
|
|
|
void tr_variantFree (tr_variant *);
|
|
|
|
/***
|
|
**** Serialization / Deserialization
|
|
***/
|
|
|
|
typedef enum
|
|
{
|
|
TR_VARIANT_FMT_BENC,
|
|
TR_VARIANT_FMT_JSON,
|
|
TR_VARIANT_FMT_JSON_LEAN /* saves bandwidth by omitting all whitespace. */
|
|
}
|
|
tr_variant_fmt;
|
|
|
|
int tr_variantToFile (const tr_variant * variant,
|
|
tr_variant_fmt fmt,
|
|
const char * filename);
|
|
|
|
char* tr_variantToStr (const tr_variant * variant,
|
|
tr_variant_fmt fmt,
|
|
int * len);
|
|
|
|
struct evbuffer * tr_variantToBuf (const tr_variant * variant,
|
|
tr_variant_fmt fmt);
|
|
|
|
/* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
|
|
int tr_variantFromFile (tr_variant * setme,
|
|
tr_variant_fmt fmt,
|
|
const char * filename);
|
|
|
|
/* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
|
|
int tr_variantFromBuf (tr_variant * setme,
|
|
tr_variant_fmt fmt,
|
|
const void * buf,
|
|
size_t buflen,
|
|
const char * optional_source,
|
|
const char ** setme_end);
|
|
|
|
static inline int
|
|
tr_variantFromBenc (tr_variant * setme,
|
|
const void * buf,
|
|
size_t buflen)
|
|
{
|
|
return tr_variantFromBuf (setme, TR_VARIANT_FMT_BENC,
|
|
buf, buflen, NULL, NULL);
|
|
}
|
|
static inline int
|
|
tr_variantFromBencFull (tr_variant * setme,
|
|
const void * buf,
|
|
size_t buflen,
|
|
const char * source,
|
|
const char ** setme_end)
|
|
{
|
|
return tr_variantFromBuf (setme,
|
|
TR_VARIANT_FMT_BENC,
|
|
buf,
|
|
buflen,
|
|
source,
|
|
setme_end);
|
|
}
|
|
static inline int
|
|
tr_variantFromJsonFull (tr_variant * setme,
|
|
const void * buf,
|
|
size_t buflen,
|
|
const char * source,
|
|
const char ** setme_end)
|
|
{
|
|
return tr_variantFromBuf (setme,
|
|
TR_VARIANT_FMT_JSON,
|
|
buf,
|
|
buflen,
|
|
source,
|
|
setme_end);
|
|
}
|
|
static inline int
|
|
tr_variantFromJson (tr_variant * setme,
|
|
const void * buf,
|
|
size_t buflen)
|
|
{
|
|
return tr_variantFromBuf (setme,
|
|
TR_VARIANT_FMT_JSON,
|
|
buf,
|
|
buflen,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
static inline bool
|
|
tr_variantIsType (const tr_variant * b, int type)
|
|
{
|
|
return (b != NULL) && (b->type == type);
|
|
}
|
|
|
|
|
|
/***
|
|
**** Strings
|
|
***/
|
|
|
|
static inline bool
|
|
tr_variantIsString (const tr_variant * b)
|
|
{
|
|
return (b != NULL) && (b->type == TR_VARIANT_TYPE_STR);
|
|
}
|
|
|
|
bool tr_variantGetStr (const tr_variant * variant,
|
|
const char ** setme_str,
|
|
size_t * setme_len);
|
|
|
|
void tr_variantInitStr (tr_variant * initme,
|
|
const void * str,
|
|
int str_len);
|
|
|
|
void tr_variantInitQuark (tr_variant * initme,
|
|
const tr_quark quark);
|
|
|
|
void tr_variantInitRaw (tr_variant * initme,
|
|
const void * raw,
|
|
size_t raw_len);
|
|
|
|
bool tr_variantGetRaw (const tr_variant * variant,
|
|
const uint8_t ** raw_setme,
|
|
size_t * len_setme);
|
|
/***
|
|
**** Real Numbers
|
|
***/
|
|
|
|
static inline bool
|
|
tr_variantIsReal (const tr_variant * v)
|
|
{
|
|
return (v != NULL) && (v->type == TR_VARIANT_TYPE_REAL);
|
|
}
|
|
|
|
void tr_variantInitReal (tr_variant * initme,
|
|
double value);
|
|
|
|
bool tr_variantGetReal (const tr_variant * variant,
|
|
double * value_setme);
|
|
|
|
/***
|
|
**** Booleans
|
|
***/
|
|
|
|
static inline bool
|
|
tr_variantIsBool (const tr_variant * v)
|
|
{
|
|
return (v != NULL) && (v->type == TR_VARIANT_TYPE_BOOL);
|
|
}
|
|
|
|
void tr_variantInitBool (tr_variant * initme,
|
|
bool value);
|
|
|
|
bool tr_variantGetBool (const tr_variant * variant,
|
|
bool * setme);
|
|
|
|
|
|
/***
|
|
**** Ints
|
|
***/
|
|
|
|
static inline bool
|
|
tr_variantIsInt (const tr_variant * v)
|
|
{
|
|
return (v != NULL) && (v->type == TR_VARIANT_TYPE_INT);
|
|
}
|
|
|
|
void tr_variantInitInt (tr_variant * variant,
|
|
int64_t value);
|
|
|
|
bool tr_variantGetInt (const tr_variant * val,
|
|
int64_t * setme);
|
|
|
|
/***
|
|
**** Lists
|
|
***/
|
|
|
|
static inline bool
|
|
tr_variantIsList (const tr_variant * v)
|
|
{
|
|
return (v != NULL) && (v->type == TR_VARIANT_TYPE_LIST);
|
|
}
|
|
|
|
void tr_variantInitList (tr_variant * list,
|
|
size_t reserve_count);
|
|
|
|
void tr_variantListReserve (tr_variant * list,
|
|
size_t reserve_count);
|
|
|
|
tr_variant * tr_variantListAdd (tr_variant * list);
|
|
|
|
tr_variant * tr_variantListAddBool (tr_variant * list,
|
|
bool addme);
|
|
|
|
tr_variant * tr_variantListAddInt (tr_variant * list,
|
|
int64_t addme);
|
|
|
|
tr_variant * tr_variantListAddReal (tr_variant * list,
|
|
double addme);
|
|
|
|
tr_variant * tr_variantListAddStr (tr_variant * list,
|
|
const char * addme);
|
|
|
|
tr_variant * tr_variantListAddQuark (tr_variant * list,
|
|
const tr_quark addme);
|
|
|
|
tr_variant * tr_variantListAddRaw (tr_variant * list,
|
|
const void * addme_value,
|
|
size_t addme_len);
|
|
|
|
tr_variant * tr_variantListAddList (tr_variant * list,
|
|
size_t reserve_count);
|
|
|
|
tr_variant * tr_variantListAddDict (tr_variant * list,
|
|
size_t reserve_count);
|
|
|
|
tr_variant * tr_variantListChild (tr_variant * list,
|
|
size_t pos);
|
|
|
|
bool tr_variantListRemove (tr_variant * list,
|
|
size_t pos);
|
|
|
|
size_t tr_variantListSize (const tr_variant * list);
|
|
|
|
|
|
/***
|
|
**** Dictionaries
|
|
***/
|
|
|
|
static inline bool
|
|
tr_variantIsDict (const tr_variant * v)
|
|
{
|
|
return (v != NULL) && (v->type == TR_VARIANT_TYPE_DICT);
|
|
}
|
|
|
|
void tr_variantInitDict (tr_variant * initme,
|
|
size_t reserve_count);
|
|
|
|
void tr_variantDictReserve (tr_variant * dict,
|
|
size_t reserve_count);
|
|
|
|
bool tr_variantDictRemove (tr_variant * dict,
|
|
const tr_quark key);
|
|
|
|
tr_variant * tr_variantDictAdd (tr_variant * dict,
|
|
const tr_quark key);
|
|
|
|
tr_variant * tr_variantDictAddReal (tr_variant * dict,
|
|
const tr_quark key,
|
|
double value);
|
|
|
|
tr_variant * tr_variantDictAddInt (tr_variant * dict,
|
|
const tr_quark key,
|
|
int64_t value);
|
|
|
|
tr_variant * tr_variantDictAddBool (tr_variant * dict,
|
|
const tr_quark key,
|
|
bool value);
|
|
|
|
tr_variant * tr_variantDictAddStr (tr_variant * dict,
|
|
const tr_quark key,
|
|
const char * value);
|
|
|
|
tr_variant * tr_variantDictAddQuark (tr_variant * dict,
|
|
const tr_quark key,
|
|
const tr_quark val);
|
|
|
|
tr_variant * tr_variantDictAddList (tr_variant * dict,
|
|
const tr_quark key,
|
|
size_t reserve_count);
|
|
|
|
tr_variant * tr_variantDictAddDict (tr_variant * dict,
|
|
const tr_quark key,
|
|
size_t reserve_count);
|
|
|
|
tr_variant * tr_variantDictAddRaw (tr_variant * dict,
|
|
const tr_quark key,
|
|
const void * value,
|
|
size_t len);
|
|
|
|
bool tr_variantDictChild (tr_variant * dict,
|
|
size_t pos,
|
|
tr_quark * setme_key,
|
|
tr_variant ** setme_value);
|
|
|
|
tr_variant * tr_variantDictFind (tr_variant * dict,
|
|
const tr_quark key);
|
|
|
|
bool tr_variantDictFindList (tr_variant * dict,
|
|
const tr_quark key,
|
|
tr_variant ** setme);
|
|
|
|
bool tr_variantDictFindDict (tr_variant * dict,
|
|
const tr_quark key,
|
|
tr_variant ** setme_value);
|
|
|
|
bool tr_variantDictFindInt (tr_variant * dict,
|
|
const tr_quark key,
|
|
int64_t * setme);
|
|
|
|
bool tr_variantDictFindReal (tr_variant * dict,
|
|
const tr_quark key,
|
|
double * setme);
|
|
|
|
bool tr_variantDictFindBool (tr_variant * dict,
|
|
const tr_quark key,
|
|
bool * setme);
|
|
|
|
bool tr_variantDictFindStr (tr_variant * dict,
|
|
const tr_quark key,
|
|
const char ** setme,
|
|
size_t * len);
|
|
|
|
bool tr_variantDictFindRaw (tr_variant * dict,
|
|
const tr_quark key,
|
|
const uint8_t ** setme_raw,
|
|
size_t * setme_len);
|
|
|
|
/* this is only quasi-supported. don't rely on it too heavily outside of libT */
|
|
void tr_variantMergeDicts (tr_variant * dict_target,
|
|
const tr_variant * dict_source);
|
|
|
|
/***
|
|
****
|
|
****
|
|
***/
|
|
|
|
/**
|
|
***
|
|
**/
|
|
|
|
/* @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|