summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ball <nullspoon@oper.io>2017-12-31 15:19:01 -0700
committerAaron Ball <nullspoon@oper.io>2017-12-31 15:19:01 -0700
commit67009321e9aa39035eade6321a633c4111909b65 (patch)
tree4d63319241b6c02822cd5e916382c0488264d281
parent4b5f62be49769842ce2e91cf6455c219280e31fc (diff)
downloadluminous-67009321e9aa39035eade6321a633c4111909b65.tar.gz
luminous-67009321e9aa39035eade6321a633c4111909b65.tar.xz
Initial commit of config code
Config code supports loading of a specified configuration file, delimited by the '=' character. Code dynamically allocates memory in heap and thus the config_free function must be called when done with the config object. This adds the constructor, load, getter, dump, and descructor functions for the config struct. This code passes valgrind tests with no memory leaks (assuming the config_free destructor is called).
-rw-r--r--Makefile2
-rw-r--r--src/config.c231
-rw-r--r--src/config.h37
3 files changed, 270 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index f4b2ef8..b390334 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,8 @@ INITDIR=/etc/rc.d
all:
cc $(CCOPTS) $(DBG) src/main.c -o luminous
+ if [ ! -d obj ]; then mkdir obj; fi
+ cc $(CCOPTS) $(DBG) src/config.c -c -o obj/config.o
install:
install -D luminous ${DESTDIR}/${BINDIR}/luminous
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..1ff9a2b
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,231 @@
+/**
+ * Copyright (C) 2017 Aaron Ball <nullspoon@oper.io>
+ *
+ * Luminous is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Luminous is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with noteless. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "config.h"
+
+
+/**
+ * config_new:
+ * @c Config struct to initialize
+ * @path Path to the config file to initialize from (only used by config_load)
+ *
+ * Config struct constructor.
+ *
+ * Returns success (0) or failure (-1). Failure occurs when specified config
+ * file is not accessible or could not be found.
+ */
+int config_new(struct config* c, const char* path) {
+ FILE* fd;
+
+ // Check if the config file exists
+ fd = fopen(path, "r");
+ if(!fd)
+ return -1;
+ fclose(fd);
+
+ c->count = 0;
+ c->path = path;
+ c->keys = malloc(0);
+ c->vals = malloc(0);
+ return 0;
+}
+
+
+/**
+ * line_get_key:
+ * @line Line to search for key in
+ * @start Pointer to integer holding substring start index
+ * @end Pointer to integer holding substring end index
+ *
+ * Searches the specified string for a key (preceeding an '=' delimiter).
+ *
+ * Returns Length of found key, otherwise -1.
+ */
+int line_get_key(char* line, int* start, int* end) {
+ *start = 0;
+ *end = 0;
+
+ // Find beginning of key, allowing for preceeding whitespace
+ while(line[*start] == ' ' && line[*start] != '\0')
+ *start = *start + 1;
+
+ // Return error if no non-whitespace text was found
+ if(line[*start] == '\0')
+ return -1;
+
+ *end = *start;
+
+ // Find the end of the key
+ while(line[*end] != ' ' && line[*end] != '=' && line[*end] != '\0')
+ *end = *end + 1;
+
+ return *end - *start;
+}
+
+
+/**
+ * line_get_val:
+ * @line Line to search for value in
+ * @start Pointer to integer holding substring start index
+ * @end Pointer to integer holding substring end index
+ *
+ * Searches the specified string for a value (following an '=' delimiter).
+ *
+ * Returns Length of found value, otherwise -1.
+ */
+int line_get_val(char* line, int* start, int* end) {
+ *start = 0;
+ *end = 0;
+
+ // Find beginning of key, allowing for preceeding whitespace
+ // Set the start cursor to the first non-whitespace character after the
+ // equals sign
+ while(line[*start] != '=' && line[*start] != '\0')
+ *start = *start + 1;
+
+ // Advance one to pass the equals sign
+ *start = *start + 1;
+
+ // A seperate loop to handle leading whitespace. Having this outside of the
+ // previous loop prevents us from allowing for multiple contiguous equals
+ // signs
+ while(line[*start] == ' ')
+ *start = *start + 1;
+
+ // Return error if no equals sign was found
+ if(line[*start] == '\0')
+ return -1;
+
+ // Find the end of the string, not including the newline char if one is
+ // present (this is why we don't use strlen, becuase it includes the index of
+ // the newline char if one is present)
+ while(line[*end] != '\n' && line[*end] != '\0')
+ *end = *end + 1;
+
+ return *end - *start;
+}
+
+
+/**
+ * config_load:
+ * @c Config struct to load config data into
+ *
+ * Returns number of config items found in the config file
+ */
+int config_load(struct config* c) {
+ // Values for tracking config line component start and end indexes
+ int keystart = 0, keyend = 0, keylen = 0;
+ int valstart = 0, valend = 0, vallen = 0;
+ char buf[512]; // Config line buffer
+ FILE* fd; // Config file descriptor
+
+ fd = fopen(c->path, "r");
+
+ while(fgets(buf, 512, fd) != NULL) {
+ c->count++;
+
+ // Allocate array space for new keys and values
+ c->keys = realloc(c->keys, sizeof(char*) * c->count);
+ c->vals = realloc(c->vals, sizeof(char*) * c->count);
+
+ // Get the key start and end index
+ keylen = line_get_key(buf, &keystart, &keyend);
+ // Allocate space for new key
+ c->keys[c->count - 1] = malloc(keylen + 1);
+ // Copy the key into the new memory
+ strncpy(c->keys[c->count - 1], &buf[keystart], keylen);
+ // Dont' forget the null byte!
+ c->keys[c->count - 1][keylen] = '\0';
+
+ // Do the exact same thing for the value
+ vallen = line_get_val(buf, &valstart, &valend);
+ c->vals[c->count - 1] = malloc(vallen + 1);
+ strncpy(c->vals[c->count - 1], &buf[valstart], vallen);
+ c->vals[c->count - 1][vallen] = '\0';
+
+ // Reset our index variables
+ keystart = 0, keyend = 0, keylen = 0;
+ valstart = 0, valend = 0, vallen = 0;
+ }
+
+ fclose(fd);
+
+ return c->count;
+}
+
+
+/**
+ * config_dump:
+ * @c Config struct to dump
+ * @fd File descriptor to print dump text to. If NULL, prints to stdout
+ *
+ * Dumps the provided config struct to the specified file descriptor.
+ */
+void config_dump(struct config* c, FILE* fd) {
+ int i = 0;
+ if(!fd)
+ fd = stdout;
+
+ while(i < c->count) {
+ fprintf(fd, "%d %s %s\n", i, c->keys[i], c->vals[i]);
+ i++;
+ }
+}
+
+
+/**
+ * config_get:
+ * @c Config struct to search for a matching key
+ * @key Config key to find value for
+ * @out Output buffer to copy value to
+ *
+ * Returns Status integer (0 == key found, -1 == key not found)
+ */
+int config_get(struct config* c, char* key, char* out) {
+ int i = 0;
+
+ while(i < c->count) {
+ // Copy value for matching key to output buffer
+ if(strcmp(c->keys[i], key) == 0) {
+ strcpy(out, c->vals[i]);
+ return 0;
+ }
+ i++;
+ }
+
+ // If we reach this point, no matching keys were found
+ return -1;
+}
+
+
+/**
+ * config_free:
+ * @c Config struct to free
+ */
+int config_free(struct config* c) {
+ while(c->count > 0) {
+ // Free the corresponding
+ free(c->keys[c->count - 1]);
+ free(c->vals[c->count - 1]);
+ c->count--;
+ }
+
+ // Free the array space
+ free(c->keys);
+ free(c->vals);
+
+ return 0;
+}
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..247efb3
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2017 Aaron Ball <nullspoon@oper.io>
+ *
+ * Luminous is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Luminous is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with noteless. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct config {
+ const char* path;
+ int count; // Number of config entries
+ char** keys;
+ char** vals;
+};
+
+
+int config_new(struct config*, const char*);
+
+int config_load(struct config*);
+
+void config_dump(struct config*, FILE*);
+
+int config_get(struct config*, char*, char*);
+
+int config_free(struct config*);

Generated by cgit