summaryrefslogtreecommitdiff
path: root/src/config.c
blob: a8c83d22ac67deba4cc071fdfc54b474b231e3c5 (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 = 120;
   47   char buf[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     // Temp variable to store the text between index start and index end
   79     strncpy(tmp_line, &buf[start], end - start + 1);
   80     // Make sure it has a trailing newline so sscanf works
   81     strcat(tmp_line, "\n");
   82 
   83     // Parse the line into temp variables
   84     sscanf(tmp_line, "%s %s", key, value);
   85 
   86     // Allocate heap memory for values since these need to persist.
   87     // Note that here we are using the temp variables to establish string
   88     // length for when we allocate heap memory.
   89     conf->keys[i] = malloc(sizeof(char) * strlen(key));
   90     conf->values[i] = malloc(sizeof(char) * strlen(value));
   91 
   92     // Copy in the temp values
   93     strcpy(conf->keys[i], key);
   94     strcpy(conf->values[i], value);
   95 
   96     // Increment the counter for tracking keys and values in their respective
   97     // arrays
   98     i++;
   99   }
  100 
  101   fclose(f);
  102 
  103   return 0;
  104 }
  105 
  106 
  107 /**
  108  * Destructor for config struct.
  109  *
  110  * @param conf Config_t pointer to be freed from memory
  111  */
  112 void config_free(config_t* conf) {
  113   for(int i = 0; i < conf->count; i++) {
  114     free(conf->keys[i]);
  115     free(conf->values[i]);
  116   }
  117   free(conf->keys);
  118   free(conf->values);
  119 }
  120 
  121 
  122 /**
  123  * Performs a line count of valid lines in the specified config file. This is
  124  * useful for determining the size of an array to store keys or values in.
  125  * A valid line is considered to be a line that is not empty or commented out.
  126  *
  127  * @param path Path to the config file to be parsed
  128  *
  129  * @return int Count of lines that are not commented out or empty
  130  */
  131 int config_valid_line_count(char* path) {
  132   int count = 0;
  133 
  134   FILE* f;
  135   f = fopen(path, "r");
  136 
  137   int len = 120;
  138   char buf[len];
  139 
  140   while(fgets(buf, len, f) != NULL) {
  141     int start = 0;
  142 
  143     // Find the first char
  144     while(buf[start] == ' ') { start++; }
  145 
  146     // Confirm the line is not a comment or empty
  147     if(buf[start] != '#' && buf[start] != '\n') { count++; }
  148   }
  149   fclose(f);
  150 
  151   return count;
  152 }
  153 
  154 
  155 /**
  156  * Checks the configuration struct for the given key's value.
  157  *
  158  * @param conf Config_t instance pointer containing keys and values to check
  159  * @param key Key to check if exists
  160  *
  161  * @return int Key value exists (1) or not (0)
  162  */
  163 int config_isset(config_t* conf, char* key) {
  164   for(int i = 0; i < conf->count; i++) {
  165     if(strcmp(conf->keys[i], key) == 0) {
  166       return 1;
  167     }
  168   }
  169   return 0;
  170 }
  171 
  172 /**
  173  * TODO
  174  */
  175 char* config_get(config_t* conf, char* key) {
  176   for(int i = 0; i < conf->count; i++) {
  177     if(strcmp(conf->keys[i], key) == 0) {
  178       return conf->values[i];
  179     }
  180   }
  181   return NULL;
  182 }
  183 
  184 
  185 /**
  186  * Parses one line of the config file. Strips illegal characters first, then
  187  * sets key to the text on the left of the equals sign and value to the text on
  188  * the right.
  189  *
  190  * string line - Config file line to be parsed and added to the config object
  191  *
  192  * return int Success or failure
  193  */
  194 // int config::parse_line( string line ) {
  195 //   // The two vars that will be appended to the key value vector
  196 //   string key;
  197 //   string value;
  198 //   int split;
  199 // 
  200 //   // Clean spaces and other illegal chars
  201 //   string clean_line;
  202 //   for( int i = 0; i < line.length(); i++ ) {
  203 //     if( line[i] == ' ' ) {
  204 //       // Ignore, it's a space
  205 //       continue;
  206 //     } else {
  207 //       clean_line += line[i];
  208 //     }
  209 //   }
  210 // 
  211 //   // Line was empty, skip 'er
  212 //   if( clean_line.length() == 0 ) { return 0; }
  213 // 
  214 //   // One character at a time
  215 //   for( int i = 0; i < clean_line.length(); i++ ) {
  216 //     if( clean_line[i] == '=' ) {
  217 //       // Set the key
  218 //       key = clean_line.substr( 0, i );
  219 //       split = i;
  220 //       break;
  221 //     }
  222 //   }
  223 //   // Set the value
  224 //   value = clean_line.substr( split + 1, clean_line.length() );
  225 // 
  226 //   // Append to class global values
  227 //   values.push_back( key );
  228 //   values.push_back( value );
  229 // 
  230 //   // Success!
  231 //   return 0;
  232 // }

Generated by cgit