summaryrefslogtreecommitdiff
path: root/src/config.c
blob: c3509cc750fc7fee66e138138d36b3a6d4483678 (plain)
    1 /**
    2  * A class to help with parsing standard config files
    3  *
    4  * Copyright (C) 2014 Aaron Ball <nullspoon@iohq.net>
    5  *
    6  * Noteless is free software: you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License as published by
    8  * the Free Software Foundation, either version 3 of the License, or
    9  * (at your option) any later version.
   10  *
   11  * Noteless is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with noteless.  If not, see <http://www.gnu.org/licenses/>.
   18  */
   19 #include "config.h"
   20 
   21 /**
   22  * Constructor for the config class. Reads config file into a vector (one line
   23  * per index), then parses each line into a vector size 2x.
   24  *
   25  * @param const char* p Path to the config file to be read in
   26  */
   27 int config_new(config_t* conf, char* p) {
   28   // TODO
   29   strcpy(conf->path, p);
   30 
   31   conf->count = config_valid_line_count(p);
   32 
   33   conf->keys = malloc(sizeof(char*) * conf->count);
   34   conf->values = malloc(sizeof(char*) * conf->count);
   35 
   36   FILE* f;
   37   f = fopen(conf->path, "r");
   38 
   39   // Verify the file could be opened
   40   if(!f) {
   41     printf("Could not open config file at %s.\n", conf->path);
   42     return -1;
   43   }
   44 
   45   // Set the maximum read width and read buffer array
   46   int len = config_line_len;
   47   char buf[config_line_len] = "";
   48 
   49   char key[32];
   50   char value[256];
   51 
   52   int i = 0;
   53   while(fgets(buf, len, f) != NULL) {
   54     int start = 0;
   55     // This loop allows for lines to not start at the beginning
   56     while(buf[start] != '\0') {
   57       if(buf[start] != ' ') {
   58         break;
   59       } else {
   60         start++;
   61       }
   62     }
   63 
   64     // Skip all lines starting with a comment char
   65     if(buf[start] == '#') { continue; }
   66     // Skip empty lines
   67     if(buf[start] == '\n') { continue; }
   68 
   69     int end = start;
   70     while(buf[end] != '\0') {
   71       // This allows for inline comment chars.  The line ends when the first
   72       // comment char is found.
   73       if(buf[end] == '#' || buf[end] == '\n') { break; }
   74       end++;
   75     }
   76 
   77     //char tmp_line[end - start + 10];
   78     char tmp_line[config_line_len] = "";
   79     // Temp variable to store the text between index start and index end
   80     strncpy(tmp_line, &buf[start], end - start + 1);
   81     // Make sure it has a trailing newline so sscanf works
   82     strcat(tmp_line, "\n");
   83 
   84     // Parse the line into temp variables
   85     sscanf(tmp_line, "%s %s", key, value);
   86 
   87     // Allocate heap memory for values since these need to persist.
   88     // Note that here we are using the temp variables to establish string
   89     // length for when we allocate heap memory.
   90     conf->keys[i] = malloc(sizeof(char) * (strlen(key) + 1));
   91     conf->values[i] = malloc(sizeof(char) * (strlen(value) + 1));
   92 
   93     // Copy in the temp values
   94     strcpy(conf->keys[i], key);
   95     strcpy(conf->values[i], value);
   96 
   97     // Increment the counter for tracking keys and values in their respective
   98     // arrays
   99     i++;
  100   }
  101 
  102   fclose(f);
  103 
  104   return 0;
  105 }
  106 
  107 
  108 /**
  109  * Destructor for config struct.
  110  *
  111  * @param conf Config_t pointer to be freed from memory
  112  */
  113 void config_free(config_t* conf) {
  114   for(int i = 0; i < conf->count; i++) {
  115     free(conf->keys[i]);
  116     free(conf->values[i]);
  117   }
  118   free(conf->keys);
  119   free(conf->values);
  120 }
  121 
  122 
  123 /**
  124  * Performs a line count of valid lines in the specified config file. This is
  125  * useful for determining the size of an array to store keys or values in.
  126  * A valid line is considered to be a line that is not empty or commented out.
  127  *
  128  * @param path Path to the config file to be parsed
  129  *
  130  * @return int Count of lines that are not commented out or empty
  131  */
  132 int config_valid_line_count(char* path) {
  133   int count = 0;
  134 
  135   FILE* f;
  136   f = fopen(path, "r");
  137 
  138   int len = config_line_len;
  139   char buf[config_line_len];
  140 
  141   while(fgets(buf, len, f) != NULL) {
  142     int start = 0;
  143 
  144     // Find the first char
  145     while(buf[start] == ' ') { start++; }
  146 
  147     // Confirm the line is not a comment or empty
  148     if(buf[start] != '#' && buf[start] != '\n') { count++; }
  149   }
  150   fclose(f);
  151 
  152   return count;
  153 }
  154 
  155 
  156 /**
  157  * Checks the configuration struct for the given key's value.
  158  *
  159  * @param conf Config_t instance pointer containing keys and values to check
  160  * @param key Key to check if exists
  161  *
  162  * @return int Key value exists (1) or not (0)
  163  */
  164 int config_isset(config_t* conf, char* key) {
  165   for(int i = 0; i < conf->count; i++) {
  166     if(strcmp(conf->keys[i], key) == 0) {
  167       return 1;
  168     }
  169   }
  170   return 0;
  171 }
  172 
  173 /**
  174  * TODO
  175  */
  176 char* config_get(config_t* conf, char* key) {
  177   for(int i = 0; i < conf->count; i++) {
  178     if(strcmp(conf->keys[i], key) == 0) {
  179       return conf->values[i];
  180     }
  181   }
  182   return NULL;
  183 }
  184 
  185 
  186 /**
  187  * Parses one line of the config file. Strips illegal characters first, then
  188  * sets key to the text on the left of the equals sign and value to the text on
  189  * the right.
  190  *
  191  * string line - Config file line to be parsed and added to the config object
  192  *
  193  * return int Success or failure
  194  */
  195 // int config::parse_line( string line ) {
  196 //   // The two vars that will be appended to the key value vector
  197 //   string key;
  198 //   string value;
  199 //   int split;
  200 // 
  201 //   // Clean spaces and other illegal chars
  202 //   string clean_line;
  203 //   for( int i = 0; i < line.length(); i++ ) {
  204 //     if( line[i] == ' ' ) {
  205 //       // Ignore, it's a space
  206 //       continue;
  207 //     } else {
  208 //       clean_line += line[i];
  209 //     }
  210 //   }
  211 // 
  212 //   // Line was empty, skip 'er
  213 //   if( clean_line.length() == 0 ) { return 0; }
  214 // 
  215 //   // One character at a time
  216 //   for( int i = 0; i < clean_line.length(); i++ ) {
  217 //     if( clean_line[i] == '=' ) {
  218 //       // Set the key
  219 //       key = clean_line.substr( 0, i );
  220 //       split = i;
  221 //       break;
  222 //     }
  223 //   }
  224 //   // Set the value
  225 //   value = clean_line.substr( split + 1, clean_line.length() );
  226 // 
  227 //   // Append to class global values
  228 //   values.push_back( key );
  229 //   values.push_back( value );
  230 // 
  231 //   // Success!
  232 //   return 0;
  233 // }

Generated by cgit