Battery: init support of JSON config

This commit is contained in:
李通洲
2023-03-09 16:01:18 +08:00
parent cbaeed7e8e
commit 790ca460d4
6 changed files with 246 additions and 26 deletions
+2 -1
View File
@@ -70,7 +70,7 @@ cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32"
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_JSONC "Enable json-c" ON "LINUX OR WIN32" OFF)
cmake_dependent_option(ENABLE_JSONC "Enable json-c" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
@@ -228,6 +228,7 @@ configure_file(src/fastfetch_config.h.in fastfetch_config.h)
set(LIBFASTFETCH_SRC
src/common/bar.c
src/common/config.c
src/common/font.c
src/common/format.c
src/common/init.c
+132
View File
@@ -0,0 +1,132 @@
#include "fastfetch.h"
#include "common/config.h"
#ifdef FF_HAVE_JSONC
#include "common/io/io.h"
#include "modules/modules.h"
#include <assert.h>
static inline void wrapJsoncFree(JSONCData* data)
{
assert(data);
if (data->root)
data->ffjson_object_put(data->root);
}
static const char* parseModules(FFinstance* instance, JSONCData* data, json_object* modules)
{
array_list* list = data->ffjson_object_get_array(modules);
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 (data->ffjson_object_is_type(module, json_type_string))
{
type = data->ffjson_object_get_string(module);
module = NULL;
}
else if (data->ffjson_object_is_type(module, json_type_object))
{
type = data->ffjson_object_get_string(data->ffjson_object_object_get(module, "type"));
if (!type) return "module object must contain a type key";
}
else
return "modules must be an array of strings or objects";
if(!ffParseBatteryJsonObject(instance, type, data, module))
return "Unknown module type";
}
return NULL;
}
const char* ffJsonConfigParse(FFinstance* instance)
{
FF_LIBRARY_LOAD(libjsonc, &instance->config.libJSONC, "dlopen libjson-c" FF_LIBRARY_EXTENSION" failed",
#ifdef _WIN32
"libjson-c-5" FF_LIBRARY_EXTENSION, -1
#else
"libjson-c" FF_LIBRARY_EXTENSION, 5
#endif
)
JSONCData __attribute__((__cleanup__(wrapJsoncFree))) data = {};
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_tokener_parse)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_is_type)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_array)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_boolean)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_double)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_string_len)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_string)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_get_object)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_object_get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libjsonc, data, json_object_put)
FF_STRBUF_AUTO_DESTROY content;
ffStrbufInit(&content);
FF_LIST_FOR_EACH(FFstrbuf, filename, instance->state.platform.configDirs)
{
uint32_t oldLength = filename->length;
ffStrbufAppendS(filename, "fastfetch/config.json");
bool success = ffAppendFileBuffer(filename->chars, &content);
ffStrbufSubstrBefore(filename, oldLength);
if (success) break;
}
data.root = data.ffjson_tokener_parse(content.chars);
if (!data.root)
return "Failed to parse JSON config file";
lh_table* rootObject = data.ffjson_object_get_object(data.root);
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 = (struct json_object *)lh_entry_v(entry);
if (strcmp(key, "modules") == 0)
{
const char* error = parseModules(instance, &data, val);
if (error) return error;
}
else
return "Unknown JSON config key in root object";
}
return NULL;
}
bool ffJsonConfigParseModuleArgs(JSONCData* data, const char* key, json_object* val, FFModuleArgs* moduleArgs)
{
if(strcasecmp(key, "key") == 0)
{
ffStrbufSetNS(&moduleArgs->key, (uint32_t) data->ffjson_object_get_string_len(val), data->ffjson_object_get_string(val));
return true;
}
else if(strcasecmp(key, "format") == 0)
{
ffStrbufSetNS(&moduleArgs->outputFormat, (uint32_t) data->ffjson_object_get_string_len(val), data->ffjson_object_get_string(val));
return true;
}
else if(strcasecmp(key, "error") == 0)
{
ffStrbufSetNS(&moduleArgs->errorFormat, (uint32_t) data->ffjson_object_get_string_len(val), data->ffjson_object_get_string(val));
return true;
}
return false;
}
#else
const char* ffParseJsonConfig(FF_MAYBE_UNUSED FFinstance* instance)
{
return "Fastfetch was compiled without json-c support";
}
#endif
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#ifdef FF_HAVE_JSONC
#include <json-c/json.h>
#include "common/library.h"
typedef struct JSONCData
{
FF_LIBRARY_SYMBOL(json_tokener_parse)
FF_LIBRARY_SYMBOL(json_object_is_type)
FF_LIBRARY_SYMBOL(json_object_get_array)
FF_LIBRARY_SYMBOL(json_object_get_boolean)
FF_LIBRARY_SYMBOL(json_object_get_double)
FF_LIBRARY_SYMBOL(json_object_get_string_len)
FF_LIBRARY_SYMBOL(json_object_get_string)
FF_LIBRARY_SYMBOL(json_object_get_object)
FF_LIBRARY_SYMBOL(json_object_object_get)
FF_LIBRARY_SYMBOL(json_object_put)
json_object* root;
} JSONCData;
bool ffJsonConfigParseModuleArgs(JSONCData* data, const char* key, json_object* val, FFModuleArgs* moduleArgs);
#endif
const char* ffJsonConfigParse(FFinstance* instance);
+33 -25
View File
@@ -18,6 +18,7 @@
#pragma GCC diagnostic ignored "-Wsign-conversion"
#include "modules/os/os.h"
#include "common/config.h"
#include "modules/modules.h"
typedef struct CustomValue
@@ -1537,34 +1538,41 @@ int main(int argc, const char** argv)
fflush(stdout);
#endif
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data.structure.length)
if (ffStrbufIgnCaseEqualS(&data.structure, "Config"))
{
uint32_t colonIndex = ffStrbufNextIndexC(&data.structure, startIndex, ':');
data.structure.chars[colonIndex] = '\0';
uint64_t ms = 0;
if(__builtin_expect(instance.config.stat, false))
ms = ffTimeGetTick();
parseStructureCommand(&instance, &data, data.structure.chars + startIndex);
if(__builtin_expect(instance.config.stat, false))
ffJsonConfigParse(&instance);
}
else
{
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data.structure.length)
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
if(instance.config.pipe)
puts(str);
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
uint32_t colonIndex = ffStrbufNextIndexC(&data.structure, startIndex, ':');
data.structure.chars[colonIndex] = '\0';
uint64_t ms = 0;
if(__builtin_expect(instance.config.stat, false))
ms = ffTimeGetTick();
parseStructureCommand(&instance, &data, data.structure.chars + startIndex);
if(__builtin_expect(instance.config.stat, false))
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
if(instance.config.pipe)
puts(str);
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
#if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
fflush(stdout);
#endif
startIndex = colonIndex + 1;
}
#if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
fflush(stdout);
#endif
startIndex = colonIndex + 1;
}
ffFinish(&instance);
+45
View File
@@ -146,3 +146,48 @@ void ffDestroyBatteryOptions(FFBatteryOptions* options)
ffStrbufDestroy(&options->dir);
#endif
}
#ifdef FF_HAVE_JSONC
bool ffParseBatteryJsonObject(FFinstance* instance, const char* type, JSONCData* data, json_object* module)
{
if (strcasecmp(type, FF_BATTERY_MODULE_NAME) != 0)
return false;
FFBatteryOptions __attribute__((__cleanup__(ffDestroyBatteryOptions))) options;
ffInitBatteryOptions(&options);
if (module)
{
struct lh_entry* entry;
lh_foreach(data->ffjson_object_get_object(module), entry)
{
const char* key = (const char *)lh_entry_k(entry);
if (strcasecmp(key, "type") == 0)
continue;
json_object* val = (struct json_object *)lh_entry_v(entry);
if (ffJsonConfigParseModuleArgs(data, key, val, &options.moduleArgs))
continue;
#ifdef __linux__
if (strcasecmp(key, "dir") == 0)
{
ffStrbufSetS(&options.dir, data->ffjson_object_get_string(val));
continue;
}
#endif
if (strcasecmp(key, "temp") == 0)
{
options.temp = (bool) data->ffjson_object_get_boolean(val);
continue;
}
ffPrintError(instance, FF_BATTERY_MODULE_NAME, 0, &options.moduleArgs, "Unknown JSON key %s", key);
}
}
ffPrintBattery(instance, &options);
return true;
}
#endif
+5
View File
@@ -8,3 +8,8 @@ void ffPrintBattery(FFinstance* instance, FFBatteryOptions* options);
void ffInitBatteryOptions(FFBatteryOptions* options);
bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, const char* value);
void ffDestroyBatteryOptions(FFBatteryOptions* options);
#ifdef FF_HAVE_JSONC
#include "common/config.h"
bool ffParseBatteryJsonObject(FFinstance* instance, const char* type, JSONCData* data, json_object* module);
#endif