summaryrefslogtreecommitdiff
path: root/src/config.c
blob: 1ff9a2b69cbe76b43fdd8a9a8cc4012ac3c29d28 (plain)
    1 /**
    2  * Copyright (C) 2017 Aaron Ball <nullspoon@oper.io>
    3  *
    4  * Luminous is free software: you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation, either version 3 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * Luminous is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with noteless.  If not, see <http://www.gnu.org/licenses/>.
   16  */
   17 #include "config.h"
   18 
   19 
   20 /**
   21  * config_new:
   22  * @c    Config struct to initialize
   23  * @path Path to the config file to initialize from (only used by config_load)
   24  *
   25  * Config struct constructor.
   26  *
   27  * Returns success (0) or failure (-1). Failure occurs when specified config
   28  * file is not accessible or could not be found.
   29  */
   30 int config_new(struct config* c, const char* path) {
   31   FILE* fd;
   32 
   33   // Check if the config file exists
   34   fd = fopen(path, "r");
   35   if(!fd)
   36     return -1;
   37   fclose(fd);
   38 
   39   c->count = 0;
   40   c->path = path;
   41   c->keys = malloc(0);
   42   c->vals = malloc(0);
   43   return 0;
   44 }
   45 
   46 
   47 /**
   48  * line_get_key:
   49  * @line  Line to search for key in
   50  * @start Pointer to integer holding substring start index
   51  * @end   Pointer to integer holding substring end index
   52  *
   53  * Searches the specified string for a key (preceeding an '=' delimiter).
   54  *
   55  * Returns Length of found key, otherwise -1.
   56  */
   57 int line_get_key(char* line, int* start, int* end) {
   58   *start = 0;
   59   *end   = 0;
   60 
   61   // Find beginning of key, allowing for preceeding whitespace
   62   while(line[*start] == ' ' && line[*start] != '\0')
   63     *start = *start + 1;
   64 
   65   // Return error if no non-whitespace text was found
   66   if(line[*start] == '\0')
   67     return -1;
   68 
   69   *end = *start;
   70 
   71   // Find the end of the key
   72   while(line[*end] != ' ' && line[*end] != '=' && line[*end] != '\0')
   73     *end = *end + 1;
   74 
   75   return *end - *start;
   76 }
   77 
   78 
   79 /**
   80  * line_get_val:
   81  * @line  Line to search for value in
   82  * @start Pointer to integer holding substring start index
   83  * @end   Pointer to integer holding substring end index
   84  *
   85  * Searches the specified string for a value (following an '=' delimiter).
   86  *
   87  * Returns Length of found value, otherwise -1.
   88  */
   89 int line_get_val(char* line, int* start, int* end) {
   90   *start = 0;
   91   *end   = 0;
   92 
   93   // Find beginning of key, allowing for preceeding whitespace
   94   // Set the start cursor to the first non-whitespace character after the
   95   // equals sign
   96   while(line[*start] != '=' && line[*start] != '\0')
   97     *start = *start + 1;
   98 
   99   // Advance one to pass the equals sign
  100   *start = *start + 1;
  101 
  102   // A seperate loop to handle leading whitespace. Having this outside of the
  103   // previous loop prevents us from allowing for multiple contiguous equals
  104   // signs
  105   while(line[*start] == ' ')
  106     *start = *start + 1;
  107 
  108   // Return error if no equals sign was found
  109   if(line[*start] == '\0')
  110     return -1;
  111 
  112   // Find the end of the string, not including the newline char if one is
  113   // present (this is why we don't use strlen, becuase it includes the index of
  114   // the newline char if one is present)
  115   while(line[*end] != '\n' && line[*end] != '\0')
  116     *end = *end + 1;
  117 
  118   return *end - *start;
  119 }
  120 
  121 
  122 /**
  123  * config_load:
  124  * @c Config struct to load config data into
  125  *
  126  * Returns number of config items found in the config file
  127  */
  128 int config_load(struct config* c) {
  129   // Values for tracking config line component start and end indexes
  130   int keystart = 0, keyend = 0, keylen = 0;
  131   int valstart = 0, valend = 0, vallen = 0;
  132   char buf[512];  // Config line buffer
  133   FILE* fd;       // Config file descriptor
  134 
  135   fd = fopen(c->path, "r");
  136 
  137   while(fgets(buf, 512, fd) != NULL) {
  138     c->count++;
  139 
  140     // Allocate array space for new keys and values
  141     c->keys = realloc(c->keys, sizeof(char*) * c->count);
  142     c->vals = realloc(c->vals, sizeof(char*) * c->count);
  143 
  144     // Get the key start and end index
  145     keylen = line_get_key(buf, &keystart, &keyend);
  146     // Allocate space for new key
  147     c->keys[c->count - 1] = malloc(keylen + 1);
  148     // Copy the key into the new memory
  149     strncpy(c->keys[c->count - 1], &buf[keystart], keylen);
  150     // Dont' forget the null byte!
  151     c->keys[c->count - 1][keylen] = '\0';
  152 
  153     // Do the exact same thing for the value
  154     vallen = line_get_val(buf, &valstart, &valend);
  155     c->vals[c->count - 1] = malloc(vallen + 1);
  156     strncpy(c->vals[c->count - 1], &buf[valstart], vallen);
  157     c->vals[c->count - 1][vallen] = '\0';
  158 
  159     // Reset our index variables
  160     keystart = 0, keyend = 0, keylen = 0;
  161     valstart = 0, valend = 0, vallen = 0;
  162   }
  163 
  164   fclose(fd);
  165 
  166   return c->count;
  167 }
  168 
  169 
  170 /**
  171  * config_dump:
  172  * @c  Config struct to dump
  173  * @fd File descriptor to print dump text to. If NULL, prints to stdout
  174  *
  175  * Dumps the provided config struct to the specified file descriptor.
  176  */
  177 void config_dump(struct config* c, FILE* fd) {
  178   int i = 0;
  179   if(!fd)
  180     fd = stdout;
  181 
  182   while(i < c->count) {
  183     fprintf(fd, "%d %s   %s\n", i, c->keys[i], c->vals[i]);
  184     i++;
  185   }
  186 }
  187 
  188 
  189 /**
  190  * config_get:
  191  * @c   Config struct to search for a matching key
  192  * @key Config key to find value for
  193  * @out Output buffer to copy value to
  194  *
  195  * Returns Status integer (0 == key found, -1 == key not found)
  196  */
  197 int config_get(struct config* c, char* key, char* out) {
  198   int i = 0;
  199 
  200   while(i < c->count) {
  201     // Copy value for matching key to output buffer
  202     if(strcmp(c->keys[i], key) == 0) {
  203       strcpy(out, c->vals[i]);
  204       return 0;
  205     }
  206     i++;
  207   }
  208 
  209   // If we reach this point, no matching keys were found
  210   return -1;
  211 }
  212 
  213 
  214 /**
  215  * config_free:
  216  * @c Config struct to free
  217  */
  218 int config_free(struct config* c) {
  219   while(c->count > 0) {
  220     // Free the corresponding 
  221     free(c->keys[c->count - 1]);
  222     free(c->vals[c->count - 1]);
  223     c->count--;
  224   }
  225 
  226   // Free the array space
  227   free(c->keys);
  228   free(c->vals);
  229 
  230   return 0;
  231 }

Generated by cgit