refactor: make tr_variantFromBuf() public (#2187)
* refactor: add tr_variantFromBuf() and support inplace json/benc parsing
This commit is contained in:
parent
36f5d56cfe
commit
a79a868257
|
@ -1298,7 +1298,7 @@ bool Application::Impl::call_rpc_for_selected_torrents(std::string const& method
|
|||
auto* session = core_->get_session();
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, method);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, method);
|
||||
args = tr_variantDictAddDict(&top, TR_KEY_arguments, 1);
|
||||
ids = tr_variantDictAddList(args, TR_KEY_ids, 0);
|
||||
sel_->selected_foreach(
|
||||
|
@ -1337,7 +1337,7 @@ void Application::Impl::start_all_torrents()
|
|||
tr_variant request;
|
||||
|
||||
tr_variantInitDict(&request, 1);
|
||||
tr_variantDictAddStr(&request, TR_KEY_method, "torrent-start"sv);
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, "torrent-start"sv);
|
||||
tr_rpc_request_exec_json(session, &request, nullptr, nullptr);
|
||||
tr_variantFree(&request);
|
||||
}
|
||||
|
@ -1348,7 +1348,7 @@ void Application::Impl::pause_all_torrents()
|
|||
tr_variant request;
|
||||
|
||||
tr_variantInitDict(&request, 1);
|
||||
tr_variantDictAddStr(&request, TR_KEY_method, "torrent-stop"sv);
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, "torrent-stop"sv);
|
||||
tr_rpc_request_exec_json(session, &request, nullptr, nullptr);
|
||||
tr_variantFree(&request);
|
||||
}
|
||||
|
|
|
@ -393,7 +393,7 @@ void DetailsDialog::Impl::torrent_set_bool(tr_quark key, bool value)
|
|||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddBool(args, key, value);
|
||||
tr_variant* const ids = tr_variantDictAddList(args, TR_KEY_ids, ids_.size());
|
||||
|
@ -412,7 +412,7 @@ void DetailsDialog::Impl::torrent_set_int(tr_quark key, int value)
|
|||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddInt(args, key, value);
|
||||
tr_variant* const ids = tr_variantDictAddList(args, TR_KEY_ids, ids_.size());
|
||||
|
@ -431,7 +431,7 @@ void DetailsDialog::Impl::torrent_set_real(tr_quark key, double value)
|
|||
tr_variant top;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddReal(args, key, value);
|
||||
tr_variant* const ids = tr_variantDictAddList(args, TR_KEY_ids, ids_.size());
|
||||
|
@ -2385,7 +2385,7 @@ void DetailsDialog::Impl::on_add_tracker_response(int response, Gtk::Dialog* dia
|
|||
tr_variant* trackers;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-set"sv);
|
||||
args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddInt(args, TR_KEY_id, torrent_id);
|
||||
trackers = tr_variantDictAddList(args, TR_KEY_trackerAdd, 1);
|
||||
|
@ -2455,7 +2455,7 @@ void DetailsDialog::Impl::on_tracker_list_remove_button_clicked()
|
|||
tr_variant* trackers;
|
||||
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-set"sv);
|
||||
args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddInt(args, TR_KEY_id, torrent_id);
|
||||
trackers = tr_variantDictAddList(args, TR_KEY_trackerRemove, 1);
|
||||
|
|
|
@ -1445,7 +1445,7 @@ void Session::start_now(int id)
|
|||
{
|
||||
tr_variant top;
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-start-now");
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-start-now");
|
||||
|
||||
auto args = tr_variantDictAddDict(&top, TR_KEY_arguments, 1);
|
||||
auto ids = tr_variantDictAddList(args, TR_KEY_ids, 1);
|
||||
|
@ -1712,7 +1712,7 @@ void Session::port_test()
|
|||
|
||||
tr_variant request;
|
||||
tr_variantInitDict(&request, 2);
|
||||
tr_variantDictAddStr(&request, TR_KEY_method, "port-test");
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, "port-test");
|
||||
tr_variantDictAddInt(&request, TR_KEY_tag, tag);
|
||||
impl_->send_rpc_request(
|
||||
&request,
|
||||
|
@ -1743,7 +1743,7 @@ void Session::blocklist_update()
|
|||
|
||||
tr_variant request;
|
||||
tr_variantInitDict(&request, 2);
|
||||
tr_variantDictAddStr(&request, TR_KEY_method, "blocklist-update");
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, "blocklist-update");
|
||||
tr_variantDictAddInt(&request, TR_KEY_tag, tag);
|
||||
impl_->send_rpc_request(
|
||||
&request,
|
||||
|
|
|
@ -218,7 +218,7 @@ static void on_announce_done(
|
|||
else
|
||||
{
|
||||
tr_variant benc;
|
||||
bool const variant_loaded = tr_variantFromBenc(&benc, msg) == 0;
|
||||
auto const variant_loaded = tr_variantFromBuf(&benc, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, msg);
|
||||
|
||||
if (tr_env_key_exists("TR_CURL_VERBOSE"))
|
||||
{
|
||||
|
@ -390,7 +390,8 @@ static void on_scrape_done(
|
|||
else
|
||||
{
|
||||
auto top = tr_variant{};
|
||||
auto const variant_loaded = tr_variantFromBenc(&top, msg) == 0;
|
||||
|
||||
auto const variant_loaded = tr_variantFromBuf(&top, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, msg);
|
||||
|
||||
if (tr_env_key_exists("TR_CURL_VERBOSE"))
|
||||
{
|
||||
|
|
|
@ -477,9 +477,9 @@ static void tr_realMakeMetaInfo(tr_metainfo_builder* builder)
|
|||
tr_variantDictAddStr(&top, TR_KEY_comment, builder->comment);
|
||||
}
|
||||
|
||||
tr_variantDictAddStr(&top, TR_KEY_created_by, TR_NAME "/" LONG_VERSION_STRING);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_created_by, TR_NAME "/" LONG_VERSION_STRING);
|
||||
tr_variantDictAddInt(&top, TR_KEY_creation_date, time(nullptr));
|
||||
tr_variantDictAddStr(&top, TR_KEY_encoding, "UTF-8");
|
||||
tr_variantDictAddStrView(&top, TR_KEY_encoding, "UTF-8");
|
||||
makeInfoDict(tr_variantDictAddDict(&top, TR_KEY_info, 666), builder);
|
||||
}
|
||||
|
||||
|
|
|
@ -1124,7 +1124,7 @@ static void parseLtepHandshake(tr_peerMsgsImpl* msgs, uint32_t len, struct evbuf
|
|||
msgs->peerSentLtepHandshake = true;
|
||||
|
||||
auto val = tr_variant{};
|
||||
if (tr_variantFromBenc(&val, { tmp, len }) != 0 || !tr_variantIsDict(&val))
|
||||
if (!tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, { tmp, len }) || !tr_variantIsDict(&val))
|
||||
{
|
||||
dbgmsg(msgs, "GET extended-handshake, couldn't get dictionary");
|
||||
tr_free(tmp);
|
||||
|
@ -1241,7 +1241,7 @@ static void parseUtMetadata(tr_peerMsgsImpl* msgs, uint32_t msglen, struct evbuf
|
|||
|
||||
auto dict = tr_variant{};
|
||||
char const* benc_end = nullptr;
|
||||
if (tr_variantFromBenc(&dict, std::string_view{ tmp, msglen }, &benc_end) == 0)
|
||||
if (tr_variantFromBuf(&dict, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, { tmp, msglen }, &benc_end))
|
||||
{
|
||||
(void)tr_variantDictFindInt(&dict, TR_KEY_msg_type, &msg_type);
|
||||
(void)tr_variantDictFindInt(&dict, TR_KEY_piece, &piece);
|
||||
|
@ -1310,52 +1310,50 @@ static void parseUtPex(tr_peerMsgsImpl* msgs, uint32_t msglen, struct evbuffer*
|
|||
tr_peerIoReadBytes(msgs->io, inbuf, tmp, msglen);
|
||||
|
||||
tr_variant val;
|
||||
bool const loaded = tr_variantFromBenc(&val, std::string_view{ tmp, msglen }) == 0;
|
||||
bool const loaded = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, { tmp, msglen });
|
||||
|
||||
if (loaded)
|
||||
{
|
||||
uint8_t const* added = nullptr;
|
||||
auto added_len = size_t{};
|
||||
if (tr_variantDictFindRaw(&val, TR_KEY_added, &added, &added_len))
|
||||
{
|
||||
uint8_t const* added_f = nullptr;
|
||||
auto added_f_len = size_t{};
|
||||
if (!tr_variantDictFindRaw(&val, TR_KEY_added_f, &added_f, &added_f_len))
|
||||
{
|
||||
added_f_len = 0;
|
||||
added_f = nullptr;
|
||||
}
|
||||
|
||||
auto n = size_t{};
|
||||
tr_pex* const pex = tr_peerMgrCompactToPex(added, added_len, added_f, added_f_len, &n);
|
||||
n = std::min(n, size_t{ MAX_PEX_PEER_COUNT });
|
||||
tr_peerMgrAddPex(tor, TR_PEER_FROM_PEX, pex, n);
|
||||
tr_free(pex);
|
||||
}
|
||||
|
||||
if (tr_variantDictFindRaw(&val, TR_KEY_added6, &added, &added_len))
|
||||
{
|
||||
uint8_t const* added_f = nullptr;
|
||||
auto added_f_len = size_t{};
|
||||
if (!tr_variantDictFindRaw(&val, TR_KEY_added6_f, &added_f, &added_f_len))
|
||||
{
|
||||
added_f_len = 0;
|
||||
added_f = nullptr;
|
||||
}
|
||||
|
||||
auto n = size_t{};
|
||||
tr_pex* const pex = tr_peerMgrCompact6ToPex(added, added_len, added_f, added_f_len, &n);
|
||||
n = std::min(n, size_t{ MAX_PEX_PEER_COUNT });
|
||||
tr_peerMgrAddPex(tor, TR_PEER_FROM_PEX, pex, n);
|
||||
tr_free(pex);
|
||||
}
|
||||
|
||||
tr_variantFree(&val);
|
||||
}
|
||||
|
||||
tr_free(tmp);
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t const* added = nullptr;
|
||||
auto added_len = size_t{};
|
||||
if (tr_variantDictFindRaw(&val, TR_KEY_added, &added, &added_len))
|
||||
{
|
||||
uint8_t const* added_f = nullptr;
|
||||
auto added_f_len = size_t{};
|
||||
if (!tr_variantDictFindRaw(&val, TR_KEY_added_f, &added_f, &added_f_len))
|
||||
{
|
||||
added_f_len = 0;
|
||||
added_f = nullptr;
|
||||
}
|
||||
|
||||
auto n = size_t{};
|
||||
tr_pex* const pex = tr_peerMgrCompactToPex(added, added_len, added_f, added_f_len, &n);
|
||||
n = std::min(n, size_t{ MAX_PEX_PEER_COUNT });
|
||||
tr_peerMgrAddPex(tor, TR_PEER_FROM_PEX, pex, n);
|
||||
tr_free(pex);
|
||||
}
|
||||
|
||||
if (tr_variantDictFindRaw(&val, TR_KEY_added6, &added, &added_len))
|
||||
{
|
||||
uint8_t const* added_f = nullptr;
|
||||
auto added_f_len = size_t{};
|
||||
if (!tr_variantDictFindRaw(&val, TR_KEY_added6_f, &added_f, &added_f_len))
|
||||
{
|
||||
added_f_len = 0;
|
||||
added_f = nullptr;
|
||||
}
|
||||
|
||||
auto n = size_t{};
|
||||
tr_pex* const pex = tr_peerMgrCompact6ToPex(added, added_len, added_f, added_f_len, &n);
|
||||
n = std::min(n, size_t{ MAX_PEX_PEER_COUNT });
|
||||
tr_peerMgrAddPex(tor, TR_PEER_FROM_PEX, pex, n);
|
||||
tr_free(pex);
|
||||
}
|
||||
|
||||
tr_variantFree(&val);
|
||||
}
|
||||
|
||||
static void sendPex(tr_peerMsgsImpl* msgs);
|
||||
|
|
|
@ -382,7 +382,7 @@ static uint64_t loadIdleLimits(tr_variant* dict, tr_torrent* tor)
|
|||
|
||||
static void saveName(tr_variant* dict, tr_torrent const* tor)
|
||||
{
|
||||
tr_variantDictAddStr(dict, TR_KEY_name, tr_torrentName(tor));
|
||||
tr_variantDictAddStrView(dict, TR_KEY_name, tr_torrentName(tor));
|
||||
}
|
||||
|
||||
static uint64_t loadName(tr_variant* dict, tr_torrent* tor)
|
||||
|
@ -424,7 +424,7 @@ static void saveFilenames(tr_variant* dict, tr_torrent const* tor)
|
|||
|
||||
for (tr_file_index_t i = 0; i < n; ++i)
|
||||
{
|
||||
tr_variantListAddStr(list, files[i].is_renamed ? files[i].name : "");
|
||||
tr_variantListAddStrView(list, files[i].is_renamed ? files[i].name : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ static void bitfieldToRaw(tr_bitfield const* b, tr_variant* benc)
|
|||
}
|
||||
else if (b->hasAll())
|
||||
{
|
||||
tr_variantInitStr(benc, "all"sv);
|
||||
tr_variantInitStrView(benc, "all"sv);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -510,7 +510,7 @@ static void saveProgress(tr_variant* dict, tr_torrent* tor)
|
|||
/* add the progress */
|
||||
if (tor->completeness == TR_SEED)
|
||||
{
|
||||
tr_variantDictAddStr(prog, TR_KEY_have, "all"sv);
|
||||
tr_variantDictAddStrView(prog, TR_KEY_have, "all"sv);
|
||||
}
|
||||
|
||||
/* add the blocks bitfield */
|
||||
|
@ -691,7 +691,7 @@ void tr_torrentSaveResume(tr_torrent* tor)
|
|||
tr_variantDictAddInt(&top, TR_KEY_added_date, tor->addedDate);
|
||||
tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->corruptPrev + tor->corruptCur);
|
||||
tr_variantDictAddInt(&top, TR_KEY_done_date, tor->doneDate);
|
||||
tr_variantDictAddStr(&top, TR_KEY_destination, tor->downloadDir);
|
||||
tr_variantDictAddStrView(&top, TR_KEY_destination, tor->downloadDir);
|
||||
|
||||
if (tor->incompleteDir != nullptr)
|
||||
{
|
||||
|
@ -748,15 +748,21 @@ static uint64_t loadFromFile(tr_torrent* tor, uint64_t fieldsToLoad, bool* didRe
|
|||
}
|
||||
|
||||
char* const filename = getResumeFilename(tor, TR_METAINFO_BASENAME_HASH);
|
||||
|
||||
if (!tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename, &error))
|
||||
auto buf = std::vector<char>{};
|
||||
if (!tr_loadFile(buf, filename, &error) ||
|
||||
!tr_variantFromBuf(
|
||||
&top,
|
||||
TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE,
|
||||
{ std::data(buf), std::size(buf) },
|
||||
nullptr,
|
||||
&error))
|
||||
{
|
||||
tr_logAddTorDbg(tor, "Couldn't read \"%s\": %s", filename, error->message);
|
||||
tr_error_clear(&error);
|
||||
|
||||
char* old_filename = getResumeFilename(tor, TR_METAINFO_BASENAME_NAME_AND_PARTIAL_HASH);
|
||||
|
||||
if (!tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, old_filename, &error))
|
||||
if (!tr_variantFromFile(&top, TR_VARIANT_PARSE_BENC, old_filename, &error))
|
||||
{
|
||||
tr_logAddTorDbg(tor, "Couldn't read \"%s\" either: %s", old_filename, error->message);
|
||||
tr_error_free(error);
|
||||
|
|
|
@ -184,7 +184,7 @@ static void handle_upload(struct evhttp_request* req, tr_rpc_server* server)
|
|||
|
||||
auto top = tr_variant{};
|
||||
tr_variantInitDict(&top, 2);
|
||||
tr_variantDictAddStr(&top, TR_KEY_method, "torrent-add");
|
||||
tr_variantDictAddStrView(&top, TR_KEY_method, "torrent-add");
|
||||
auto* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 2);
|
||||
tr_variantDictAddBool(args, TR_KEY_paused, paused);
|
||||
|
||||
|
@ -195,7 +195,7 @@ static void handle_upload(struct evhttp_request* req, tr_rpc_server* server)
|
|||
tr_variantDictAddStrView(args, TR_KEY_filename, body);
|
||||
have_source = true;
|
||||
}
|
||||
else if (tr_variantFromBenc(&test, body) == 0)
|
||||
else if (tr_variantFromBuf(&test, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, body))
|
||||
{
|
||||
auto* b64 = static_cast<char*>(tr_base64_encode(body.c_str(), body_len, nullptr));
|
||||
tr_variantDictAddStr(args, TR_KEY_metainfo, b64);
|
||||
|
@ -458,7 +458,7 @@ static void rpc_response_func(tr_session* /*session*/, tr_variant* response, voi
|
|||
static void handle_rpc_from_json(struct evhttp_request* req, tr_rpc_server* server, std::string_view json)
|
||||
{
|
||||
auto top = tr_variant{};
|
||||
auto const have_content = tr_variantFromJson(&top, json) == 0;
|
||||
auto const have_content = tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, json);
|
||||
|
||||
auto* const data = tr_new0(struct rpc_response_data, 1);
|
||||
data->req = req;
|
||||
|
|
|
@ -420,9 +420,9 @@ static void addTrackers(tr_info const* info, tr_variant* trackers)
|
|||
{
|
||||
tr_tracker_info const* t = &info->trackers[i];
|
||||
tr_variant* d = tr_variantListAddDict(trackers, 4);
|
||||
tr_variantDictAddStr(d, TR_KEY_announce, t->announce);
|
||||
tr_variantDictAddStrView(d, TR_KEY_announce, t->announce);
|
||||
tr_variantDictAddInt(d, TR_KEY_id, t->id);
|
||||
tr_variantDictAddStr(d, TR_KEY_scrape, t->scrape);
|
||||
tr_variantDictAddStrView(d, TR_KEY_scrape, t->scrape);
|
||||
tr_variantDictAddInt(d, TR_KEY_tier, t->tier);
|
||||
}
|
||||
}
|
||||
|
@ -542,7 +542,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_downloadDir:
|
||||
tr_variantInitStr(initme, tr_torrentGetDownloadDir(tor));
|
||||
tr_variantInitStrView(initme, tr_torrentGetDownloadDir(tor));
|
||||
break;
|
||||
|
||||
case TR_KEY_downloadedEver:
|
||||
|
@ -562,7 +562,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_errorString:
|
||||
tr_variantInitStr(initme, st->errorString);
|
||||
tr_variantInitStrView(initme, st->errorString);
|
||||
break;
|
||||
|
||||
case TR_KEY_eta:
|
||||
|
@ -584,7 +584,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_hashString:
|
||||
tr_variantInitStr(initme, tor->info.hashString);
|
||||
tr_variantInitStrView(initme, tor->info.hashString);
|
||||
break;
|
||||
|
||||
case TR_KEY_haveUnchecked:
|
||||
|
@ -646,7 +646,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_name:
|
||||
tr_variantInitStr(initme, tr_torrentName(tor));
|
||||
tr_variantInitStrView(initme, tr_torrentName(tor));
|
||||
break;
|
||||
|
||||
case TR_KEY_percentDone:
|
||||
|
@ -697,7 +697,7 @@ static void initField(
|
|||
}
|
||||
else
|
||||
{
|
||||
tr_variantInitStr(initme, ""sv);
|
||||
tr_variantInitStrView(initme, ""sv);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -711,7 +711,7 @@ static void initField(
|
|||
break;
|
||||
|
||||
case TR_KEY_primary_mime_type:
|
||||
tr_variantInitStr(initme, tr_torrentPrimaryMimeType(tor));
|
||||
tr_variantInitStrView(initme, tr_torrentPrimaryMimeType(tor));
|
||||
break;
|
||||
|
||||
case TR_KEY_priorities:
|
||||
|
@ -2290,7 +2290,7 @@ static void addSessionField(tr_session* s, tr_variant* d, tr_quark key)
|
|||
break;
|
||||
|
||||
case TR_KEY_rpc_version_semver:
|
||||
tr_variantDictAddStr(d, key, RPC_VERSION_SEMVER);
|
||||
tr_variantDictAddStrView(d, key, RPC_VERSION_SEMVER);
|
||||
break;
|
||||
|
||||
case TR_KEY_rpc_version_minimum:
|
||||
|
@ -2382,7 +2382,7 @@ static void addSessionField(tr_session* s, tr_variant* d, tr_quark key)
|
|||
break;
|
||||
|
||||
case TR_KEY_version:
|
||||
tr_variantDictAddStr(d, key, LONG_VERSION_STRING);
|
||||
tr_variantDictAddStrView(d, key, LONG_VERSION_STRING);
|
||||
break;
|
||||
|
||||
case TR_KEY_encryption:
|
||||
|
|
|
@ -324,7 +324,7 @@ void tr_sessionGetDefaultSettings(tr_variant* d)
|
|||
|
||||
tr_variantDictReserve(d, 69);
|
||||
tr_variantDictAddBool(d, TR_KEY_blocklist_enabled, false);
|
||||
tr_variantDictAddStr(d, TR_KEY_blocklist_url, "http://www.example.com/blocklist"sv);
|
||||
tr_variantDictAddStrView(d, TR_KEY_blocklist_url, "http://www.example.com/blocklist"sv);
|
||||
tr_variantDictAddInt(d, TR_KEY_cache_size_mb, DefaultCacheSizeMB);
|
||||
tr_variantDictAddBool(d, TR_KEY_dht_enabled, true);
|
||||
tr_variantDictAddBool(d, TR_KEY_utp_enabled, true);
|
||||
|
@ -346,7 +346,7 @@ void tr_sessionGetDefaultSettings(tr_variant* d)
|
|||
tr_variantDictAddBool(d, TR_KEY_peer_port_random_on_start, false);
|
||||
tr_variantDictAddInt(d, TR_KEY_peer_port_random_low, 49152);
|
||||
tr_variantDictAddInt(d, TR_KEY_peer_port_random_high, 65535);
|
||||
tr_variantDictAddStr(d, TR_KEY_peer_socket_tos, TR_DEFAULT_PEER_SOCKET_TOS_STR);
|
||||
tr_variantDictAddStrView(d, TR_KEY_peer_socket_tos, TR_DEFAULT_PEER_SOCKET_TOS_STR);
|
||||
tr_variantDictAddBool(d, TR_KEY_pex_enabled, true);
|
||||
tr_variantDictAddBool(d, TR_KEY_port_forwarding_enabled, true);
|
||||
tr_variantDictAddInt(d, TR_KEY_preallocation, TR_PREALLOCATE_SPARSE);
|
||||
|
@ -358,20 +358,20 @@ void tr_sessionGetDefaultSettings(tr_variant* d)
|
|||
tr_variantDictAddBool(d, TR_KEY_ratio_limit_enabled, false);
|
||||
tr_variantDictAddBool(d, TR_KEY_rename_partial_files, true);
|
||||
tr_variantDictAddBool(d, TR_KEY_rpc_authentication_required, false);
|
||||
tr_variantDictAddStr(d, TR_KEY_rpc_bind_address, "0.0.0.0");
|
||||
tr_variantDictAddStrView(d, TR_KEY_rpc_bind_address, "0.0.0.0");
|
||||
tr_variantDictAddBool(d, TR_KEY_rpc_enabled, false);
|
||||
tr_variantDictAddStr(d, TR_KEY_rpc_password, "");
|
||||
tr_variantDictAddStr(d, TR_KEY_rpc_username, "");
|
||||
tr_variantDictAddStr(d, TR_KEY_rpc_whitelist, TR_DEFAULT_RPC_WHITELIST);
|
||||
tr_variantDictAddStrView(d, TR_KEY_rpc_password, "");
|
||||
tr_variantDictAddStrView(d, TR_KEY_rpc_username, "");
|
||||
tr_variantDictAddStrView(d, TR_KEY_rpc_whitelist, TR_DEFAULT_RPC_WHITELIST);
|
||||
tr_variantDictAddBool(d, TR_KEY_rpc_whitelist_enabled, true);
|
||||
tr_variantDictAddStr(d, TR_KEY_rpc_host_whitelist, TR_DEFAULT_RPC_HOST_WHITELIST);
|
||||
tr_variantDictAddStrView(d, TR_KEY_rpc_host_whitelist, TR_DEFAULT_RPC_HOST_WHITELIST);
|
||||
tr_variantDictAddBool(d, TR_KEY_rpc_host_whitelist_enabled, true);
|
||||
tr_variantDictAddInt(d, TR_KEY_rpc_port, TR_DEFAULT_RPC_PORT);
|
||||
tr_variantDictAddStr(d, TR_KEY_rpc_url, TR_DEFAULT_RPC_URL_STR);
|
||||
tr_variantDictAddStrView(d, TR_KEY_rpc_url, TR_DEFAULT_RPC_URL_STR);
|
||||
tr_variantDictAddBool(d, TR_KEY_scrape_paused_torrents_enabled, true);
|
||||
tr_variantDictAddStr(d, TR_KEY_script_torrent_added_filename, "");
|
||||
tr_variantDictAddStrView(d, TR_KEY_script_torrent_added_filename, "");
|
||||
tr_variantDictAddBool(d, TR_KEY_script_torrent_added_enabled, false);
|
||||
tr_variantDictAddStr(d, TR_KEY_script_torrent_done_filename, "");
|
||||
tr_variantDictAddStrView(d, TR_KEY_script_torrent_done_filename, "");
|
||||
tr_variantDictAddBool(d, TR_KEY_script_torrent_done_enabled, false);
|
||||
tr_variantDictAddInt(d, TR_KEY_seed_queue_size, 10);
|
||||
tr_variantDictAddBool(d, TR_KEY_seed_queue_enabled, false);
|
||||
|
@ -386,8 +386,8 @@ void tr_sessionGetDefaultSettings(tr_variant* d)
|
|||
tr_variantDictAddBool(d, TR_KEY_speed_limit_up_enabled, false);
|
||||
tr_variantDictAddInt(d, TR_KEY_umask, 022);
|
||||
tr_variantDictAddInt(d, TR_KEY_upload_slots_per_torrent, 14);
|
||||
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv4, TR_DEFAULT_BIND_ADDRESS_IPV4);
|
||||
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv6, TR_DEFAULT_BIND_ADDRESS_IPV6);
|
||||
tr_variantDictAddStrView(d, TR_KEY_bind_address_ipv4, TR_DEFAULT_BIND_ADDRESS_IPV4);
|
||||
tr_variantDictAddStrView(d, TR_KEY_bind_address_ipv6, TR_DEFAULT_BIND_ADDRESS_IPV6);
|
||||
tr_variantDictAddBool(d, TR_KEY_start_added_torrents, true);
|
||||
tr_variantDictAddBool(d, TR_KEY_trash_original_torrent_files, false);
|
||||
tr_variantDictAddInt(d, TR_KEY_anti_brute_force_threshold, 100);
|
||||
|
@ -491,7 +491,7 @@ bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const*
|
|||
auto fileSettings = tr_variant{};
|
||||
auto const filename = tr_strvPath(configDir, "settings.json"sv);
|
||||
auto success = bool{};
|
||||
if (tr_error* error = nullptr; tr_variantFromFile(&fileSettings, TR_VARIANT_FMT_JSON, filename.c_str(), &error))
|
||||
if (tr_error* error = nullptr; tr_variantFromFile(&fileSettings, TR_VARIANT_PARSE_JSON, filename.c_str(), &error))
|
||||
{
|
||||
tr_variantMergeDicts(dict, &fileSettings);
|
||||
tr_variantFree(&fileSettings);
|
||||
|
@ -520,7 +520,7 @@ void tr_sessionSaveSettings(tr_session* session, char const* configDir, tr_varia
|
|||
{
|
||||
tr_variant fileSettings;
|
||||
|
||||
if (tr_variantFromFile(&fileSettings, TR_VARIANT_FMT_JSON, filename.c_str(), nullptr))
|
||||
if (tr_variantFromFile(&fileSettings, TR_VARIANT_PARSE_JSON, filename.c_str(), nullptr))
|
||||
{
|
||||
tr_variantMergeDicts(&settings, &fileSettings);
|
||||
tr_variantFree(&fileSettings);
|
||||
|
|
|
@ -42,12 +42,12 @@ static void loadCumulativeStats(tr_session const* session, tr_session_stats* set
|
|||
auto top = tr_variant{};
|
||||
|
||||
auto filename = getFilename(session);
|
||||
bool loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_JSON, filename.c_str(), nullptr);
|
||||
bool loaded = tr_variantFromFile(&top, TR_VARIANT_PARSE_JSON, filename.c_str(), nullptr);
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
filename = getOldFilename(session);
|
||||
loaded = tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename.c_str(), nullptr);
|
||||
loaded = tr_variantFromFile(&top, TR_VARIANT_PARSE_BENC, filename.c_str(), nullptr);
|
||||
}
|
||||
|
||||
if (loaded)
|
||||
|
|
|
@ -80,13 +80,22 @@ static void clearMetainfo(tr_ctor* ctor)
|
|||
setSourceFile(ctor, nullptr);
|
||||
}
|
||||
|
||||
static int parseMetainfoContents(tr_ctor* ctor)
|
||||
{
|
||||
auto& contents = ctor->contents;
|
||||
auto sv = std::string_view{ std::data(contents), std::size(contents) };
|
||||
ctor->isSet_metainfo = tr_variantFromBuf(&ctor->metainfo, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, sv);
|
||||
return ctor->isSet_metainfo ? 0 : EILSEQ;
|
||||
}
|
||||
|
||||
int tr_ctorSetMetainfo(tr_ctor* ctor, void const* metainfo, size_t len)
|
||||
{
|
||||
clearMetainfo(ctor);
|
||||
auto sv = std::string_view{ static_cast<char const*>(metainfo), len };
|
||||
auto const err = tr_variantFromBenc(&ctor->metainfo, sv);
|
||||
ctor->isSet_metainfo = err == 0;
|
||||
return err;
|
||||
|
||||
ctor->contents.resize(len);
|
||||
std::copy_n(static_cast<char const*>(metainfo), len, std::begin(ctor->contents));
|
||||
|
||||
return parseMetainfoContents(ctor);
|
||||
}
|
||||
|
||||
char const* tr_ctorGetSourceFile(tr_ctor const* ctor)
|
||||
|
@ -115,13 +124,14 @@ int tr_ctorSetMetainfoFromMagnetLink(tr_ctor* ctor, char const* magnet_link)
|
|||
|
||||
int tr_ctorSetMetainfoFromFile(tr_ctor* ctor, char const* filename)
|
||||
{
|
||||
clearMetainfo(ctor);
|
||||
|
||||
if (!tr_loadFile(ctor->contents, filename, nullptr) || std::empty(ctor->contents))
|
||||
{
|
||||
clearMetainfo(ctor);
|
||||
return EILSEQ;
|
||||
}
|
||||
|
||||
int const err = tr_ctorSetMetainfo(ctor, std::data(ctor->contents), std::size(ctor->contents));
|
||||
int const err = parseMetainfoContents(ctor);
|
||||
if (err)
|
||||
{
|
||||
clearMetainfo(ctor);
|
||||
|
|
|
@ -119,7 +119,8 @@ static size_t findInfoDictOffset(tr_torrent const* tor)
|
|||
if (fileContents != nullptr)
|
||||
{
|
||||
auto top = tr_variant{};
|
||||
if (tr_variantFromBenc(&top, std::string_view{ reinterpret_cast<char const*>(fileContents), fileLen }) == 0)
|
||||
auto const contents_sv = std::string_view{ reinterpret_cast<char const*>(fileContents), fileLen };
|
||||
if (tr_variantFromBuf(&top, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, contents_sv))
|
||||
{
|
||||
tr_variant* infoDict = nullptr;
|
||||
if (tr_variantDictFindDict(&top, TR_KEY_info, &infoDict))
|
||||
|
@ -276,19 +277,16 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, in
|
|||
if (checksumPassed)
|
||||
{
|
||||
/* checksum passed; now try to parse it as benc */
|
||||
tr_variant infoDict;
|
||||
auto metadata_sv = std::string_view{ m->metadata, m->metadata_size };
|
||||
int const err = tr_variantFromBenc(&infoDict, metadata_sv);
|
||||
dbgmsg(tor, "err is %d", err);
|
||||
|
||||
metainfoParsed = err == 0;
|
||||
auto infoDict = tr_variant{};
|
||||
auto const metadata_sv = std::string_view{ m->metadata, m->metadata_size };
|
||||
metainfoParsed = tr_variantFromBuf(&infoDict, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, metadata_sv);
|
||||
if (metainfoParsed)
|
||||
{
|
||||
/* yay we have bencoded metainfo... merge it into our .torrent file */
|
||||
tr_variant newMetainfo;
|
||||
char* path = tr_strdup(tor->info.torrent);
|
||||
|
||||
if (tr_variantFromFile(&newMetainfo, TR_VARIANT_FMT_BENC, path, nullptr))
|
||||
if (tr_variantFromFile(&newMetainfo, TR_VARIANT_PARSE_BENC, path, nullptr))
|
||||
{
|
||||
/* remove any old .torrent and .resume files */
|
||||
tr_sys_path_remove(path, nullptr);
|
||||
|
|
|
@ -2566,7 +2566,7 @@ bool tr_torrentSetAnnounceList(tr_torrent* tor, tr_tracker_info const* trackers_
|
|||
}
|
||||
|
||||
/* save to the .torrent file */
|
||||
if (ok && tr_variantFromFile(&metainfo, TR_VARIANT_FMT_BENC, tor->info.torrent, nullptr))
|
||||
if (ok && tr_variantFromFile(&metainfo, TR_VARIANT_PARSE_BENC, tor->info.torrent, nullptr))
|
||||
{
|
||||
/* remove the old fields */
|
||||
tr_variantDictRemove(&metainfo, TR_KEY_announce);
|
||||
|
|
|
@ -315,14 +315,14 @@ int tr_dhtInit(tr_session* ss)
|
|||
|
||||
auto const dat_file = tr_strvPath(ss->configDir, "dht.dat"sv);
|
||||
auto benc = tr_variant{};
|
||||
int rc = tr_variantFromFile(&benc, TR_VARIANT_FMT_BENC, dat_file.c_str(), nullptr) ? 0 : -1;
|
||||
auto const ok = tr_variantFromFile(&benc, TR_VARIANT_PARSE_JSON, dat_file.c_str());
|
||||
|
||||
bool have_id = false;
|
||||
uint8_t* nodes = nullptr;
|
||||
uint8_t* nodes6 = nullptr;
|
||||
size_t len = 0;
|
||||
size_t len6 = 0;
|
||||
if (rc == 0)
|
||||
if (ok)
|
||||
{
|
||||
uint8_t const* raw = nullptr;
|
||||
have_id = tr_variantDictFindRaw(&benc, TR_KEY_id, &raw, &len);
|
||||
|
@ -365,8 +365,7 @@ int tr_dhtInit(tr_session* ss)
|
|||
tr_rand_buffer(myid, 20);
|
||||
}
|
||||
|
||||
rc = dht_init(ss->udp_socket, ss->udp6_socket, myid, nullptr);
|
||||
|
||||
int rc = dht_init(ss->udp_socket, ss->udp6_socket, myid, nullptr);
|
||||
if (rc < 0)
|
||||
{
|
||||
tr_free(nodes6);
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
#define LIBTRANSMISSION_VARIANT_MODULE
|
||||
|
||||
#include "transmission.h"
|
||||
|
||||
#include "tr-assert.h"
|
||||
#include "utils.h" /* tr_snprintf() */
|
||||
#include "variant.h"
|
||||
#include "variant-common.h"
|
||||
#include "variant.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
@ -152,8 +154,10 @@ static tr_variant* get_node(std::deque<tr_variant*>& stack, std::optional<tr_qua
|
|||
* easier to read, but was vulnerable to a smash-stacking
|
||||
* attack via maliciously-crafted bencoded data. (#667)
|
||||
*/
|
||||
int tr_variantParseBenc(tr_variant& top, std::string_view benc, char const** setme_end)
|
||||
int tr_variantParseBenc(tr_variant& top, int parse_opts, std::string_view benc, char const** setme_end)
|
||||
{
|
||||
TR_ASSERT((parse_opts & TR_VARIANT_PARSE_BENC) != 0);
|
||||
|
||||
auto stack = std::deque<tr_variant*>{};
|
||||
auto key = std::optional<tr_quark>{};
|
||||
|
||||
|
@ -252,7 +256,14 @@ int tr_variantParseBenc(tr_variant& top, std::string_view benc, char const** set
|
|||
tr_variant* const v = get_node(stack, key, &top, &err);
|
||||
if (v != nullptr)
|
||||
{
|
||||
tr_variantInitStr(v, *sv);
|
||||
if ((parse_opts & TR_VARIANT_PARSE_INPLACE) != 0)
|
||||
{
|
||||
tr_variantInitStrView(v, *sv);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_variantInitStr(v, *sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
struct tr_variant;
|
||||
#include "transmission.h"
|
||||
|
||||
#include "variant.h"
|
||||
|
||||
using VariantWalkFunc = void (*)(tr_variant const* val, void* user_data);
|
||||
|
||||
|
@ -44,6 +46,6 @@ std::optional<int64_t> tr_bencParseInt(std::string_view* benc_inout);
|
|||
/** @brief Private function that's exposed here only for unit tests */
|
||||
std::optional<std::string_view> tr_bencParseStr(std::string_view* benc_inout);
|
||||
|
||||
int tr_variantParseBenc(tr_variant& setme, std::string_view benc, char const** setme_end);
|
||||
int tr_variantParseBenc(tr_variant& setme, int opts, std::string_view benc, char const** setme_end);
|
||||
|
||||
int tr_variantParseJson(tr_variant& setme, std::string_view benc, char const** setme_end);
|
||||
int tr_variantParseJson(tr_variant& setme, int opts, std::string_view benc, char const** setme_end);
|
||||
|
|
|
@ -27,19 +27,21 @@
|
|||
#include "variant.h"
|
||||
#include "variant-common.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
/* arbitrary value... this is much deeper than our code goes */
|
||||
#define MAX_DEPTH 64
|
||||
|
||||
struct json_wrapper_data
|
||||
{
|
||||
int error;
|
||||
bool has_content;
|
||||
tr_variant* top;
|
||||
char const* key;
|
||||
size_t keylen;
|
||||
struct evbuffer* keybuf;
|
||||
struct evbuffer* strbuf;
|
||||
std::string_view key;
|
||||
evbuffer* keybuf;
|
||||
evbuffer* strbuf;
|
||||
int error;
|
||||
std::deque<tr_variant*> stack;
|
||||
tr_variant* top;
|
||||
int parse_opts;
|
||||
|
||||
/* A very common pattern is for a container's children to be similar,
|
||||
* e.g. they may all be objects with the same set of keys. So when
|
||||
|
@ -63,12 +65,10 @@ static tr_variant* get_node(struct jsonsl_st* jsn)
|
|||
{
|
||||
node = tr_variantListAdd(parent);
|
||||
}
|
||||
else if (tr_variantIsDict(parent) && data->key != nullptr)
|
||||
else if (tr_variantIsDict(parent) && !std::empty(data->key))
|
||||
{
|
||||
node = tr_variantDictAdd(parent, tr_quark_new(std::string_view{ data->key, data->keylen }));
|
||||
|
||||
data->key = nullptr;
|
||||
data->keylen = 0;
|
||||
node = tr_variantDictAdd(parent, tr_quark_new(data->key));
|
||||
data->key = ""sv;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -154,7 +154,7 @@ static bool decode_hex_string(char const* in, unsigned int* setme)
|
|||
return true;
|
||||
}
|
||||
|
||||
static char* extract_escaped_string(char const* in, size_t in_len, size_t* len, struct evbuffer* buf)
|
||||
static std::string_view extract_escaped_string(char const* in, size_t in_len, struct evbuffer* buf)
|
||||
{
|
||||
char const* const in_end = in + in_len;
|
||||
|
||||
|
@ -252,13 +252,12 @@ static char* extract_escaped_string(char const* in, size_t in_len, size_t* len,
|
|||
}
|
||||
}
|
||||
|
||||
*len = evbuffer_get_length(buf);
|
||||
return (char*)evbuffer_pullup(buf, -1);
|
||||
return { (char const*)evbuffer_pullup(buf, -1), evbuffer_get_length(buf) };
|
||||
}
|
||||
|
||||
static char const* extract_string(jsonsl_t jsn, struct jsonsl_state_st* state, size_t* len, struct evbuffer* buf)
|
||||
static std::pair<std::string_view, bool> extract_string(jsonsl_t jsn, struct jsonsl_state_st* state, struct evbuffer* buf)
|
||||
{
|
||||
/* figure out where the string is */
|
||||
// figure out where the string is
|
||||
char const* in_begin = jsn->base + state->pos_begin;
|
||||
if (*in_begin == '"')
|
||||
{
|
||||
|
@ -267,15 +266,13 @@ static char const* extract_string(jsonsl_t jsn, struct jsonsl_state_st* state, s
|
|||
|
||||
char const* const in_end = jsn->base + state->pos_cur;
|
||||
size_t const in_len = in_end - in_begin;
|
||||
|
||||
if (memchr(in_begin, '\\', in_len) == nullptr)
|
||||
{
|
||||
/* it's not escaped */
|
||||
*len = in_len;
|
||||
return in_begin;
|
||||
return std::make_pair(std::string_view{ in_begin, in_len }, true);
|
||||
}
|
||||
|
||||
return extract_escaped_string(in_begin, in_len, len, buf);
|
||||
return std::make_pair(extract_escaped_string(in_begin, in_len, buf), false);
|
||||
}
|
||||
|
||||
static void action_callback_POP(
|
||||
|
@ -288,15 +285,22 @@ static void action_callback_POP(
|
|||
|
||||
if (state->type == JSONSL_T_STRING)
|
||||
{
|
||||
auto len = size_t{};
|
||||
char const* str = extract_string(jsn, state, &len, data->strbuf);
|
||||
tr_variantInitStr(get_node(jsn), { str, len });
|
||||
auto const [str, inplace] = extract_string(jsn, state, data->strbuf);
|
||||
if (inplace && ((data->parse_opts & TR_VARIANT_PARSE_INPLACE) != 0))
|
||||
{
|
||||
tr_variantInitStrView(get_node(jsn), str);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_variantInitStr(get_node(jsn), str);
|
||||
}
|
||||
data->has_content = true;
|
||||
}
|
||||
else if (state->type == JSONSL_T_HKEY)
|
||||
{
|
||||
data->has_content = true;
|
||||
data->key = extract_string(jsn, state, &data->keylen, data->keybuf);
|
||||
auto const [key, inplace] = extract_string(jsn, state, data->keybuf);
|
||||
data->key = key;
|
||||
}
|
||||
else if (state->type == JSONSL_T_LIST || state->type == JSONSL_T_OBJECT)
|
||||
{
|
||||
|
@ -336,8 +340,10 @@ static void action_callback_POP(
|
|||
}
|
||||
}
|
||||
|
||||
int tr_variantParseJson(tr_variant& setme, std::string_view benc, char const** setme_end)
|
||||
int tr_variantParseJson(tr_variant& setme, int parse_opts, std::string_view benc, char const** setme_end)
|
||||
{
|
||||
TR_ASSERT((parse_opts & TR_VARIANT_PARSE_JSON) != 0);
|
||||
|
||||
auto data = json_wrapper_data{};
|
||||
|
||||
jsonsl_t jsn = jsonsl_new(MAX_DEPTH);
|
||||
|
@ -349,12 +355,13 @@ int tr_variantParseJson(tr_variant& setme, std::string_view benc, char const** s
|
|||
|
||||
data.error = 0;
|
||||
data.has_content = false;
|
||||
data.key = nullptr;
|
||||
data.top = &setme;
|
||||
data.stack = {};
|
||||
data.key = ""sv;
|
||||
data.keybuf = evbuffer_new();
|
||||
data.strbuf = evbuffer_new();
|
||||
data.parse_opts = parse_opts;
|
||||
data.preallocGuess = {};
|
||||
data.stack = {};
|
||||
data.strbuf = evbuffer_new();
|
||||
data.top = &setme;
|
||||
|
||||
/* parse it */
|
||||
jsonsl_feed(jsn, static_cast<jsonsl_char_t const*>(std::data(benc)), std::size(benc));
|
||||
|
|
|
@ -1292,42 +1292,35 @@ int tr_variantToFile(tr_variant const* v, tr_variant_fmt fmt, char const* filena
|
|||
****
|
||||
***/
|
||||
|
||||
static int tr_variantFromBuf(tr_variant& setme, tr_variant_fmt fmt, std::string_view buf, char const** setme_end)
|
||||
bool tr_variantFromBuf(tr_variant* setme, int opts, std::string_view buf, char const** setme_end, tr_error** error)
|
||||
{
|
||||
/* parse with LC_NUMERIC="C" to ensure a "." decimal separator */
|
||||
struct locale_context locale_ctx;
|
||||
// supported formats: benc, json
|
||||
TR_ASSERT((opts & (TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_JSON)) != 0);
|
||||
|
||||
// parse with LC_NUMERIC="C" to ensure a "." decimal separator
|
||||
auto locale_ctx = locale_context{};
|
||||
use_numeric_locale(&locale_ctx, "C");
|
||||
|
||||
auto err = int{};
|
||||
switch (fmt)
|
||||
{
|
||||
case TR_VARIANT_FMT_JSON:
|
||||
case TR_VARIANT_FMT_JSON_LEAN:
|
||||
err = tr_variantParseJson(setme, buf, setme_end);
|
||||
break;
|
||||
|
||||
default /* TR_VARIANT_FMT_BENC */:
|
||||
err = tr_variantParseBenc(setme, buf, setme_end);
|
||||
break;
|
||||
}
|
||||
auto err = (opts & TR_VARIANT_PARSE_BENC) ? tr_variantParseBenc(*setme, opts, buf, setme_end) :
|
||||
tr_variantParseJson(*setme, opts, buf, setme_end);
|
||||
|
||||
/* restore the previous locale */
|
||||
restore_locale(&locale_ctx);
|
||||
return err;
|
||||
|
||||
if (err)
|
||||
{
|
||||
tr_error_set_literal(error, EILSEQ, "error parsing encoded data");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int tr_variantFromBenc(tr_variant* setme, std::string_view benc, char const** setme_end)
|
||||
bool tr_variantFromFile(tr_variant* setme, tr_variant_parse_opts opts, char const* filename, tr_error** error)
|
||||
{
|
||||
return tr_variantFromBuf(*setme, TR_VARIANT_FMT_BENC, benc, setme_end);
|
||||
}
|
||||
// can't do inplace when this function is allocating & freeing the memory...
|
||||
TR_ASSERT((opts & TR_VARIANT_PARSE_INPLACE) == 0);
|
||||
|
||||
int tr_variantFromJson(tr_variant* setme, std::string_view json)
|
||||
{
|
||||
return tr_variantFromBuf(*setme, TR_VARIANT_FMT_JSON, json, nullptr);
|
||||
}
|
||||
|
||||
bool tr_variantFromFile(tr_variant* setme, tr_variant_fmt fmt, char const* filename, tr_error** error)
|
||||
{
|
||||
auto buf = std::vector<char>{};
|
||||
if (!tr_loadFile(buf, filename, error))
|
||||
{
|
||||
|
@ -1335,12 +1328,5 @@ bool tr_variantFromFile(tr_variant* setme, tr_variant_fmt fmt, char const* filen
|
|||
}
|
||||
|
||||
auto sv = std::string_view{ std::data(buf), std::size(buf) };
|
||||
auto const error_code = tr_variantFromBuf(*setme, fmt, sv, nullptr);
|
||||
if (error_code != 0)
|
||||
{
|
||||
tr_error_set_literal(error, error_code, _("Unable to parse file content"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return tr_variantFromBuf(setme, opts, sv, nullptr, error);
|
||||
}
|
||||
|
|
|
@ -112,12 +112,22 @@ char* tr_variantToStr(tr_variant const* variant, tr_variant_fmt fmt, size_t* len
|
|||
|
||||
struct evbuffer* tr_variantToBuf(tr_variant const* variant, tr_variant_fmt fmt);
|
||||
|
||||
enum tr_variant_parse_opts
|
||||
{
|
||||
TR_VARIANT_PARSE_BENC = (1 << 0),
|
||||
TR_VARIANT_PARSE_JSON = (1 << 1),
|
||||
TR_VARIANT_PARSE_INPLACE = (1 << 2)
|
||||
};
|
||||
|
||||
/* TR_VARIANT_FMT_JSON_LEAN and TR_VARIANT_FMT_JSON are equivalent here. */
|
||||
bool tr_variantFromFile(tr_variant* setme, tr_variant_fmt fmt, char const* filename, struct tr_error** error);
|
||||
bool tr_variantFromFile(tr_variant* setme, tr_variant_parse_opts opts, char const* filename, struct tr_error** error = nullptr);
|
||||
|
||||
int tr_variantFromBenc(tr_variant* setme, std::string_view benc, char const** setme_end = nullptr);
|
||||
|
||||
int tr_variantFromJson(tr_variant* setme, std::string_view json);
|
||||
bool tr_variantFromBuf(
|
||||
tr_variant* setme,
|
||||
int variant_parse_opts,
|
||||
std::string_view buf,
|
||||
char const** setme_end = nullptr,
|
||||
tr_error** error = nullptr);
|
||||
|
||||
constexpr bool tr_variantIsType(tr_variant const* b, int type)
|
||||
{
|
||||
|
|
|
@ -426,7 +426,7 @@ Prefs::~Prefs()
|
|||
tr_variant file_settings;
|
||||
QFile const file(QDir(config_dir_).absoluteFilePath(QStringLiteral("settings.json")));
|
||||
|
||||
if (!tr_variantFromFile(&file_settings, TR_VARIANT_FMT_JSON, file.fileName().toUtf8().constData(), nullptr))
|
||||
if (!tr_variantFromFile(&file_settings, TR_VARIANT_PARSE_JSON, file.fileName().toUtf8().constData(), nullptr))
|
||||
{
|
||||
tr_variantInitDict(&file_settings, PREFS_COUNT);
|
||||
}
|
||||
|
|
|
@ -277,7 +277,7 @@ void RpcClient::networkRequestFinished(QNetworkReply* reply)
|
|||
|
||||
TrVariantPtr json = createVariant();
|
||||
RpcResponse result;
|
||||
if (tr_variantFromJson(json.get(), json_sv) == 0)
|
||||
if (tr_variantFromBuf(json.get(), TR_VARIANT_PARSE_JSON, json_sv))
|
||||
{
|
||||
result = parseResponseData(*json);
|
||||
}
|
||||
|
|
|
@ -48,8 +48,7 @@ TEST_P(JSONTest, testElements)
|
|||
};
|
||||
|
||||
tr_variant top;
|
||||
int err = tr_variantFromJson(&top, in);
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
EXPECT_TRUE(tr_variantIsDict(&top));
|
||||
|
||||
auto sv = std::string_view{};
|
||||
|
@ -78,43 +77,29 @@ TEST_P(JSONTest, testElements)
|
|||
EXPECT_TRUE(tr_variantDictFindStrView(&top, tr_quark_new("null"sv), &sv));
|
||||
EXPECT_EQ(""sv, sv);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
|
||||
TEST_P(JSONTest, testUtf8)
|
||||
{
|
||||
auto in = std::string{ "{ \"key\": \"Letöltések\" }" };
|
||||
auto in = "{ \"key\": \"Letöltések\" }"sv;
|
||||
tr_variant top;
|
||||
auto sv = std::string_view{};
|
||||
char* json;
|
||||
int err;
|
||||
tr_quark const key = tr_quark_new("key"sv);
|
||||
|
||||
err = tr_variantFromJson(&top, in);
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
EXPECT_TRUE(tr_variantIsDict(&top));
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&top, key, &sv));
|
||||
EXPECT_EQ("Letöltések"sv, sv);
|
||||
tr_variantFree(&top);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
|
||||
in = std::string{ R"({ "key": "\u005C" })" };
|
||||
err = tr_variantFromJson(&top, in);
|
||||
EXPECT_EQ(0, err);
|
||||
in = R"({ "key": "\u005C" })"sv;
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
EXPECT_TRUE(tr_variantIsDict(&top));
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&top, key, &sv));
|
||||
EXPECT_EQ("\\"sv, sv);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
tr_variantFree(&top);
|
||||
|
||||
/**
|
||||
* 1. Feed it JSON-escaped nonascii to the JSON decoder.
|
||||
|
@ -124,32 +109,22 @@ TEST_P(JSONTest, testUtf8)
|
|||
* 5. Dogfood that result back into the parser.
|
||||
* 6. Confirm that the result is UTF-8.
|
||||
*/
|
||||
in = std::string{ R"({ "key": "Let\u00f6lt\u00e9sek" })" };
|
||||
err = tr_variantFromJson(&top, in);
|
||||
EXPECT_EQ(0, err);
|
||||
in = R"({ "key": "Let\u00f6lt\u00e9sek" })"sv;
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
EXPECT_TRUE(tr_variantIsDict(&top));
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&top, key, &sv));
|
||||
EXPECT_EQ("Letöltések"sv, sv);
|
||||
json = tr_variantToStr(&top, TR_VARIANT_FMT_JSON, nullptr);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
tr_variantFree(&top);
|
||||
|
||||
EXPECT_NE(nullptr, json);
|
||||
EXPECT_NE(nullptr, strstr(json, "\\u00f6"));
|
||||
EXPECT_NE(nullptr, strstr(json, "\\u00e9"));
|
||||
err = tr_variantFromJson(&top, json);
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, json));
|
||||
EXPECT_TRUE(tr_variantIsDict(&top));
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&top, key, &sv));
|
||||
EXPECT_EQ("Letöltések"sv, sv);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
tr_variantFree(&top);
|
||||
|
||||
tr_free(json);
|
||||
}
|
||||
|
@ -172,11 +147,10 @@ TEST_P(JSONTest, test1)
|
|||
};
|
||||
|
||||
tr_variant top;
|
||||
auto const err = tr_variantFromJson(&top, in);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
|
||||
auto sv = std::string_view{};
|
||||
int64_t i;
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantIsDict(&top));
|
||||
auto* headers = tr_variantDictFind(&top, tr_quark_new("headers"sv));
|
||||
EXPECT_NE(nullptr, headers);
|
||||
|
@ -210,25 +184,21 @@ TEST_P(JSONTest, test2)
|
|||
auto const in = std::string{ " " };
|
||||
|
||||
top.type = 0;
|
||||
int err = tr_variantFromJson(&top, in);
|
||||
|
||||
EXPECT_NE(0, err);
|
||||
EXPECT_FALSE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
EXPECT_FALSE(tr_variantIsDict(&top));
|
||||
}
|
||||
|
||||
TEST_P(JSONTest, test3)
|
||||
{
|
||||
auto const in = std::string{
|
||||
"{ \"error\": 2,"
|
||||
" \"errorString\": \"torrent not registered with this tracker 6UHsVW'*C\","
|
||||
" \"eta\": 262792,"
|
||||
" \"id\": 25,"
|
||||
" \"leftUntilDone\": 2275655680 }"
|
||||
};
|
||||
auto const
|
||||
in = "{ \"error\": 2,"
|
||||
" \"errorString\": \"torrent not registered with this tracker 6UHsVW'*C\","
|
||||
" \"eta\": 262792,"
|
||||
" \"id\": 25,"
|
||||
" \"leftUntilDone\": 2275655680 }"sv;
|
||||
|
||||
tr_variant top;
|
||||
auto const err = tr_variantFromJson(&top, in);
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
|
||||
auto sv = std::string_view{};
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&top, TR_KEY_errorString, &sv));
|
||||
|
@ -241,8 +211,7 @@ TEST_P(JSONTest, unescape)
|
|||
{
|
||||
tr_variant top;
|
||||
auto const in = std::string{ R"({ "string-1": "\/usr\/lib" })" };
|
||||
int const err = tr_variantFromJson(&top, in);
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, in));
|
||||
|
||||
auto sv = std::string_view{};
|
||||
EXPECT_TRUE(tr_variantDictFindStrView(&top, tr_quark_new("string-1"sv), &sv));
|
||||
|
|
|
@ -87,7 +87,7 @@ TEST_F(RpcTest, sessionGet)
|
|||
|
||||
tr_variant request;
|
||||
tr_variantInitDict(&request, 1);
|
||||
tr_variantDictAddStr(&request, TR_KEY_method, "session-get");
|
||||
tr_variantDictAddStrView(&request, TR_KEY_method, "session-get");
|
||||
tr_variant response;
|
||||
tr_rpc_request_exec_json(session_, &request, rpc_response_func, &response);
|
||||
tr_variantFree(&request);
|
||||
|
|
|
@ -211,16 +211,16 @@ TEST_F(VariantTest, parse)
|
|||
auto i = int64_t{};
|
||||
auto val = tr_variant{};
|
||||
char const* end;
|
||||
auto err = tr_variantFromBenc(&val, benc, &end);
|
||||
EXPECT_EQ(0, err);
|
||||
auto ok = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, benc, &end);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_TRUE(tr_variantGetInt(&val, &i));
|
||||
EXPECT_EQ(int64_t(64), i);
|
||||
EXPECT_EQ(std::data(benc) + std::size(benc), end);
|
||||
tr_variantFree(&val);
|
||||
|
||||
benc = "li64ei32ei16ee"sv;
|
||||
err = tr_variantFromBenc(&val, benc, &end);
|
||||
EXPECT_EQ(0, err);
|
||||
ok = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, benc, &end);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_EQ(std::data(benc) + std::size(benc), end);
|
||||
EXPECT_EQ(size_t{ 3 }, tr_variantListSize(&val));
|
||||
EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&val, 0), &i));
|
||||
|
@ -240,13 +240,12 @@ TEST_F(VariantTest, parse)
|
|||
end = nullptr;
|
||||
|
||||
benc = "lllee"sv;
|
||||
err = tr_variantFromBenc(&val, benc, &end);
|
||||
EXPECT_NE(0, err);
|
||||
ok = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, benc, &end);
|
||||
EXPECT_FALSE(ok);
|
||||
EXPECT_EQ(nullptr, end);
|
||||
|
||||
benc = "le"sv;
|
||||
err = tr_variantFromBenc(&val, benc, &end);
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_TRUE(tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, benc, &end));
|
||||
EXPECT_EQ(std::data(benc) + std::size(benc), end);
|
||||
|
||||
saved = tr_variantToStr(&val, TR_VARIANT_FMT_BENC, &len);
|
||||
|
@ -280,14 +279,10 @@ TEST_F(VariantTest, bencParseAndReencode)
|
|||
{
|
||||
tr_variant val;
|
||||
char const* end = nullptr;
|
||||
auto const err = tr_variantFromBenc(&val, test.benc, &end);
|
||||
if (!test.is_good)
|
||||
auto const is_good = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, test.benc, &end);
|
||||
EXPECT_EQ(test.is_good, is_good);
|
||||
if (is_good)
|
||||
{
|
||||
EXPECT_NE(0, err);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(0, err);
|
||||
EXPECT_EQ(test.benc.data() + test.benc.size(), end);
|
||||
auto saved_len = size_t{};
|
||||
auto* saved = tr_variantToStr(&val, TR_VARIANT_FMT_BENC, &saved_len);
|
||||
|
@ -305,8 +300,8 @@ TEST_F(VariantTest, bencSortWhenSerializing)
|
|||
|
||||
tr_variant val;
|
||||
char const* end;
|
||||
auto const err = tr_variantFromBenc(&val, In, &end);
|
||||
EXPECT_EQ(0, err);
|
||||
auto const ok = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, In, &end);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_EQ(std::data(In) + std::size(In), end);
|
||||
|
||||
auto len = size_t{};
|
||||
|
@ -325,8 +320,8 @@ TEST_F(VariantTest, bencMalformedTooManyEndings)
|
|||
|
||||
tr_variant val;
|
||||
char const* end;
|
||||
auto const err = tr_variantFromBenc(&val, In, &end);
|
||||
EXPECT_EQ(0, err);
|
||||
auto const ok = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, In, &end);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_EQ(std::data(In) + std::size(ExpectedOut), end);
|
||||
|
||||
auto len = size_t{};
|
||||
|
@ -342,14 +337,14 @@ TEST_F(VariantTest, bencMalformedNoEnding)
|
|||
{
|
||||
auto constexpr In = "l1:a1:b1:c"sv;
|
||||
tr_variant val;
|
||||
EXPECT_EQ(EILSEQ, tr_variantFromBenc(&val, In));
|
||||
EXPECT_FALSE(tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, In));
|
||||
}
|
||||
|
||||
TEST_F(VariantTest, bencMalformedIncompleteString)
|
||||
{
|
||||
auto constexpr In = "1:"sv;
|
||||
tr_variant val;
|
||||
EXPECT_EQ(EILSEQ, tr_variantFromBenc(&val, In));
|
||||
EXPECT_FALSE(tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, In));
|
||||
}
|
||||
|
||||
TEST_F(VariantTest, bencToJson)
|
||||
|
@ -372,7 +367,7 @@ TEST_F(VariantTest, bencToJson)
|
|||
for (auto const& test : Tests)
|
||||
{
|
||||
tr_variant top;
|
||||
tr_variantFromBenc(&top, test.benc);
|
||||
tr_variantFromBuf(&top, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, test.benc);
|
||||
|
||||
auto len = size_t{};
|
||||
auto* str = tr_variantToStr(&top, TR_VARIANT_FMT_JSON_LEAN, &len);
|
||||
|
@ -399,9 +394,9 @@ TEST_F(VariantTest, merge)
|
|||
tr_variantDictAddInt(&dest, i1, 1);
|
||||
tr_variantDictAddInt(&dest, i2, 2);
|
||||
tr_variantDictAddInt(&dest, i4, -35); /* remains untouched */
|
||||
tr_variantDictAddStr(&dest, s5, "abc");
|
||||
tr_variantDictAddStr(&dest, s6, "def");
|
||||
tr_variantDictAddStr(&dest, s7, "127.0.0.1"); /* remains untouched */
|
||||
tr_variantDictAddStrView(&dest, s5, "abc");
|
||||
tr_variantDictAddStrView(&dest, s6, "def");
|
||||
tr_variantDictAddStrView(&dest, s7, "127.0.0.1"); /* remains untouched */
|
||||
|
||||
/* new dictionary, will overwrite items in dest */
|
||||
tr_variant src;
|
||||
|
@ -409,9 +404,9 @@ TEST_F(VariantTest, merge)
|
|||
tr_variantDictAddInt(&src, i1, 1); /* same value */
|
||||
tr_variantDictAddInt(&src, i2, 4); /* new value */
|
||||
tr_variantDictAddInt(&src, i3, 3); /* new key:value */
|
||||
tr_variantDictAddStr(&src, s5, "abc"); /* same value */
|
||||
tr_variantDictAddStr(&src, s6, "xyz"); /* new value */
|
||||
tr_variantDictAddStr(&src, s8, "ghi"); /* new key:value */
|
||||
tr_variantDictAddStrView(&src, s5, "abc"); /* same value */
|
||||
tr_variantDictAddStrView(&src, s6, "xyz"); /* new value */
|
||||
tr_variantDictAddStrView(&src, s8, "ghi"); /* new key:value */
|
||||
|
||||
tr_variantMergeDicts(&dest, /*const*/ &src);
|
||||
|
||||
|
@ -447,8 +442,8 @@ TEST_F(VariantTest, stackSmash)
|
|||
// confirm that it parses
|
||||
char const* end;
|
||||
tr_variant val;
|
||||
auto err = tr_variantFromBenc(&val, in, &end);
|
||||
EXPECT_EQ(0, err);
|
||||
auto ok = tr_variantFromBuf(&val, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, in, &end);
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_EQ(in.data() + in.size(), end);
|
||||
|
||||
// confirm that we can serialize it back again
|
||||
|
|
|
@ -342,7 +342,7 @@ int tr_main(int argc, char* argv[])
|
|||
|
||||
printf("%s\n", filename);
|
||||
|
||||
if (!tr_variantFromFile(&top, TR_VARIANT_FMT_BENC, filename, &error))
|
||||
if (!tr_variantFromFile(&top, TR_VARIANT_PARSE_BENC, filename, &error))
|
||||
{
|
||||
printf("\tError reading file: %s\n", error->message);
|
||||
tr_error_free(error);
|
||||
|
|
|
@ -590,7 +590,7 @@ static void addIdArg(tr_variant* args, char const* id_str, char const* fallback)
|
|||
|
||||
if (tr_strcmp0(id_str, "active") == 0)
|
||||
{
|
||||
tr_variantDictAddStr(args, TR_KEY_ids, "recently-active"sv);
|
||||
tr_variantDictAddStrView(args, TR_KEY_ids, "recently-active"sv);
|
||||
}
|
||||
else if (strcmp(id_str, "all") != 0)
|
||||
{
|
||||
|
@ -2039,7 +2039,7 @@ static int processResponse(char const* rpcurl, std::string_view response)
|
|||
TR_PRIsv_ARG(response));
|
||||
}
|
||||
|
||||
if (tr_variantFromJson(&top, response) != 0)
|
||||
if (!tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, response))
|
||||
{
|
||||
tr_logAddNamedError(MY_NAME, "Unable to parse response \"%" TR_PRIsv "\"", TR_PRIsv_ARG(response));
|
||||
status |= EXIT_FAILURE;
|
||||
|
@ -2281,7 +2281,7 @@ static tr_variant* ensure_sset(tr_variant** sset)
|
|||
{
|
||||
*sset = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(*sset, 3);
|
||||
tr_variantDictAddStr(*sset, TR_KEY_method, "session-set"sv);
|
||||
tr_variantDictAddStrView(*sset, TR_KEY_method, "session-set"sv);
|
||||
args = tr_variantDictAddDict(*sset, ARGUMENTS, 0);
|
||||
}
|
||||
|
||||
|
@ -2300,7 +2300,7 @@ static tr_variant* ensure_tset(tr_variant** tset)
|
|||
{
|
||||
*tset = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(*tset, 3);
|
||||
tr_variantDictAddStr(*tset, TR_KEY_method, "torrent-set"sv);
|
||||
tr_variantDictAddStrView(*tset, TR_KEY_method, "torrent-set"sv);
|
||||
args = tr_variantDictAddDict(*tset, ARGUMENTS, 1);
|
||||
}
|
||||
|
||||
|
@ -2345,7 +2345,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
|
||||
tadd = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(tadd, 3);
|
||||
tr_variantDictAddStr(tadd, TR_KEY_method, "torrent-add"sv);
|
||||
tr_variantDictAddStrView(tadd, TR_KEY_method, "torrent-add"sv);
|
||||
tr_variantDictAddInt(tadd, TR_KEY_tag, TAG_TORRENT_ADD);
|
||||
tr_variantDictAddDict(tadd, ARGUMENTS, 0);
|
||||
break;
|
||||
|
@ -2434,7 +2434,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
tr_variant* args;
|
||||
tr_variant* fields;
|
||||
tr_variantInitDict(top, 3);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-get"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-get"sv);
|
||||
args = tr_variantDictAddDict(top, ARGUMENTS, 0);
|
||||
fields = tr_variantDictAddList(args, TR_KEY_fields, 0);
|
||||
|
||||
|
@ -2481,20 +2481,20 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
|
||||
case 941:
|
||||
tr_variantDictAddInt(top, TR_KEY_tag, TAG_PEERS);
|
||||
tr_variantListAddStr(fields, "peers"sv);
|
||||
tr_variantListAddStrView(fields, "peers"sv);
|
||||
addIdArg(args, id, nullptr);
|
||||
break;
|
||||
|
||||
case 942:
|
||||
tr_variantDictAddInt(top, TR_KEY_tag, TAG_PIECES);
|
||||
tr_variantListAddStr(fields, "pieces"sv);
|
||||
tr_variantListAddStr(fields, "pieceCount"sv);
|
||||
tr_variantListAddStrView(fields, "pieces"sv);
|
||||
tr_variantListAddStrView(fields, "pieceCount"sv);
|
||||
addIdArg(args, id, nullptr);
|
||||
break;
|
||||
|
||||
case 943:
|
||||
tr_variantDictAddInt(top, TR_KEY_tag, TAG_TRACKERS);
|
||||
tr_variantListAddStr(fields, "trackerStats"sv);
|
||||
tr_variantListAddStrView(fields, "trackerStats"sv);
|
||||
addIdArg(args, id, nullptr);
|
||||
break;
|
||||
|
||||
|
@ -2569,15 +2569,15 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
break;
|
||||
|
||||
case 910:
|
||||
tr_variantDictAddStr(args, TR_KEY_encryption, "required"sv);
|
||||
tr_variantDictAddStrView(args, TR_KEY_encryption, "required"sv);
|
||||
break;
|
||||
|
||||
case 911:
|
||||
tr_variantDictAddStr(args, TR_KEY_encryption, "preferred"sv);
|
||||
tr_variantDictAddStrView(args, TR_KEY_encryption, "preferred"sv);
|
||||
break;
|
||||
|
||||
case 912:
|
||||
tr_variantDictAddStr(args, TR_KEY_encryption, "tolerated"sv);
|
||||
tr_variantDictAddStrView(args, TR_KEY_encryption, "tolerated"sv);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
|
@ -2851,7 +2851,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
tr_variant* args;
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-set-location"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-set-location"sv);
|
||||
args = tr_variantDictAddDict(top, ARGUMENTS, 3);
|
||||
tr_variantDictAddStr(args, TR_KEY_location, optarg);
|
||||
tr_variantDictAddBool(args, TR_KEY_move, false);
|
||||
|
@ -2868,7 +2868,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "session-get"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "session-get"sv);
|
||||
tr_variantDictAddInt(top, TR_KEY_tag, TAG_SESSION);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
|
@ -2884,7 +2884,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-start"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-start"sv);
|
||||
addIdArg(tr_variantDictAddDict(top, ARGUMENTS, 1), id, nullptr);
|
||||
status |= flush(rpcurl, &top);
|
||||
}
|
||||
|
@ -2902,7 +2902,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-stop"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-stop"sv);
|
||||
addIdArg(tr_variantDictAddDict(top, ARGUMENTS, 1), id, nullptr);
|
||||
status |= flush(rpcurl, &top);
|
||||
}
|
||||
|
@ -2921,7 +2921,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 1);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "session-close"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "session-close"sv);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
}
|
||||
|
@ -2930,7 +2930,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 1);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "blocklist-update"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "blocklist-update"sv);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
}
|
||||
|
@ -2939,7 +2939,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "session-stats"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "session-stats"sv);
|
||||
tr_variantDictAddInt(top, TR_KEY_tag, TAG_STATS);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
|
@ -2949,7 +2949,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
{
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "port-test"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "port-test"sv);
|
||||
tr_variantDictAddInt(top, TR_KEY_tag, TAG_PORTTEST);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
|
@ -2967,7 +2967,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
|
||||
top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-reannounce"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-reannounce"sv);
|
||||
addIdArg(tr_variantDictAddDict(top, ARGUMENTS, 1), id, nullptr);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
|
@ -2985,7 +2985,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
|
||||
top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-verify"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-verify"sv);
|
||||
addIdArg(tr_variantDictAddDict(top, ARGUMENTS, 1), id, nullptr);
|
||||
status |= flush(rpcurl, &top);
|
||||
break;
|
||||
|
@ -2997,7 +2997,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
tr_variant* args;
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-remove"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-remove"sv);
|
||||
args = tr_variantDictAddDict(top, ARGUMENTS, 2);
|
||||
tr_variantDictAddBool(args, TR_KEY_delete_local_data, c == 840);
|
||||
addIdArg(args, id, nullptr);
|
||||
|
@ -3010,7 +3010,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
|
|||
tr_variant* args;
|
||||
tr_variant* top = tr_new0(tr_variant, 1);
|
||||
tr_variantInitDict(top, 2);
|
||||
tr_variantDictAddStr(top, TR_KEY_method, "torrent-set-location"sv);
|
||||
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-set-location"sv);
|
||||
args = tr_variantDictAddDict(top, ARGUMENTS, 3);
|
||||
tr_variantDictAddStr(args, TR_KEY_location, optarg);
|
||||
tr_variantDictAddBool(args, TR_KEY_move, true);
|
||||
|
|
|
@ -260,8 +260,8 @@ static void doScrape(tr_info const* inf)
|
|||
tr_variant* files;
|
||||
bool matched = false;
|
||||
char const* begin = (char const*)evbuffer_pullup(buf, -1);
|
||||
|
||||
if (tr_variantFromBenc(&top, { begin, evbuffer_get_length(buf) }) == 0)
|
||||
auto sv = std::string_view{ begin, evbuffer_get_length(buf) };
|
||||
if (tr_variantFromBuf(&top, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, sv))
|
||||
{
|
||||
if (tr_variantDictFindDict(&top, TR_KEY_files, &files))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue