JsonConfig: refactor string buffer JSON handling for robustness

This commit is contained in:
李通洲
2025-08-02 17:41:19 +08:00
parent 6d86813647
commit 3cef51ec4a
21 changed files with 90 additions and 64 deletions
+3 -3
View File
@@ -16,12 +16,12 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs*
{
if(ffStrEqualsIgnCase(key, "key"))
{
ffStrbufSetNS(&moduleArgs->key, (uint32_t) yyjson_get_len(val), yyjson_get_str(val));
ffStrbufSetJsonVal(&moduleArgs->key, val);
return true;
}
else if(ffStrEqualsIgnCase(key, "format"))
{
ffStrbufSetNS(&moduleArgs->outputFormat, (uint32_t) yyjson_get_len(val), yyjson_get_str(val));
ffStrbufSetJsonVal(&moduleArgs->outputFormat, val);
return true;
}
else if(ffStrEqualsIgnCase(key, "outputColor"))
@@ -41,7 +41,7 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs*
}
else if(ffStrEqualsIgnCase(key, "keyIcon"))
{
ffStrbufSetS(&moduleArgs->keyIcon, yyjson_get_str(val));
ffStrbufSetJsonVal(&moduleArgs->keyIcon, val);
return true;
}
return false;
+1 -1
View File
@@ -45,7 +45,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
ffStrbufInitStatic(&camera->name, "Unknown");
}
ffStrbufInit(&camera->vendor);
ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id")));
ffStrbufInitJsonVal(&camera->id, yyjson_obj_get(device, "id"));
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
if (yyjson_is_obj(sizes))
{
+2 -2
View File
@@ -59,7 +59,7 @@ static void detectScoop(FFPackagesResult* result)
{
ffStrbufClear(&scoopPath);
if (root)
ffStrbufSetS(&scoopPath, yyjson_get_str(yyjson_obj_get(root, "root_path")));
ffStrbufSetJsonVal(&scoopPath, yyjson_obj_get(root, "root_path"));
if (scoopPath.length == 0)
{
ffStrbufSet(&scoopPath, &instance.state.platform.homeDir);
@@ -72,7 +72,7 @@ static void detectScoop(FFPackagesResult* result)
{
ffStrbufClear(&scoopPath);
if (root)
ffStrbufSetS(&scoopPath, yyjson_get_str(yyjson_obj_get(root, "global_path")));
ffStrbufSetJsonVal(&scoopPath, yyjson_obj_get(root, "global_path"));
if (scoopPath.length == 0)
{
ffStrbufSetS(&scoopPath, getenv("ProgramData"));
+1 -1
View File
@@ -84,7 +84,7 @@ const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* resul
if (doc)
{
yyjson_val* root = yyjson_doc_get_root(doc);
ffStrbufAppendS(&result->ip, yyjson_get_str(yyjson_obj_get(root, "ip")));
ffStrbufAppendJsonVal(&result->ip, yyjson_obj_get(root, "ip"));
ffStrbufDestroy(&result->location);
ffStrbufInitF(&result->location, "%s, %s", yyjson_get_str(yyjson_obj_get(root, "city")), yyjson_get_str(yyjson_obj_get(root, "country")));
return NULL;
@@ -23,16 +23,14 @@ static const char* detectWTProfile(yyjson_val* profile, FFstrbuf* name, double*
if (name->length == 0)
{
yyjson_val* pface = yyjson_obj_get(font, "face");
if(yyjson_is_str(pface))
ffStrbufAppendS(name, unsafe_yyjson_get_str(pface));
ffStrbufAppendJsonVal(name, yyjson_obj_get(font, "face"));
}
if (*size < 0)
{
yyjson_val* psize = yyjson_obj_get(font, "size");
if (yyjson_is_num(psize))
*size = yyjson_get_num(psize);
*size = unsafe_yyjson_get_num(psize);
}
return NULL;
}
+4 -4
View File
@@ -46,7 +46,7 @@ const char* ffDetectWifi(FFlist* result)
item->conn.channel = 0;
item->conn.frequency = 0;
ffStrbufAppendS(&item->inf.status, yyjson_get_str(yyjson_obj_get(root, "supplicant_state")));
ffStrbufAppendJsonVal(&item->inf.status, yyjson_obj_get(root, "supplicant_state"));
if(!item->inf.status.length)
{
ffStrbufAppendS(&item->inf.status, "Unknown");
@@ -59,9 +59,9 @@ const char* ffDetectWifi(FFlist* result)
double rssi = yyjson_get_num(yyjson_obj_get(root, "rssi"));
item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2;
ffStrbufAppendS(&item->inf.description, yyjson_get_str(yyjson_obj_get(root, "ip")));
ffStrbufAppendS(&item->conn.bssid, yyjson_get_str(yyjson_obj_get(root, "bssid")));
ffStrbufAppendS(&item->conn.ssid, yyjson_get_str(yyjson_obj_get(root, "ssid")));
ffStrbufAppendJsonVal(&item->inf.description, yyjson_obj_get(root, "ip"));
ffStrbufAppendJsonVal(&item->conn.bssid, yyjson_obj_get(root, "bssid"));
ffStrbufAppendJsonVal(&item->conn.ssid, yyjson_obj_get(root, "ssid"));
item->conn.frequency = (uint16_t) yyjson_get_int(yyjson_obj_get(root, "frequency_mhz"));
item->conn.txRate = yyjson_get_num(yyjson_obj_get(root, "link_speed_mbps"));
item->conn.channel = ffWifiFreqToChannel(item->conn.frequency);
+3 -3
View File
@@ -86,19 +86,19 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "shell"))
{
ffStrbufSetS(&options->shell, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->shell, val);
continue;
}
if (ffStrEqualsIgnCase(key, "param"))
{
ffStrbufSetS(&options->param, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->param, val);
continue;
}
if (ffStrEqualsIgnCase(key, "text"))
{
ffStrbufSetS(&options->text, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->text, val);
continue;
}
+3 -3
View File
@@ -312,19 +312,19 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "folders"))
{
ffStrbufSetS(&options->folders, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->folders, val);
continue;
}
if (ffStrEqualsIgnCase(key, "hideFolders"))
{
ffStrbufSetS(&options->hideFolders, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->hideFolders, val);
continue;
}
if (ffStrEqualsIgnCase(key, "hideFS"))
{
ffStrbufSetS(&options->hideFS, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->hideFS, val);
continue;
}
+1 -1
View File
@@ -138,7 +138,7 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "namePrefix"))
{
ffStrbufSetS(&options->namePrefix, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->namePrefix, val);
continue;
}
+1 -1
View File
@@ -407,7 +407,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "namePrefix"))
{
ffStrbufSetS(&options->namePrefix, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->namePrefix, val);
continue;
}
+1 -1
View File
@@ -152,7 +152,7 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "namePrefix"))
{
ffStrbufSetS(&options->namePrefix, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->namePrefix, val);
continue;
}
+6 -1
View File
@@ -345,7 +345,12 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
size_t flagIdx, flagMax;
yyjson_arr_foreach(val, flagIdx, flagMax, flagObj)
{
const char* flag = yyjson_get_str(flagObj);
if (!yyjson_is_str(flagObj))
{
ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", key);
continue;
}
const char* flag = unsafe_yyjson_get_str(flagObj);
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(flag, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
switch (toupper(flag[0]))
+1 -1
View File
@@ -167,7 +167,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m
if (ffStrEqualsIgnCase(key, "namePrefix"))
{
ffStrbufSetS(&options->namePrefix, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->namePrefix, val);
continue;
}
+1 -1
View File
@@ -82,7 +82,7 @@ void ffParsePublicIpJsonObject(FFPublicIpOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "url"))
{
ffStrbufSetS(&options->url, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->url, val);
continue;
}
+1 -1
View File
@@ -152,7 +152,7 @@ void ffParseSeparatorJsonObject(FFSeparatorOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "string"))
{
ffStrbufSetS(&options->string, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->string, val);
continue;
}
+2 -2
View File
@@ -72,13 +72,13 @@ void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module)
if (ffStrEqualsIgnCase(key, "location"))
{
ffStrbufSetS(&options->location, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->location, val);
continue;
}
if (ffStrEqualsIgnCase(key, "outputFormat"))
{
ffStrbufSetS(&options->outputFormat, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->outputFormat, val);
continue;
}
+20 -20
View File
@@ -48,7 +48,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
else if (ffStrEqualsIgnCase(key, "hideCursor"))
options->hideCursor = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "separator"))
ffStrbufSetS(&options->keyValueSeparator, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->keyValueSeparator, val);
else if (ffStrEqualsIgnCase(key, "color"))
{
if (yyjson_is_str(val))
@@ -58,18 +58,18 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
}
else if (yyjson_is_obj(val))
{
const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys"));
yyjson_val* colorKeys = yyjson_obj_get(val, "keys");
if (colorKeys)
ffOptionParseColor(colorKeys, &options->colorKeys);
const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title"));
ffOptionParseColor(yyjson_get_str(colorKeys), &options->colorKeys);
yyjson_val* colorTitle = yyjson_obj_get(val, "title");
if (colorTitle)
ffOptionParseColor(colorTitle, &options->colorTitle);
const char* colorOutput = yyjson_get_str(yyjson_obj_get(val, "output"));
ffOptionParseColor(yyjson_get_str(colorTitle), &options->colorTitle);
yyjson_val* colorOutput = yyjson_obj_get(val, "output");
if (colorOutput)
ffOptionParseColor(colorOutput, &options->colorOutput);
const char* colorSeparator = yyjson_get_str(yyjson_obj_get(val, "separator"));
ffOptionParseColor(yyjson_get_str(colorOutput), &options->colorOutput);
yyjson_val* colorSeparator = yyjson_obj_get(val, "separator");
if (colorSeparator)
ffOptionParseColor(colorSeparator, &options->colorSeparator);
ffOptionParseColor(yyjson_get_str(colorSeparator), &options->colorSeparator);
}
else
return "display.color must be either a string or an object";
@@ -268,21 +268,21 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
{
if (!yyjson_is_obj(char_)) return "display.bar.char must be an object";
const char* charElapsed = yyjson_get_str(yyjson_obj_get(char_, "elapsed"));
yyjson_val* charElapsed = yyjson_obj_get(char_, "elapsed");
if (charElapsed)
ffStrbufSetS(&options->barCharElapsed, charElapsed);
ffStrbufSetJsonVal(&options->barCharElapsed, charElapsed);
const char* charTotal = yyjson_get_str(yyjson_obj_get(char_, "total"));
yyjson_val* charTotal = yyjson_obj_get(char_, "total");
if (charTotal)
ffStrbufSetS(&options->barCharTotal, charTotal);
ffStrbufSetJsonVal(&options->barCharTotal, charTotal);
}
else
{
const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed"));
yyjson_val* charElapsed = yyjson_obj_get(val, "charElapsed");
if (charElapsed)
return "display.bar.charElapsed has been renamed to display.bar.char.elapsed.";
const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal"));
yyjson_val* charTotal = yyjson_obj_get(val, "charTotal");
if (charTotal)
return "display.bar.charTotal has been renamed to display.bar.char.total.";
}
@@ -303,19 +303,19 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* borderLeft = yyjson_obj_get(border, "left");
if (borderLeft)
ffStrbufSetS(&options->barBorderLeft, yyjson_get_str(borderLeft));
ffStrbufSetJsonVal(&options->barBorderLeft, borderLeft);
yyjson_val* borderRight = yyjson_obj_get(border, "right");
if (borderRight)
ffStrbufSetS(&options->barBorderRight, yyjson_get_str(borderRight));
ffStrbufSetJsonVal(&options->barBorderRight, borderRight);
yyjson_val* borderLeftElapsed = yyjson_obj_get(border, "leftElapsed");
if (borderLeftElapsed)
ffStrbufSetS(&options->barBorderLeftElapsed, yyjson_get_str(borderLeftElapsed));
ffStrbufSetJsonVal(&options->barBorderLeftElapsed, borderLeftElapsed);
yyjson_val* borderRightElapsed = yyjson_obj_get(border, "rightElapsed");
if (borderRightElapsed)
ffStrbufSetS(&options->barBorderRightElapsed, yyjson_get_str(borderRightElapsed));
ffStrbufSetJsonVal(&options->barBorderRightElapsed, borderRightElapsed);
}
}
else
@@ -418,7 +418,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
yyjson_val* item;
size_t idx, max;
yyjson_arr_foreach(val, idx, max, item)
ffStrbufInitS(ffListAdd(&options->constants), yyjson_get_str(item));
ffStrbufInitJsonVal(ffListAdd(&options->constants), item);
}
else if (ffStrEqualsIgnCase(key, "freq"))
{
+5 -3
View File
@@ -18,13 +18,15 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
{
const char* key = yyjson_get_str(key_);
if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
if (ffStrEqualsIgnCase(key, "thread"))
options->multithreading = yyjson_get_bool(val);
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
options->processingTimeout = (int32_t) yyjson_get_int(val);
else if (ffStrEqualsIgnCase(key, "preRun"))
{
if (system(yyjson_get_str(val)) < 0)
if (!yyjson_is_str(val))
return "general.preRun must be a string";
if (system(unsafe_yyjson_get_str(val)) < 0)
return "Failed to execute preRun command";
}
else if (ffStrEqualsIgnCase(key, "detectVersion"))
@@ -32,7 +34,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
else if (ffStrEqualsIgnCase(key, "playerName"))
ffStrbufSetS(&options->playerName, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->playerName, val);
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
{
if (yyjson_is_str(val))
+3 -4
View File
@@ -263,8 +263,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
if (yyjson_is_str(object))
{
const char* value = yyjson_get_str(object);
ffStrbufSetS(&options->source, value);
ffStrbufSetJsonVal(&options->source, object);
return NULL;
}
@@ -305,7 +304,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
}
else if (ffStrEqualsIgnCase(key, "source"))
{
ffStrbufSetS(&options->source, yyjson_get_str(val));
ffStrbufSetJsonVal(&options->source, val);
continue;
}
else if (ffStrEqualsIgnCase(key, "color"))
@@ -403,7 +402,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
yyjson_val* symbols = yyjson_obj_get(val, "symbols");
if (symbols)
ffStrbufSetS(&options->chafaSymbols, yyjson_get_str(symbols));
ffStrbufSetJsonVal(&options->chafaSymbols, symbols);
yyjson_val* canvasMode = yyjson_obj_get(val, "canvasMode");
if (canvasMode)
-6
View File
@@ -219,12 +219,6 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c)
strbuf->length += 1;
}
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value)
{
ffStrbufClear(strbuf);
ffStrbufAppendNS(strbuf, length, value);
}
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c)
{
if(strbuf->length == 0)
+29 -1
View File
@@ -9,6 +9,7 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "3rdparty/yyjson/yyjson.h"
#ifdef _WIN32
// #include <shlwapi.h>
@@ -48,7 +49,6 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c);
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c);
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
@@ -211,6 +211,16 @@ static inline void ffStrbufAppendS(FFstrbuf* strbuf, const char* value)
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
}
static inline bool ffStrbufAppendJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal)
{
if (yyjson_is_str(jsonVal))
{
ffStrbufAppendNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal));
return true;
}
return false;
}
static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
{
ffStrbufClear(strbuf);
@@ -219,6 +229,12 @@ static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
}
static inline void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value)
{
ffStrbufClear(strbuf);
ffStrbufAppendNS(strbuf, length, value);
}
static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
{
assert(value && value != strbuf);
@@ -230,6 +246,12 @@ static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
ffStrbufSetNS(strbuf, value->length, value->chars);
}
static inline bool ffStrbufSetJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal)
{
ffStrbufClear(strbuf);
return ffStrbufAppendJsonVal(strbuf, jsonVal);
}
static inline void ffStrbufInit(FFstrbuf* strbuf)
{
extern char* CHAR_NULL_PTR;
@@ -284,6 +306,12 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateNS(uint32_t length, const ch
return strbuf;
}
static inline bool ffStrbufInitJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal)
{
ffStrbufInit(strbuf);
return ffStrbufAppendJsonVal(strbuf, jsonVal);
}
static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str)
{
ffStrbufInit(strbuf);