structure and values can be set in fastfetch via command line and file!

This commit is contained in:
Linus Dierheimer
2021-03-03 19:59:39 +01:00
parent 4dffbb0bb7
commit db6d2eb3a3
21 changed files with 398 additions and 329 deletions
+2 -1
View File
@@ -26,7 +26,7 @@ include_directories(
)
set(SRCS
src/util.c
src/common.c
src/logo.c
src/modules/break.c
src/modules/custom.c
@@ -55,6 +55,7 @@ set(SRCS
add_executable(fastfetch
src/fastfetch.c
src/util/FFvaluestore.c
${SRCS}
)
-51
View File
@@ -174,59 +174,8 @@ static const char* getCacheDir(FFinstance* instance)
return cache;
}
static const char* getConfigDir(FFinstance* instance)
{
static char config[256];
static bool init = false;
if(init)
return config;
const char* xdgConfig = getenv("XDG_CONFIG_HOME");
if(xdgConfig == NULL)
{
strcpy(config, instance->state.passwd->pw_dir);
strcat(config, "/.config");
}
else
{
strcpy(config, xdgConfig);
}
mkdir(config, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a config folder but whow knews
strcat(config, "/fastfetch/");
mkdir(config, S_IRWXU | S_IRGRP | S_IROTH);
init = true;
return config;
}
bool ffPrintCustomValue(FFinstance* instance, const char* key)
{
char fileName[256];
strcpy(fileName, getConfigDir(instance));
strcat(fileName, "values/");
strcat(fileName, key);
char value[1024];
ffGetFileContent(fileName, value, sizeof(value));
if(value[0] == '\0')
return false;
ffPrintLogoAndKey(instance, key);
puts(value);
return true;
}
bool ffPrintCachedValue(FFinstance* instance, const char* key)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, key))
return true;
#endif // FASTFETCH_BUILD_FLASHFETCH
if(instance->config.recache)
return false;
+310 -210
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include "fastfetch_config.h"
#include "util/FFvaluestore.h"
#include <malloc.h>
#include <sys/types.h>
@@ -7,24 +8,48 @@
#include <sys/stat.h>
#include <fcntl.h>
#define FASTFETCH_DEFAULT_STRUCTURE "Title:Seperator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:Theme:Icons:Font:Terminal:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors"
#define FASTFETCH_DEFAULT_CONFIG \
"--structure "FASTFETCH_DEFAULT_STRUCTURE"\n" \
"--seperator 4\n" \
"--offsetx 0\n" \
"--color-logo true\n" \
"--recache false\n" \
"--show-errors false\n"
//Things only needed by fastfetch
typedef struct FFdata
{
FFvaluestore valuestore;
char structure[2048];
char logoName[32];
} FFdata;
static void printHelp()
{
puts(
"usage: fastfetch <options>\n"
"\n"
" -h, --help: shows this message and exits\n"
" -h <command>, --help <command>: shows help for a specific command and exits\n"
" -v --version prints the version of fastfetch and exits\n"
" -l <name>, --logo <name>: sets the shown logo. Also changes the main color accordingly\n"
" -c <color>, --color <color>: sets the color of the keys. Must be a linux console color code\n"
" -s <width>, --seperator <width>: sets the distance between logo and text\n"
" -x <offset>, --offsetx <offset>: sets the x offset. Can be negative to cut the logo, but no more than logo width.\n"
" --no-color: disables all colors. This MUST be before -l/--logo or --print-logos\n"
" --no-color-logo: disables the coloring of the logo. This MUST be before -l/--logo or --print-logos\n"
" -r --recache: dont use cached values and generate new ones\n"
" --show-errors: if an error occurs, show it instead of discarding the category\n"
" --list-logos: lists the names of available logos and exits\n"
" --print-logos: prints available logos and exits\n"
" -h, --help: shows this message and exits\n"
" -h <command>, --help <command>: shows help for a specific command and exits\n"
" -v --version: prints the version of fastfetch and exits\n"
" --list-logos: list available logos and exits\n"
" --print-logos: shows available logos and exits\n"
" --print-default-config: prints the default config and exits\n"
" --structure <structure>: sets the structure of the fetch. Must be a colon seperated list of keys\n"
" --set <key=value>: hard set the value of an key"
" -l <name>, --logo <name>: sets the shown logo. Also changes the main color accordingly\n"
" -c <color>, --color <color>: sets the color of the keys. Must be a linux console color code\n"
" -s <width>, --seperator <width>: sets the distance between logo and text\n"
" -x <offset>, --offsetx <offset>: sets the x offset. Can be negative to cut the logo, but no more than logo width.\n"
" --show-errors <?value>: print occuring errors\n"
" --color-logo <?value>: if set to false, the logo will be black / white\n"
" -r <?value> --recache <?value>: if set to true, no cached values will be used\n"
"\n"
"If an value starts with an ?, it is optional. \"true\" will be used if not set.\n"
"\n"
"All options can be make permanent in $XDG_CONFIG_HOME/fastfetch/config.conf"
);
}
@@ -51,131 +76,9 @@ static void printCommandHelp(const char* command)
printf("No specific help for command %s provided\n", command);
}
static void parseArguments(int argc, char** argv, FFconfig* config)
{
bool colorText = true;
int logoIndex = -1;
for(int i = 1; i < argc; i++)
{
if(strcasecmp(argv[i], "-h") == 0 || strcasecmp(argv[i], "--help") == 0)
{
if(i == argc - 1)
printHelp();
else
printCommandHelp(argv[i + 1]);
exit(0);
}
else if(strcasecmp(argv[i], "-v") == 0 || strcasecmp(argv[i], "--version") == 0)
{
puts(FASTFETCH_PROJECT_NAME" "FASTFETCH_PROJECT_VER);
exit(0);
}
else if(strcasecmp(argv[i], "--list-logos") == 0)
{
ffListLogos();
exit(0);
}
else if(strcasecmp(argv[i], "--print-logos") == 0)
{
ffPrintLogos(config->colorLogo);
exit(0);
}
else if(strcasecmp(argv[i], "--show-errors") == 0)
{
config->showErrors = true;
}
else if(strcasecmp(argv[i], "-l") == 0 || strcasecmp(argv[i], "--logo") == 0)
{
if(i == argc - 1)
{
printf("Error: usage: %s <logo>\n", argv[i]);
exit(41);
}
logoIndex = i + 1;
++i;
}
else if(strcasecmp(argv[i], "-c") == 0 || strcasecmp(argv[i], "--color") == 0)
{
if(i == argc - 1)
{
printf("Error: usage: %s <color>\n", argv[i]);
exit(42);
}
size_t len = strlen(argv[i + 1]);
if(len > 28)
{
printf("Error: max color string length is 28, %zu given\n", len);
exit(43);
}
sprintf(config->color, "\033[%sm", argv[i + 1]);
++i;
}
else if(strcasecmp(argv[i], "-s") == 0 || strcasecmp(argv[i], "--seperator") == 0)
{
if(i == argc -1)
{
printf("Error: usage: %s <width>\n", argv[i]);
exit(44);
}
if(sscanf(argv[i + 1], "%hd", &config->logo_seperator) != 1)
{
printf("Error: couldn't parse %s to uint16_t\n", argv[i + 1]);
exit(45);
}
++i;
}
else if(strcasecmp(argv[i], "-x") == 0 || strcasecmp(argv[i], "--offsetx") == 0)
{
if(i == argc -1)
{
printf("Error: usage: %s <offset>\n", argv[i]);
exit(46);
}
if(sscanf(argv[i + 1], "%hi", &config->offsetx) != 1)
{
printf("Error: couldn't parse %s to int16_t\n", argv[i + 1]);
exit(47);
}
++i;
}
else if(strcasecmp(argv[i], "-r") == 0 || strcasecmp(argv[i], "--recache") == 0)
{
config->recache = true;
}
else if(strcasecmp(argv[i], "--no-color") == 0)
{
colorText = false;
config->colorLogo = false;
}
else if(strcasecmp(argv[i], "--no-color-logo") == 0)
{
config->colorLogo = false;
}
else
{
printf("Error: unknown option: %s\n", argv[i]);
exit(40);
}
}
//Load logo after parsing because of --no-color and --no-color-logo
if(logoIndex >= 0)
ffLoadLogoSet(config, argv[logoIndex]);
else
ffLoadLogo(config);
//We need to do this after loading the logo
if(colorText)
strcpy(config->color, config->logo.color);
else
config->color[0] = '\0';
}
static void defaultConfig(FFconfig* config)
{
config->color[0] = '\0';
config->logo_seperator = 4;
config->offsetx = 0;
config->titleLength = 20; // This is overwritten by ffPrintTitle
@@ -184,42 +87,24 @@ static void defaultConfig(FFconfig* config)
config->recache = false;
}
static FILE* createStructureFile(const char* filename)
static bool parseBoolean(const char* str)
{
FILE* f = fopen(filename, "wr");
fputs(
"Title\n"
"Seperator\n"
"OS\n"
"Host\n"
"Kernel\n"
"Uptime\n"
"Packages\n"
"Shell\n"
"Resolution\n"
"DesktopEnvironment\n"
"Theme\n"
"Icons\n"
"Font\n"
"Terminal\n"
"CPU\n"
"GPU\n"
"Memory\n"
"Disk\n"
"Battery\n"
"Locale\n"
"Break\n"
"Colors\n"
,f);
fseek(f, 0, SEEK_SET);
return f;
return
strcasecmp(str, "true") == 0 ||
strcasecmp(str, "yes") == 0 ||
strcasecmp(str, "1") == 0
;
}
static void parseLine(FFinstance* instance, const char* line)
static void parseStructureCommand(FFinstance* instance, FFdata* data, const char* line)
{
const char* setValue = ffValuestoreGet(&data->valuestore, line);
if(setValue != NULL)
{
ffPrintCustom(instance, line, setValue);
return;
}
if(strcasecmp(line, "break") == 0)
ffPrintBreak(instance);
else if(strcasecmp(line, "title") == 0)
@@ -268,57 +153,272 @@ static void parseLine(FFinstance* instance, const char* line)
ffPrintError(instance, line, "<no implementaion provided>");
}
static void parseStructureFile(FFinstance* instance)
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value)
{
char configFolder[256];
strcpy(configFolder, instance->state.passwd->pw_dir);
strcat(configFolder, "/.config");
mkdir(configFolder, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a config folder but whow knews
strcat(configFolder, "/fastfetch/");
mkdir(configFolder, S_IRWXU | S_IRGRP | S_IROTH);
char valueDir[256];
strcpy(valueDir, configFolder);
strcat(valueDir, "values/");
mkdir(valueDir, S_IRWXU | S_IRGRP | S_IROTH);
char structureFileName[256];
strcpy(structureFileName, configFolder);
strcat(structureFileName, "structure");
FILE* structureFile;
if(access(structureFileName, F_OK) != 0)
structureFile = createStructureFile(structureFileName);
else
structureFile = fopen(structureFileName, "r");
char* line = NULL;
size_t len;
ssize_t read;
while ((read = getline(&line, &len, structureFile)) != -1)
if(strcasecmp(key, "-h") == 0 || strcasecmp(key, "--help") == 0)
{
if(line[read - 1] == '\n')
line[read - 1] = '\0';
if(value == NULL)
printHelp();
else
printCommandHelp(value);
ffTrimTrailingWhitespace(line);
if(!ffPrintCustomValue(instance, line))
parseLine(instance, line);
exit(0);
}
else if(strcasecmp(key, "-v") == 0 || strcasecmp(key, "--version") == 0)
{
puts(FASTFETCH_PROJECT_NAME" "FASTFETCH_PROJECT_VER);
exit(0);
}
else if(strcasecmp(key, "--list-logos") == 0)
{
ffListLogos();
exit(0);
}
else if(strcasecmp(key, "--print-logos") == 0)
{
ffPrintLogos(instance->config.colorLogo);
exit(0);
}
else if(strcasecmp(key, "--print-default-config") == 0)
{
puts(FASTFETCH_DEFAULT_CONFIG);
exit(0);
}
else if(strcasecmp(key, "--show-errors") == 0)
{
if(value == NULL)
instance->config.showErrors = true;
else
instance->config.showErrors = parseBoolean(value);
}
else if(strcasecmp(key, "-l") == 0 || strcasecmp(key, "--logo") == 0)
{
if(value == NULL)
{
printf("Error: usage: %s <logo>\n", key);
exit(41);
}
free(line);
fclose(structureFile);
strcpy(data->logoName, value);
}
else if(strcasecmp(key, "--color-logo") == 0)
{
if(value == NULL)
instance->config.colorLogo = true;
else
instance->config.colorLogo = parseBoolean(value);
}
else if(strcasecmp(key, "-c") == 0 || strcasecmp(key, "--color") == 0)
{
if(value == NULL)
{
printf("Error: usage: %s <color>\n", key);
exit(42);
}
size_t len = strlen(value);
if(len > 28)
{
printf("Error: max color string length is 28, %zu given\n", len);
exit(43);
}
sprintf(instance->config.color, "\033[%sm", value);
}
else if(strcasecmp(key, "-s") == 0 || strcasecmp(key, "--seperator") == 0)
{
if(value == NULL)
{
printf("Error: usage: %s <width>\n", key);
exit(44);
}
if(sscanf(value, "%hd", &instance->config.logo_seperator) != 1)
{
printf("Error: couldn't parse %s to uint16_t\n", value);
exit(45);
}
}
else if(strcasecmp(key, "-x") == 0 || strcasecmp(key, "--offsetx") == 0)
{
if(value == NULL)
{
printf("Error: usage: %s <offset>\n", key);
exit(46);
}
if(sscanf(value, "%hi", &instance->config.offsetx) != 1)
{
printf("Error: couldn't parse %s to int16_t\n", value);
exit(47);
}
}
else if(strcasecmp(key, "--structure") == 0)
{
if(value == NULL)
{
printf("Error: usage: %s <structure>\n", key);
exit(46);
}
strcpy(data->structure, value);
}
else if(strcasecmp(key, "--set") == 0)
{
if(value == NULL)
{
printf("Error: usage: %s <key=value>\n", key);
exit(47);
}
char* seperator = strchr(value, '=');
*seperator = '\0';
ffValuestoreSet(&data->valuestore, value, seperator + 1);
}
else if(strcasecmp(key, "-r") == 0 || strcasecmp(key, "--recache") == 0)
{
if(value == NULL)
instance->config.recache = true;
else
instance->config.recache = parseBoolean(value);
}
else
{
printf("Error: unknown option: %s\n", key);
exit(40);
}
}
int main(int argc, char** argv)
static void parseConfigFile(FFinstance* instance, FFdata* data)
{
char fileName[256];
const char* xdgConfig = getenv("XDG_CONFIG_HOME");
if(xdgConfig == NULL)
{
strcpy(fileName, instance->state.passwd->pw_dir);
strcat(fileName, "/.config");
}
else
{
strcpy(fileName, xdgConfig);
}
mkdir(fileName, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a config folder but whow knews
strcat(fileName, "/fastfetch/");
mkdir(fileName, S_IRWXU | S_IRGRP | S_IROTH);
strcat(fileName, "config.conf");
if(access(fileName, F_OK) != 0)
{
FILE* file = fopen(fileName, "w");
fputs(FASTFETCH_DEFAULT_CONFIG, file);
fclose(file);
return;
}
FILE* file = fopen(fileName, "r");
char* line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, file)) != -1) {
if(line[read - 1] == '\n')
line[read - 1] = '\0';
else
line[read] = '\0';
ffTrimTrailingWhitespace(line);
if(line[0] == '\0')
return;
char* firstIndex = strchr(line, ' ');
if(firstIndex == NULL)
{
parseOption(instance, data, line, NULL);
}
else
{
*firstIndex = '\0';
parseOption(instance, data, line, firstIndex + 1);
}
}
if(line)
free(line);
fclose(file);
}
static void parseArguments(FFinstance* instance, FFdata* data, int argc, const char** argv)
{
for(int i = 1; i < argc; i++)
{
if(i == argc - 1 || argv[i + 1][0] == '-')
{
parseOption(instance, data, argv[i], NULL);
}
else
{
parseOption(instance, data, argv[i], argv[i + 1]);
++i;
}
}
}
static void applyData(FFinstance* instance, FFdata* data)
{
//We must do this after parsing all options because of color options
if(data->logoName[0] == '\0')
ffLoadLogo(&instance->config);
else
ffLoadLogoSet(&instance->config, data->logoName);
//This must be done after loading the logo
if(instance->config.color[0] == '\0')
strcpy(instance->config.color, instance->config.logo.color);
}
static void run(FFinstance* instance, FFdata* data)
{
if(data->structure[0] == '\0')
strcpy(data->structure, FASTFETCH_DEFAULT_STRUCTURE);
char* remaining = data->structure;
char* colon = NULL;
while(true)
{
colon = strchr(remaining, ':');
if(colon != NULL)
*colon = '\0';
parseStructureCommand(instance, data, remaining);
if(colon != NULL)
remaining = colon + 1;
else
break;
}
}
int main(int argc, const char** argv)
{
FFinstance instance;
ffInitState(&instance.state);
defaultConfig(&instance.config);
parseArguments(argc, argv, &instance.config);
parseStructureFile(&instance);
return 0;
FFdata data;
ffValuestoreInit(&data.valuestore);
data.structure[0] = '\0'; //We use this in run to detect if a structure was set
data.logoName[0] = '\0';
parseConfigFile(&instance, &data);
parseArguments(&instance, &data, argc, argv);
applyData(&instance, &data);
run(&instance, &data);
ffValuestoreDelete(&data.valuestore);
}
-1
View File
@@ -67,7 +67,6 @@ void ffPrintError(FFinstance* instance, const char* key, const char* message);
void ffTrimTrailingWhitespace(char* buffer);
bool ffPrintCachedValue(FFinstance* instance, const char* key);
void ffPrintAndSaveCachedValue(FFinstance* instance, const char* key, const char* value);
bool ffPrintCustomValue(FFinstance* instance, const char* key);
//Logo functions
void ffLoadLogoSet(FFconfig* config, const char* logo);
-5
View File
@@ -2,11 +2,6 @@
void ffPrintBattery(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Battery"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
char model[256];
ffGetFileContent("/sys/class/power_supply/BAT0/model_name", model, sizeof(model));
-5
View File
@@ -15,11 +15,6 @@ static void printKDE()
void ffPrintDesktopEnvironment(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "DE"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
if(currentDesktop == NULL)
{
-5
View File
@@ -4,11 +4,6 @@
void ffPrintDisk(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Disk (/)"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
struct statvfs fs;
int ret = statvfs("/", &fs);
if(ret != 0)
-5
View File
@@ -16,11 +16,6 @@ static void parseFont(char* font, char* buffer)
void ffPrintFont(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Font"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
char plasma[256];
ffParsePropFileHome(instance, ".config/kdeglobals", "font=%[^\n]", plasma);
+2
View File
@@ -107,4 +107,6 @@ void ffPrintGPU(FFinstance* instance)
}
}
ffpci_cleanup(pacc);
dlclose(pci);
}
-2
View File
@@ -1,7 +1,5 @@
#include "fastfetch.h"
void ffPrintHost(FFinstance* instance)
{
if(ffPrintCachedValue(instance, "Host"))
-5
View File
@@ -2,11 +2,6 @@
void ffPrintIcons(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Icons"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
char plasma[256];
ffParsePropFileHome(instance, ".config/kdeglobals", "Theme=%[^\n]", plasma);
-5
View File
@@ -2,11 +2,6 @@
void ffPrintKernel(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Kernel"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
ffPrintLogoAndKey(instance, "Kernel");
puts(instance->state.utsname.release);
}
-5
View File
@@ -3,11 +3,6 @@
// Impl by: https://github.com/sam-barr/paleofetch/blob/b7c58a52c0de39b53c9b5f417889a5886d324bfa/paleofetch.c#L544
void ffPrintMemory(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Memory"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
FILE* meminfo = fopen("/proc/meminfo", "r");
if(meminfo == NULL) {
ffPrintError(instance, "Memory", "fopen(\"/proc/meminfo\", \"r\") == NULL");
-5
View File
@@ -33,11 +33,6 @@ static void printPacmanPackages()
void ffPrintPackages(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Packages"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
ffPrintLogoAndKey(instance, "Packages");
printPacmanPackages();
putchar('\n');
-2
View File
@@ -1,7 +1,5 @@
#include "fastfetch.h"
void ffPrintShell(FFinstance* instance)
{
if(ffPrintCachedValue(instance, "Shell"))
-7
View File
@@ -1,7 +1,5 @@
#include "fastfetch.h"
void printTerminalName(FFinstance* instance, const char* pid)
{
char file[256];
@@ -58,11 +56,6 @@ void printTerminalName(FFinstance* instance, const char* pid)
void ffPrintTerminal(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Terminal"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
char ppid[256];
sprintf(ppid, "%i", getppid());
printTerminalName(instance, ppid);
-5
View File
@@ -2,11 +2,6 @@
void ffPrintTheme(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Theme"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
char plasma[256];
ffParsePropFileHome(instance, ".config/kdeglobals", "Name=%[^\n]", plasma);
-5
View File
@@ -2,11 +2,6 @@
void ffPrintTitle(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Title"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
char hostname[256];
gethostname(hostname, 256);
-5
View File
@@ -2,11 +2,6 @@
void ffPrintUptime(FFinstance* instance)
{
#ifdef FASTFETCH_BUILD_FLASHFETCH
if(ffPrintCustomValue(instance, "Uptime"))
return;
#endif // FASTFETCH_BUILD_FLASHFETCH
ffPrintLogoAndKey(instance, "Uptime");
if(instance->state.sysinfo.uptime < 60)
+59
View File
@@ -0,0 +1,59 @@
#include <stdint.h>
#include <malloc.h>
#include <string.h>
#include "FFvaluestore.h"
void ffValuestoreInit(FFvaluestore* vs)
{
vs->capacity = 32;
vs->pairs = calloc(vs->capacity, sizeof(FFvaluestorePair));
vs->size = 0;
}
void ffValuestoreSet(FFvaluestore* vs, const char* name, const char* value)
{
for(uint32_t i = 0; i < vs->size; i++)
{
if(strcasecmp(vs->pairs[i].name, name) == 0)
{
strcpy(vs->pairs[i].value, value);
return;
}
}
if(vs->size == vs->capacity)
{
FFvaluestorePair* pairs = (FFvaluestorePair*) calloc(vs->capacity * 2, sizeof(FFvaluestorePair));
memcpy(pairs, vs->pairs, sizeof(FFvaluestorePair) * vs->size);
free(vs->pairs);
vs->pairs = pairs;
vs->capacity *= 2;
}
strcpy(vs->pairs[vs->size].name, name);
strcpy(vs->pairs[vs->size].value, value);
++vs->size;
}
const char* ffValuestoreGet(FFvaluestore* vs, const char* name)
{
for(uint32_t i = 0; i < vs->size; i++)
{
if(strcasecmp(vs->pairs[i].name, name) == 0)
return vs->pairs[i].value;
}
return NULL;
}
bool ffValuestoreContains(FFvaluestore* vs, const char* name)
{
return ffValuestoreGet(vs, name) != NULL;
}
void ffValuestoreDelete(FFvaluestore* vs)
{
free(vs->pairs);
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef FASTFETCH_INCLUDED_FFVALUESTORE
#define FASTFETCH_INCLUDED_FFVALUESTORE
#include <stdbool.h>
typedef struct FFvaluestorePair
{
char name[32];
char value[1024];
} FFvaluestorePair;
typedef struct FFvaluestore
{
FFvaluestorePair* pairs;
uint32_t size;
uint32_t capacity;
} FFvaluestore;
void ffValuestoreInit(FFvaluestore* vs);
void ffValuestoreSet(FFvaluestore* vs, const char* name, const char* value);
const char* ffValuestoreGet(FFvaluestore* vs, const char* name);
bool ffValuestoreContains(FFvaluestore* vs, const char* name);
void ffValuestoreDelete(FFvaluestore* vs);
#endif