2022-01-20 18:27:56 +00:00
|
|
|
// This file Copyright © 2008-2022 Mnemosyne LLC.
|
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
|
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2016-03-29 16:37:21 +00:00
|
|
|
#pragma once
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
#include <cstddef> // size_t
|
2022-04-08 01:50:26 +00:00
|
|
|
#include <cstdint> // int64_t
|
2022-01-13 02:13:58 +00:00
|
|
|
#include <string>
|
2021-12-15 21:25:42 +00:00
|
|
|
#include <string_view>
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2012-12-23 03:18:39 +00:00
|
|
|
#include "quark.h"
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
struct evbuffer;
|
|
|
|
|
2015-04-11 10:51:59 +00:00
|
|
|
struct tr_error;
|
|
|
|
|
2012-12-14 04:34:42 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2021-10-06 14:26:07 +00:00
|
|
|
enum tr_string_type
|
2012-12-22 20:35:19 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
TR_STRING_TYPE_QUARK,
|
|
|
|
TR_STRING_TYPE_HEAP,
|
2021-11-15 07:21:57 +00:00
|
|
|
TR_STRING_TYPE_BUF,
|
|
|
|
TR_STRING_TYPE_VIEW
|
2021-10-06 14:26:07 +00:00
|
|
|
};
|
2012-12-22 20:35:19 +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!
|
|
|
|
* it's included in the header for inlining and composition */
|
|
|
|
struct tr_variant_string
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_string_type type;
|
|
|
|
size_t len;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
char buf[16];
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2021-08-15 09:41:48 +00:00
|
|
|
} str;
|
2012-12-22 20:35:19 +00:00
|
|
|
};
|
2015-01-02 11:15:31 +00:00
|
|
|
|
2012-12-14 04:34:42 +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!
|
|
|
|
* it's included in the header for inlining and composition */
|
|
|
|
enum
|
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
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
|
2012-12-14 04:34:42 +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!
|
|
|
|
* it's included in the header for inlining and composition */
|
2021-10-06 14:26:07 +00:00
|
|
|
struct tr_variant
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 14:26:07 +00:00
|
|
|
char type = '\0';
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2021-10-06 14:26:07 +00:00
|
|
|
tr_quark key = TR_KEY_NONE;
|
2012-12-24 22:38:41 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
union
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
bool b;
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
double d;
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
int64_t i;
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
struct tr_variant_string s;
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
struct
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
size_t alloc;
|
|
|
|
size_t count;
|
|
|
|
struct tr_variant* vals;
|
2012-12-14 04:34:42 +00:00
|
|
|
} l;
|
2021-10-06 14:26:07 +00:00
|
|
|
} val = {};
|
|
|
|
};
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_variantFree(tr_variant*);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
**** Serialization / Deserialization
|
|
|
|
***/
|
|
|
|
|
2021-10-06 14:26:07 +00:00
|
|
|
enum tr_variant_fmt
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
|
|
|
TR_VARIANT_FMT_BENC,
|
|
|
|
TR_VARIANT_FMT_JSON,
|
|
|
|
TR_VARIANT_FMT_JSON_LEAN /* saves bandwidth by omitting all whitespace. */
|
2021-10-06 14:26:07 +00:00
|
|
|
};
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2022-03-26 03:39:08 +00:00
|
|
|
int tr_variantToFile(tr_variant const* variant, tr_variant_fmt fmt, std::string_view filename);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2021-12-27 22:47:25 +00:00
|
|
|
std::string tr_variantToStr(tr_variant const* variant, tr_variant_fmt fmt);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
struct evbuffer* tr_variantToBuf(tr_variant const* variant, tr_variant_fmt fmt);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2021-11-18 05:37:35 +00:00
|
|
|
enum tr_variant_parse_opts
|
|
|
|
{
|
|
|
|
TR_VARIANT_PARSE_BENC = (1 << 0),
|
|
|
|
TR_VARIANT_PARSE_JSON = (1 << 1),
|
|
|
|
TR_VARIANT_PARSE_INPLACE = (1 << 2)
|
|
|
|
};
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2021-12-24 19:37:34 +00:00
|
|
|
bool tr_variantFromFile(
|
|
|
|
tr_variant* setme,
|
|
|
|
tr_variant_parse_opts opts,
|
2022-03-26 03:39:08 +00:00
|
|
|
std::string_view filename,
|
2021-12-24 19:37:34 +00:00
|
|
|
struct tr_error** error = nullptr);
|
2021-11-18 05:37:35 +00:00
|
|
|
|
|
|
|
bool tr_variantFromBuf(
|
|
|
|
tr_variant* setme,
|
|
|
|
int variant_parse_opts,
|
|
|
|
std::string_view buf,
|
|
|
|
char const** setme_end = nullptr,
|
|
|
|
tr_error** error = nullptr);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsType(tr_variant const* b, int type)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return b != nullptr && b->type == type;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
**** Strings
|
|
|
|
***/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsString(tr_variant const* b)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return b != nullptr && b->type == TR_VARIANT_TYPE_STR;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 21:30:18 +00:00
|
|
|
bool tr_variantGetStrView(tr_variant const* variant, std::string_view* setme);
|
2015-01-02 11:15:31 +00:00
|
|
|
|
2021-10-20 02:30:50 +00:00
|
|
|
void tr_variantInitStr(tr_variant* initme, std::string_view);
|
2021-11-15 07:21:57 +00:00
|
|
|
void tr_variantInitStrView(tr_variant* initme, std::string_view);
|
2017-04-20 16:02:19 +00:00
|
|
|
void tr_variantInitQuark(tr_variant* initme, tr_quark const quark);
|
|
|
|
void tr_variantInitRaw(tr_variant* initme, void const* raw, size_t raw_len);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
bool tr_variantGetRaw(tr_variant const* variant, uint8_t const** raw_setme, size_t* len_setme);
|
2012-12-22 20:35:19 +00:00
|
|
|
|
2012-12-14 04:34:42 +00:00
|
|
|
/***
|
|
|
|
**** Real Numbers
|
|
|
|
***/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsReal(tr_variant const* v)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return v != nullptr && v->type == TR_VARIANT_TYPE_REAL;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_variantInitReal(tr_variant* initme, double value);
|
2017-04-20 16:02:19 +00:00
|
|
|
bool tr_variantGetReal(tr_variant const* variant, double* value_setme);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
**** Booleans
|
|
|
|
***/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsBool(tr_variant const* v)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return v != nullptr && v->type == TR_VARIANT_TYPE_BOOL;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_variantInitBool(tr_variant* initme, bool value);
|
2017-04-20 16:02:19 +00:00
|
|
|
bool tr_variantGetBool(tr_variant const* variant, bool* setme);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
**** Ints
|
|
|
|
***/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsInt(tr_variant const* v)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return v != nullptr && v->type == TR_VARIANT_TYPE_INT;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_variantInitInt(tr_variant* variant, int64_t value);
|
2017-04-20 16:02:19 +00:00
|
|
|
bool tr_variantGetInt(tr_variant const* val, int64_t* setme);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
**** Lists
|
|
|
|
***/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsList(tr_variant const* v)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return v != nullptr && v->type == TR_VARIANT_TYPE_LIST;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_variantInitList(tr_variant* list, size_t reserve_count);
|
|
|
|
void tr_variantListReserve(tr_variant* list, size_t reserve_count);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
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);
|
2021-10-20 02:30:50 +00:00
|
|
|
tr_variant* tr_variantListAddStr(tr_variant* list, std::string_view);
|
2021-11-15 07:21:57 +00:00
|
|
|
tr_variant* tr_variantListAddStrView(tr_variant* list, std::string_view);
|
2017-04-20 16:02:19 +00:00
|
|
|
tr_variant* tr_variantListAddQuark(tr_variant* list, tr_quark const addme);
|
|
|
|
tr_variant* tr_variantListAddRaw(tr_variant* list, void const* addme_value, size_t addme_len);
|
2017-04-19 12:04:45 +00:00
|
|
|
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);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
bool tr_variantListRemove(tr_variant* list, size_t pos);
|
2017-04-20 16:02:19 +00:00
|
|
|
size_t tr_variantListSize(tr_variant const* list);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
**** Dictionaries
|
|
|
|
***/
|
|
|
|
|
2021-10-06 22:24:04 +00:00
|
|
|
constexpr bool tr_variantIsDict(tr_variant const* v)
|
2012-12-14 04:34:42 +00:00
|
|
|
{
|
2021-10-06 16:32:17 +00:00
|
|
|
return v != nullptr && v->type == TR_VARIANT_TYPE_DICT;
|
2012-12-14 04:34:42 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void tr_variantInitDict(tr_variant* initme, size_t reserve_count);
|
|
|
|
void tr_variantDictReserve(tr_variant* dict, size_t reserve_count);
|
2017-04-20 16:02:19 +00:00
|
|
|
bool tr_variantDictRemove(tr_variant* dict, tr_quark const key);
|
|
|
|
|
|
|
|
tr_variant* tr_variantDictAdd(tr_variant* dict, tr_quark const key);
|
|
|
|
tr_variant* tr_variantDictAddReal(tr_variant* dict, tr_quark const key, double value);
|
|
|
|
tr_variant* tr_variantDictAddInt(tr_variant* dict, tr_quark const key, int64_t value);
|
|
|
|
tr_variant* tr_variantDictAddBool(tr_variant* dict, tr_quark const key, bool value);
|
2021-10-20 02:30:50 +00:00
|
|
|
tr_variant* tr_variantDictAddStr(tr_variant* dict, tr_quark const key, std::string_view);
|
2021-11-15 07:21:57 +00:00
|
|
|
tr_variant* tr_variantDictAddStrView(tr_variant* dict, tr_quark const key, std::string_view);
|
2017-04-20 16:02:19 +00:00
|
|
|
tr_variant* tr_variantDictAddQuark(tr_variant* dict, tr_quark const key, tr_quark const val);
|
|
|
|
tr_variant* tr_variantDictAddList(tr_variant* dict, tr_quark const key, size_t reserve_count);
|
|
|
|
tr_variant* tr_variantDictAddDict(tr_variant* dict, tr_quark const key, size_t reserve_count);
|
|
|
|
tr_variant* tr_variantDictSteal(tr_variant* dict, tr_quark const key, tr_variant* value);
|
|
|
|
tr_variant* tr_variantDictAddRaw(tr_variant* dict, tr_quark const key, void const* value, size_t len);
|
2017-04-19 12:04:45 +00:00
|
|
|
|
|
|
|
bool tr_variantDictChild(tr_variant* dict, size_t pos, tr_quark* setme_key, tr_variant** setme_value);
|
2017-04-20 16:02:19 +00:00
|
|
|
tr_variant* tr_variantDictFind(tr_variant* dict, tr_quark const key);
|
|
|
|
bool tr_variantDictFindList(tr_variant* dict, tr_quark const key, tr_variant** setme);
|
|
|
|
bool tr_variantDictFindDict(tr_variant* dict, tr_quark const key, tr_variant** setme_value);
|
|
|
|
bool tr_variantDictFindInt(tr_variant* dict, tr_quark const key, int64_t* setme);
|
|
|
|
bool tr_variantDictFindReal(tr_variant* dict, tr_quark const key, double* setme);
|
|
|
|
bool tr_variantDictFindBool(tr_variant* dict, tr_quark const key, bool* setme);
|
2021-11-01 21:30:18 +00:00
|
|
|
bool tr_variantDictFindStrView(tr_variant* dict, tr_quark const key, std::string_view* setme);
|
2017-04-20 16:02:19 +00:00
|
|
|
bool tr_variantDictFindRaw(tr_variant* dict, tr_quark const key, uint8_t const** setme_raw, size_t* setme_len);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/* this is only quasi-supported. don't rely on it too heavily outside of libT */
|
2017-04-20 16:02:19 +00:00
|
|
|
void tr_variantMergeDicts(tr_variant* dict_target, tr_variant const* dict_source);
|
2012-12-14 04:34:42 +00:00
|
|
|
|
|
|
|
/* @} */
|