Files
fastfetch/src/modules/jsonconfig/jsonconfig.c
T

229 lines
7.8 KiB
C
Raw Normal View History

2023-03-09 18:57:57 +08:00
#include "modules/jsonconfig/jsonconfig.h"
#include "common/jsonconfig.h"
2023-03-09 18:57:57 +08:00
#include "common/printing.h"
#ifdef FF_HAVE_JSONC
#include "common/io/io.h"
#include "common/json.h"
2023-03-09 18:57:57 +08:00
#include "modules/modules.h"
#include <assert.h>
2023-03-15 16:54:50 +08:00
#include <ctype.h>
2023-03-09 18:57:57 +08:00
2023-03-15 16:54:50 +08:00
static inline bool tryModule(FFinstance* instance, const char* type, json_object* module, const char* moduleName, void (*const f)(FFinstance *instance, json_object *module))
2023-03-09 18:57:57 +08:00
{
2023-03-15 16:54:50 +08:00
if (strcasecmp(type, moduleName) == 0)
{
if (module) json_object_object_del(module, "type"); // this line frees `type`
f(instance, module);
return true;
}
return false;
}
static bool parseModuleJsonObject(FFinstance* instance, const char* type, json_object* module)
{
switch (toupper(type[0]))
{
case 'B': {
return
tryModule(instance, type, module, FF_BATTERY_MODULE_NAME, ffParseBatteryJsonObject) ||
tryModule(instance, type, module, FF_BIOS_MODULE_NAME, ffParseBiosJsonObject) ||
tryModule(instance, type, module, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothJsonObject) ||
tryModule(instance, type, module, FF_BOARD_MODULE_NAME, ffParseBoardJsonObject) ||
tryModule(instance, type, module, FF_BREAK_MODULE_NAME, ffParseBreakJsonObject) ||
tryModule(instance, type, module, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessJsonObject) ||
false;
}
case 'C': {
return
2023-03-15 18:17:24 +08:00
tryModule(instance, type, module, FF_CPU_MODULE_NAME, ffParseCPUJsonObject) ||
2023-03-17 17:56:31 +08:00
tryModule(instance, type, module, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageJsonObject) ||
2023-03-15 16:54:50 +08:00
tryModule(instance, type, module, FF_COMMAND_MODULE_NAME, ffParseCommandJsonObject) ||
2023-03-15 17:02:54 +08:00
tryModule(instance, type, module, FF_COLORS_MODULE_NAME, ffParseColorsJsonObject) ||
2023-03-20 14:57:46 +08:00
tryModule(instance, type, module, FF_CURSOR_MODULE_NAME, ffParseCursorJsonObject) ||
2023-03-20 15:46:00 +08:00
tryModule(instance, type, module, FF_CUSTOM_MODULE_NAME, ffParseCustomJsonObject) ||
2023-03-15 16:54:50 +08:00
false;
}
case 'D': {
return
tryModule(instance, type, module, FF_DATETIME_MODULE_NAME, ffParseDateTimeJsonObject) ||
tryModule(instance, type, module, FF_DISPLAY_MODULE_NAME, ffParseDisplayJsonObject) ||
2023-04-02 00:13:11 +08:00
tryModule(instance, type, module, FF_DISK_MODULE_NAME, ffParseDiskJsonObject) ||
2023-03-15 16:54:50 +08:00
false;
}
2023-04-04 12:28:52 +08:00
case 'F': {
return
tryModule(instance, type, module, FF_FONT_MODULE_NAME, ffParseFontJsonObject) ||
false;
}
2023-03-26 20:42:18 +08:00
case 'G': {
return
2023-04-04 11:01:42 +08:00
tryModule(instance, type, module, FF_GAMEPAD_MODULE_NAME, ffParseGamepadJsonObject) ||
2023-03-26 20:42:18 +08:00
tryModule(instance, type, module, FF_GPU_MODULE_NAME, ffParseGPUJsonObject) ||
false;
}
2023-03-15 16:54:50 +08:00
case 'H': {
return
tryModule(instance, type, module, FF_HOST_MODULE_NAME, ffParseHostJsonObject) ||
false;
}
case 'K': {
return
tryModule(instance, type, module, FF_KERNEL_MODULE_NAME, ffParseKernelJsonObject) ||
false;
}
2023-04-04 17:47:42 +08:00
case 'L': {
return
tryModule(instance, type, module, FF_LOCALE_MODULE_NAME, ffParseLocaleJsonObject) ||
2023-04-04 20:46:50 +08:00
tryModule(instance, type, module, FF_LOCALIP_MODULE_NAME, ffParseLocalIpJsonObject) ||
2023-04-04 17:47:42 +08:00
false;
}
2023-05-11 21:07:04 +08:00
case 'M': {
return
tryModule(instance, type, module, FF_MEMORY_MODULE_NAME, ffParseMemoryJsonObject) ||
false;
}
2023-03-15 16:54:50 +08:00
case 'O': {
return
tryModule(instance, type, module, FF_OS_MODULE_NAME, ffParseOSJsonObject) ||
false;
}
2023-05-26 14:32:27 +08:00
case 'P': {
return
tryModule(instance, type, module, FF_PACKAGES_MODULE_NAME, ffParsePackagesJsonObject) ||
false;
}
2023-03-15 16:54:50 +08:00
case 'S': {
return
tryModule(instance, type, module, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorJsonObject) ||
2023-04-12 14:05:09 +08:00
tryModule(instance, type, module, FF_SOUND_MODULE_NAME, ffParseSoundJsonObject) ||
2023-05-11 21:07:04 +08:00
tryModule(instance, type, module, FF_SWAP_MODULE_NAME, ffParseSwapJsonObject) ||
2023-03-15 16:54:50 +08:00
false;
}
case 'T': {
return
tryModule(instance, type, module, FF_TITLE_MODULE_NAME, ffParseTitleJsonObject) ||
false;
}
2023-04-25 19:57:27 +08:00
case 'U': {
return
tryModule(instance, type, module, FF_UPTIME_MODULE_NAME, ffParseUptimeJsonObject) ||
false;
}
2023-04-28 19:11:55 +08:00
case 'W': {
return
2023-05-23 15:30:59 +08:00
tryModule(instance, type, module, FF_WIFI_MODULE_NAME, ffParseWifiJsonObject) ||
2023-04-28 19:11:55 +08:00
tryModule(instance, type, module, FF_WMTHEME_MODULE_NAME, ffParseWMThemeJsonObject) ||
false;
}
2023-03-15 16:54:50 +08:00
default:
return false;
}
2023-03-09 18:57:57 +08:00
}
static const char* parseModules(FFinstance* instance, json_object* modules)
2023-03-09 18:57:57 +08:00
{
array_list* list = json_object_get_array(modules);
2023-03-09 18:57:57 +08:00
if (!list) return "modules must be an array of strings or objects";
for (size_t idx = 0; idx < list->length; ++idx)
{
json_object* module = (json_object*) list->array[idx];
const char* type = NULL;
if (json_object_is_type(module, json_type_string))
2023-03-09 18:57:57 +08:00
{
type = json_object_get_string(module);
2023-03-09 18:57:57 +08:00
module = NULL;
}
else if (json_object_is_type(module, json_type_object))
2023-03-09 18:57:57 +08:00
{
json_object* object = json_object_object_get(module, "type");
type = json_object_get_string(object);
2023-03-15 16:54:50 +08:00
if (!type) return "module object must contain a \"type\" key ( case sensitive )";
if (json_object_object_length(module) == 1) // contains only Property type
module = NULL;
2023-03-09 18:57:57 +08:00
}
else
return "modules must be an array of strings or objects";
if(!parseModuleJsonObject(instance, type, module))
2023-03-09 18:57:57 +08:00
return "Unknown module type";
}
return NULL;
}
static const char* printJsonConfig(FFinstance* instance)
{
if (!ffJsonLoadLibrary(instance))
return "Failed to load json-c library";
2023-03-09 18:57:57 +08:00
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
2023-03-09 18:57:57 +08:00
FF_LIST_FOR_EACH(FFstrbuf, filename, instance->state.platform.configDirs)
{
uint32_t oldLength = filename->length;
ffStrbufAppendS(filename, "fastfetch/config.jsonc");
2023-03-09 18:57:57 +08:00
bool success = ffAppendFileBuffer(filename->chars, &content);
ffStrbufSubstrBefore(filename, oldLength);
if (success) break;
}
json_object* __attribute__((__cleanup__(wrapJsoncFree))) root = json_tokener_parse(content.chars);
if (!root)
2023-03-09 18:57:57 +08:00
return "Failed to parse JSON config file";
lh_table* rootObject = json_object_get_object(root);
2023-03-09 18:57:57 +08:00
if (!rootObject)
return "Invalid JSON config format. Root value must be an object";
struct lh_entry* entry;
lh_foreach(rootObject, entry)
{
const char* key = (const char *)lh_entry_k(entry);
json_object* val = (json_object *)lh_entry_v(entry);
2023-03-09 18:57:57 +08:00
if (strcmp(key, "modules") == 0)
{
const char* error = parseModules(instance, val);
2023-03-09 18:57:57 +08:00
if (error) return error;
}
else
return "Unknown JSON config key in root object";
}
return NULL;
}
#else
static const char* printJsonConfig(FF_MAYBE_UNUSED FFinstance* instance)
{
return "Fastfetch was compiled without json-c support";
}
#endif
void ffPrintJsonConfig(FFinstance* instance)
{
const char* error = printJsonConfig(instance);
if (error)
ffPrintErrorString(instance, "JsonConfig", 0, NULL, NULL, "%s", error);
}