refactor: use std::vector and std::array in quark.cc (#1861)

* refactor: use std::vector and std::array in quark.cc
This commit is contained in:
Charles Kerr 2021-09-30 07:01:04 -05:00 committed by GitHub
parent e47762c7ca
commit 5395e2e545
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 418 additions and 489 deletions

View File

@ -7,440 +7,417 @@
*/
#include <algorithm>
#include <cstdlib> /* bsearch() */
#include <cstring> /* memcmp() */
#include <array>
#include <cstring> // strlen()
#include <iterator>
#include <string_view>
#include <vector>
#include "transmission.h"
#include "ptrarray.h"
#include "quark.h"
#include "tr-assert.h"
#include "utils.h" /* tr_memdup(), tr_strndup() */
#include "utils.h" // tr_strndup()
struct tr_key_struct
namespace
{
char const* str;
size_t len;
};
#define Q(name) \
{ \
"" name "", sizeof("" name "") - 1, \
}
auto constexpr my_static = std::array<std::string_view, 388>{ "",
"activeTorrentCount",
"activity-date",
"activityDate",
"added",
"added-date",
"added.f",
"added6",
"added6.f",
"addedDate",
"address",
"alt-speed-down",
"alt-speed-enabled",
"alt-speed-time-begin",
"alt-speed-time-day",
"alt-speed-time-enabled",
"alt-speed-time-end",
"alt-speed-up",
"announce",
"announce-list",
"announceState",
"anti-brute-force-enabled",
"anti-brute-force-threshold",
"arguments",
"bandwidth-priority",
"bandwidthPriority",
"bind-address-ipv4",
"bind-address-ipv6",
"bitfield",
"blocklist-date",
"blocklist-enabled",
"blocklist-size",
"blocklist-updates-enabled",
"blocklist-url",
"blocks",
"bytesCompleted",
"cache-size-mb",
"clientIsChoked",
"clientIsInterested",
"clientName",
"comment",
"comment_utf_8",
"compact-view",
"complete",
"config-dir",
"cookies",
"corrupt",
"corruptEver",
"created by",
"created by.utf-8",
"creation date",
"creator",
"cumulative-stats",
"current-stats",
"date",
"dateCreated",
"delete-local-data",
"desiredAvailable",
"destination",
"details-window-height",
"details-window-width",
"dht-enabled",
"display-name",
"dnd",
"done-date",
"doneDate",
"download-dir",
"download-dir-free-space",
"download-queue-enabled",
"download-queue-size",
"downloadCount",
"downloadDir",
"downloadLimit",
"downloadLimited",
"downloadSpeed",
"downloaded",
"downloaded-bytes",
"downloadedBytes",
"downloadedEver",
"downloaders",
"downloading-time-seconds",
"dropped",
"dropped6",
"e",
"editDate",
"encoding",
"encryption",
"error",
"errorString",
"eta",
"etaIdle",
"failure reason",
"fields",
"file-count",
"fileStats",
"filename",
"files",
"files-added",
"files-unwanted",
"files-wanted",
"filesAdded",
"filter-mode",
"filter-text",
"filter-trackers",
"flagStr",
"flags",
"format",
"fromCache",
"fromDht",
"fromIncoming",
"fromLpd",
"fromLtep",
"fromPex",
"fromTracker",
"hasAnnounced",
"hasScraped",
"hashString",
"have",
"haveUnchecked",
"haveValid",
"honorsSessionLimits",
"host",
"id",
"idle-limit",
"idle-mode",
"idle-seeding-limit",
"idle-seeding-limit-enabled",
"ids",
"incomplete",
"incomplete-dir",
"incomplete-dir-enabled",
"info",
"info_hash",
"inhibit-desktop-hibernation",
"interval",
"ip",
"ipv4",
"ipv6",
"isBackup",
"isDownloadingFrom",
"isEncrypted",
"isFinished",
"isIncoming",
"isPrivate",
"isStalled",
"isUTP",
"isUploadingTo",
"labels",
"lastAnnouncePeerCount",
"lastAnnounceResult",
"lastAnnounceStartTime",
"lastAnnounceSucceeded",
"lastAnnounceTime",
"lastAnnounceTimedOut",
"lastScrapeResult",
"lastScrapeStartTime",
"lastScrapeSucceeded",
"lastScrapeTime",
"lastScrapeTimedOut",
"leecherCount",
"leftUntilDone",
"length",
"location",
"lpd-enabled",
"m",
"magnet-info",
"magnetLink",
"main-window-height",
"main-window-is-maximized",
"main-window-layout-order",
"main-window-width",
"main-window-x",
"main-window-y",
"manualAnnounceTime",
"max-peers",
"maxConnectedPeers",
"memory-bytes",
"memory-units",
"message-level",
"metadataPercentComplete",
"metadata_size",
"metainfo",
"method",
"min interval",
"min_request_interval",
"move",
"msg_type",
"mtimes",
"name",
"name.utf-8",
"nextAnnounceTime",
"nextScrapeTime",
"nodes",
"nodes6",
"open-dialog-dir",
"p",
"path",
"path.utf-8",
"paused",
"pausedTorrentCount",
"peer-congestion-algorithm",
"peer-id-ttl-hours",
"peer-limit",
"peer-limit-global",
"peer-limit-per-torrent",
"peer-port",
"peer-port-random-high",
"peer-port-random-low",
"peer-port-random-on-start",
"peer-socket-tos",
"peerIsChoked",
"peerIsInterested",
"peers",
"peers2",
"peers2-6",
"peers6",
"peersConnected",
"peersFrom",
"peersGettingFromUs",
"peersSendingToUs",
"percentDone",
"pex-enabled",
"piece",
"piece length",
"pieceCount",
"pieceSize",
"pieces",
"play-download-complete-sound",
"port",
"port-forwarding-enabled",
"port-is-open",
"preallocation",
"prefetch-enabled",
"primary-mime-type",
"priorities",
"priority",
"priority-high",
"priority-low",
"priority-normal",
"private",
"progress",
"prompt-before-exit",
"queue-move-bottom",
"queue-move-down",
"queue-move-top",
"queue-move-up",
"queue-stalled-enabled",
"queue-stalled-minutes",
"queuePosition",
"rateDownload",
"rateToClient",
"rateToPeer",
"rateUpload",
"ratio-limit",
"ratio-limit-enabled",
"ratio-mode",
"recent-download-dir-1",
"recent-download-dir-2",
"recent-download-dir-3",
"recent-download-dir-4",
"recheckProgress",
"remote-session-enabled",
"remote-session-host",
"remote-session-password",
"remote-session-port",
"remote-session-requres-authentication",
"remote-session-username",
"removed",
"rename-partial-files",
"reqq",
"result",
"rpc-authentication-required",
"rpc-bind-address",
"rpc-enabled",
"rpc-host-whitelist",
"rpc-host-whitelist-enabled",
"rpc-password",
"rpc-port",
"rpc-url",
"rpc-username",
"rpc-version",
"rpc-version-minimum",
"rpc-whitelist",
"rpc-whitelist-enabled",
"scrape",
"scrape-paused-torrents-enabled",
"scrapeState",
"script-torrent-done-enabled",
"script-torrent-done-filename",
"seconds-active",
"secondsActive",
"secondsDownloading",
"secondsSeeding",
"seed-queue-enabled",
"seed-queue-size",
"seedIdleLimit",
"seedIdleMode",
"seedRatioLimit",
"seedRatioLimited",
"seedRatioMode",
"seederCount",
"seeding-time-seconds",
"session-count",
"session-id",
"sessionCount",
"show-backup-trackers",
"show-extra-peer-details",
"show-filterbar",
"show-notification-area-icon",
"show-options-window",
"show-statusbar",
"show-toolbar",
"show-tracker-scrapes",
"size-bytes",
"size-units",
"sizeWhenDone",
"sort-mode",
"sort-reversed",
"speed",
"speed-Bps",
"speed-bytes",
"speed-limit-down",
"speed-limit-down-enabled",
"speed-limit-up",
"speed-limit-up-enabled",
"speed-units",
"start-added-torrents",
"start-minimized",
"startDate",
"status",
"statusbar-stats",
"tag",
"tier",
"time-checked",
"torrent-added",
"torrent-added-notification-command",
"torrent-added-notification-enabled",
"torrent-complete-notification-command",
"torrent-complete-notification-enabled",
"torrent-complete-sound-command",
"torrent-complete-sound-enabled",
"torrent-duplicate",
"torrent-get",
"torrent-set",
"torrent-set-location",
"torrentCount",
"torrentFile",
"torrents",
"totalSize",
"total_size",
"tracker id",
"trackerAdd",
"trackerRemove",
"trackerReplace",
"trackerStats",
"trackers",
"trash-can-enabled",
"trash-original-torrent-files",
"umask",
"units",
"upload-slots-per-torrent",
"uploadLimit",
"uploadLimited",
"uploadRatio",
"uploadSpeed",
"upload_only",
"uploaded",
"uploaded-bytes",
"uploadedBytes",
"uploadedEver",
"url-list",
"use-global-speed-limit",
"use-speed-limit",
"user-has-given-informed-consent",
"ut_comment",
"ut_holepunch",
"ut_metadata",
"ut_pex",
"ut_recommend",
"utp-enabled",
"v",
"version",
"wanted",
"warning message",
"watch-dir",
"watch-dir-enabled",
"webseeds",
"webseedsSendingToUs" };
static struct tr_key_struct constexpr my_static[] = {
Q(""),
Q("activeTorrentCount"),
Q("activity-date"),
Q("activityDate"),
Q("added"),
Q("added-date"),
Q("added.f"),
Q("added6"),
Q("added6.f"),
Q("addedDate"),
Q("address"),
Q("alt-speed-down"),
Q("alt-speed-enabled"),
Q("alt-speed-time-begin"),
Q("alt-speed-time-day"),
Q("alt-speed-time-enabled"),
Q("alt-speed-time-end"),
Q("alt-speed-up"),
Q("announce"),
Q("announce-list"),
Q("announceState"),
Q("anti-brute-force-enabled"),
Q("anti-brute-force-threshold"),
Q("arguments"),
Q("bandwidth-priority"),
Q("bandwidthPriority"),
Q("bind-address-ipv4"),
Q("bind-address-ipv6"),
Q("bitfield"),
Q("blocklist-date"),
Q("blocklist-enabled"),
Q("blocklist-size"),
Q("blocklist-updates-enabled"),
Q("blocklist-url"),
Q("blocks"),
Q("bytesCompleted"),
Q("cache-size-mb"),
Q("clientIsChoked"),
Q("clientIsInterested"),
Q("clientName"),
Q("comment"),
Q("comment_utf_8"),
Q("compact-view"),
Q("complete"),
Q("config-dir"),
Q("cookies"),
Q("corrupt"),
Q("corruptEver"),
Q("created by"),
Q("created by.utf-8"),
Q("creation date"),
Q("creator"),
Q("cumulative-stats"),
Q("current-stats"),
Q("date"),
Q("dateCreated"),
Q("delete-local-data"),
Q("desiredAvailable"),
Q("destination"),
Q("details-window-height"),
Q("details-window-width"),
Q("dht-enabled"),
Q("display-name"),
Q("dnd"),
Q("done-date"),
Q("doneDate"),
Q("download-dir"),
Q("download-dir-free-space"),
Q("download-queue-enabled"),
Q("download-queue-size"),
Q("downloadCount"),
Q("downloadDir"),
Q("downloadLimit"),
Q("downloadLimited"),
Q("downloadSpeed"),
Q("downloaded"),
Q("downloaded-bytes"),
Q("downloadedBytes"),
Q("downloadedEver"),
Q("downloaders"),
Q("downloading-time-seconds"),
Q("dropped"),
Q("dropped6"),
Q("e"),
Q("editDate"),
Q("encoding"),
Q("encryption"),
Q("error"),
Q("errorString"),
Q("eta"),
Q("etaIdle"),
Q("failure reason"),
Q("fields"),
Q("file-count"),
Q("fileStats"),
Q("filename"),
Q("files"),
Q("files-added"),
Q("files-unwanted"),
Q("files-wanted"),
Q("filesAdded"),
Q("filter-mode"),
Q("filter-text"),
Q("filter-trackers"),
Q("flagStr"),
Q("flags"),
Q("format"),
Q("fromCache"),
Q("fromDht"),
Q("fromIncoming"),
Q("fromLpd"),
Q("fromLtep"),
Q("fromPex"),
Q("fromTracker"),
Q("hasAnnounced"),
Q("hasScraped"),
Q("hashString"),
Q("have"),
Q("haveUnchecked"),
Q("haveValid"),
Q("honorsSessionLimits"),
Q("host"),
Q("id"),
Q("idle-limit"),
Q("idle-mode"),
Q("idle-seeding-limit"),
Q("idle-seeding-limit-enabled"),
Q("ids"),
Q("incomplete"),
Q("incomplete-dir"),
Q("incomplete-dir-enabled"),
Q("info"),
Q("info_hash"),
Q("inhibit-desktop-hibernation"),
Q("interval"),
Q("ip"),
Q("ipv4"),
Q("ipv6"),
Q("isBackup"),
Q("isDownloadingFrom"),
Q("isEncrypted"),
Q("isFinished"),
Q("isIncoming"),
Q("isPrivate"),
Q("isStalled"),
Q("isUTP"),
Q("isUploadingTo"),
Q("labels"),
Q("lastAnnouncePeerCount"),
Q("lastAnnounceResult"),
Q("lastAnnounceStartTime"),
Q("lastAnnounceSucceeded"),
Q("lastAnnounceTime"),
Q("lastAnnounceTimedOut"),
Q("lastScrapeResult"),
Q("lastScrapeStartTime"),
Q("lastScrapeSucceeded"),
Q("lastScrapeTime"),
Q("lastScrapeTimedOut"),
Q("leecherCount"),
Q("leftUntilDone"),
Q("length"),
Q("location"),
Q("lpd-enabled"),
Q("m"),
Q("magnet-info"),
Q("magnetLink"),
Q("main-window-height"),
Q("main-window-is-maximized"),
Q("main-window-layout-order"),
Q("main-window-width"),
Q("main-window-x"),
Q("main-window-y"),
Q("manualAnnounceTime"),
Q("max-peers"),
Q("maxConnectedPeers"),
Q("memory-bytes"),
Q("memory-units"),
Q("message-level"),
Q("metadataPercentComplete"),
Q("metadata_size"),
Q("metainfo"),
Q("method"),
Q("min interval"),
Q("min_request_interval"),
Q("move"),
Q("msg_type"),
Q("mtimes"),
Q("name"),
Q("name.utf-8"),
Q("nextAnnounceTime"),
Q("nextScrapeTime"),
Q("nodes"),
Q("nodes6"),
Q("open-dialog-dir"),
Q("p"),
Q("path"),
Q("path.utf-8"),
Q("paused"),
Q("pausedTorrentCount"),
Q("peer-congestion-algorithm"),
Q("peer-id-ttl-hours"),
Q("peer-limit"),
Q("peer-limit-global"),
Q("peer-limit-per-torrent"),
Q("peer-port"),
Q("peer-port-random-high"),
Q("peer-port-random-low"),
Q("peer-port-random-on-start"),
Q("peer-socket-tos"),
Q("peerIsChoked"),
Q("peerIsInterested"),
Q("peers"),
Q("peers2"),
Q("peers2-6"),
Q("peers6"),
Q("peersConnected"),
Q("peersFrom"),
Q("peersGettingFromUs"),
Q("peersSendingToUs"),
Q("percentDone"),
Q("pex-enabled"),
Q("piece"),
Q("piece length"),
Q("pieceCount"),
Q("pieceSize"),
Q("pieces"),
Q("play-download-complete-sound"),
Q("port"),
Q("port-forwarding-enabled"),
Q("port-is-open"),
Q("preallocation"),
Q("prefetch-enabled"),
Q("primary-mime-type"),
Q("priorities"),
Q("priority"),
Q("priority-high"),
Q("priority-low"),
Q("priority-normal"),
Q("private"),
Q("progress"),
Q("prompt-before-exit"),
Q("queue-move-bottom"),
Q("queue-move-down"),
Q("queue-move-top"),
Q("queue-move-up"),
Q("queue-stalled-enabled"),
Q("queue-stalled-minutes"),
Q("queuePosition"),
Q("rateDownload"),
Q("rateToClient"),
Q("rateToPeer"),
Q("rateUpload"),
Q("ratio-limit"),
Q("ratio-limit-enabled"),
Q("ratio-mode"),
Q("recent-download-dir-1"),
Q("recent-download-dir-2"),
Q("recent-download-dir-3"),
Q("recent-download-dir-4"),
Q("recheckProgress"),
Q("remote-session-enabled"),
Q("remote-session-host"),
Q("remote-session-password"),
Q("remote-session-port"),
Q("remote-session-requres-authentication"),
Q("remote-session-username"),
Q("removed"),
Q("rename-partial-files"),
Q("reqq"),
Q("result"),
Q("rpc-authentication-required"),
Q("rpc-bind-address"),
Q("rpc-enabled"),
Q("rpc-host-whitelist"),
Q("rpc-host-whitelist-enabled"),
Q("rpc-password"),
Q("rpc-port"),
Q("rpc-url"),
Q("rpc-username"),
Q("rpc-version"),
Q("rpc-version-minimum"),
Q("rpc-whitelist"),
Q("rpc-whitelist-enabled"),
Q("scrape"),
Q("scrape-paused-torrents-enabled"),
Q("scrapeState"),
Q("script-torrent-done-enabled"),
Q("script-torrent-done-filename"),
Q("seconds-active"),
Q("secondsActive"),
Q("secondsDownloading"),
Q("secondsSeeding"),
Q("seed-queue-enabled"),
Q("seed-queue-size"),
Q("seedIdleLimit"),
Q("seedIdleMode"),
Q("seedRatioLimit"),
Q("seedRatioLimited"),
Q("seedRatioMode"),
Q("seederCount"),
Q("seeding-time-seconds"),
Q("session-count"),
Q("session-id"),
Q("sessionCount"),
Q("show-backup-trackers"),
Q("show-extra-peer-details"),
Q("show-filterbar"),
Q("show-notification-area-icon"),
Q("show-options-window"),
Q("show-statusbar"),
Q("show-toolbar"),
Q("show-tracker-scrapes"),
Q("size-bytes"),
Q("size-units"),
Q("sizeWhenDone"),
Q("sort-mode"),
Q("sort-reversed"),
Q("speed"),
Q("speed-Bps"),
Q("speed-bytes"),
Q("speed-limit-down"),
Q("speed-limit-down-enabled"),
Q("speed-limit-up"),
Q("speed-limit-up-enabled"),
Q("speed-units"),
Q("start-added-torrents"),
Q("start-minimized"),
Q("startDate"),
Q("status"),
Q("statusbar-stats"),
Q("tag"),
Q("tier"),
Q("time-checked"),
Q("torrent-added"),
Q("torrent-added-notification-command"),
Q("torrent-added-notification-enabled"),
Q("torrent-complete-notification-command"),
Q("torrent-complete-notification-enabled"),
Q("torrent-complete-sound-command"),
Q("torrent-complete-sound-enabled"),
Q("torrent-duplicate"),
Q("torrent-get"),
Q("torrent-set"),
Q("torrent-set-location"),
Q("torrentCount"),
Q("torrentFile"),
Q("torrents"),
Q("totalSize"),
Q("total_size"),
Q("tracker id"),
Q("trackerAdd"),
Q("trackerRemove"),
Q("trackerReplace"),
Q("trackerStats"),
Q("trackers"),
Q("trash-can-enabled"),
Q("trash-original-torrent-files"),
Q("umask"),
Q("units"),
Q("upload-slots-per-torrent"),
Q("uploadLimit"),
Q("uploadLimited"),
Q("uploadRatio"),
Q("uploadSpeed"),
Q("upload_only"),
Q("uploaded"),
Q("uploaded-bytes"),
Q("uploadedBytes"),
Q("uploadedEver"),
Q("url-list"),
Q("use-global-speed-limit"),
Q("use-speed-limit"),
Q("user-has-given-informed-consent"),
Q("ut_comment"),
Q("ut_holepunch"),
Q("ut_metadata"),
Q("ut_pex"),
Q("ut_recommend"),
Q("utp-enabled"),
Q("v"),
Q("version"),
Q("wanted"),
Q("warning message"),
Q("watch-dir"),
Q("watch-dir-enabled"),
Q("webseeds"),
Q("webseedsSendingToUs"),
};
static size_t constexpr quarks_are_sorted = ( //
size_t constexpr quarks_are_sorted = ( //
[]() constexpr
{
for (size_t i = 1; i < std::size(my_static); ++i)
{
char const* lhs = my_static[i - 1].str;
char const* rhs = my_static[i].str;
while (true)
if (my_static[i - 1] >= my_static[i])
{
if (*lhs > *rhs)
{
return false;
}
if (*lhs < *rhs || *lhs == '\0' || *rhs == '\0')
{
break;
}
++lhs;
++rhs;
return false;
}
}
@ -449,75 +426,35 @@ static size_t constexpr quarks_are_sorted = ( //
static_assert(quarks_are_sorted, "Predefined quarks must be sorted by their string value");
#undef Q
auto& my_runtime{ *new std::vector<std::string_view>{} };
static int compareKeys(void const* va, void const* vb)
{
auto const* a = static_cast<struct tr_key_struct const*>(va);
auto const* b = static_cast<struct tr_key_struct const*>(vb);
int ret = memcmp(a->str, b->str, std::min(a->len, b->len));
if (ret == 0 && a->len != b->len)
{
ret = a->len < b->len ? -1 : 1;
}
return ret;
}
static tr_ptrArray my_runtime = {};
} // namespace
bool tr_quark_lookup(void const* str, size_t len, tr_quark* setme)
{
static size_t const n_static = TR_N_ELEMENTS(my_static);
TR_ASSERT(n_static == TR_N_KEYS);
struct tr_key_struct tmp;
tmp.str = static_cast<char const*>(str);
tmp.len = len;
auto constexpr n_static = std::size(my_static);
static_assert(n_static == TR_N_KEYS);
/* is it in our static array? */
auto const* match = static_cast<struct tr_key_struct const*>(
bsearch(&tmp, my_static, n_static, sizeof(struct tr_key_struct), compareKeys));
bool success = false;
if (match != nullptr)
auto const key = std::string_view{ static_cast<char const*>(str), len };
auto constexpr sbegin = std::begin(my_static), send = std::end(my_static);
auto const sit = std::lower_bound(sbegin, send, key);
if (sit != send && *sit == key)
{
*setme = match - my_static;
success = true;
*setme = std::distance(sbegin, sit);
return true;
}
/* was it added during runtime? */
if (!success && !tr_ptrArrayEmpty(&my_runtime))
auto const rbegin = std::begin(my_runtime), rend = std::end(my_runtime);
auto const rit = std::find(rbegin, rend, key);
if (rit != rend)
{
struct tr_key_struct** runtime = (struct tr_key_struct**)tr_ptrArrayBase(&my_runtime);
size_t const n_runtime = tr_ptrArraySize(&my_runtime);
for (size_t i = 0; i < n_runtime; ++i)
{
if (compareKeys(&tmp, runtime[i]) == 0)
{
*setme = TR_N_KEYS + i;
success = true;
break;
}
}
*setme = TR_N_KEYS + std::distance(rbegin, rit);
return true;
}
return success;
}
static tr_quark append_new_quark(void const* str, size_t len)
{
tr_quark ret;
struct tr_key_struct* tmp;
tmp = tr_new(struct tr_key_struct, 1);
tmp->str = tr_strndup(str, len);
tmp->len = len;
ret = TR_N_KEYS + tr_ptrArraySize(&my_runtime);
tr_ptrArrayAppend(&my_runtime, tmp);
return ret;
return false;
}
tr_quark tr_quark_new(void const* str, size_t len)
@ -533,7 +470,8 @@ tr_quark tr_quark_new(void const* str, size_t len)
if (!tr_quark_lookup(str, len, &ret))
{
ret = append_new_quark(str, len);
ret = TR_N_KEYS + std::size(my_runtime);
my_runtime.emplace_back(tr_strndup(str, len), len);
}
}
@ -542,21 +480,12 @@ tr_quark tr_quark_new(void const* str, size_t len)
char const* tr_quark_get_string(tr_quark q, size_t* len)
{
struct tr_key_struct const* tmp;
if (q < TR_N_KEYS)
{
tmp = &my_static[q];
}
else
{
tmp = static_cast<struct tr_key_struct const*>(tr_ptrArrayNth(&my_runtime, q - TR_N_KEYS));
}
auto const& tmp = q < TR_N_KEYS ? my_static[q] : my_runtime[q - TR_N_KEYS];
if (len != nullptr)
{
*len = tmp->len;
*len = std::size(tmp);
}
return tmp->str;
return std::data(tmp);
}