wmi

git clone git://oldgit.suckless.org/wmi/
Log | Files | Refs | LICENSE

loader.cpp (4609B)


      1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us>
      2 // See LICENSE for license details.
      3 
      4 extern "C" {
      5 #include <sys/stat.h>
      6 #include <sys/types.h>
      7 }
      8 
      9 #include <fstream>
     10 #include <iostream>
     11 #include <sstream>
     12 
     13 #include "loader.h"
     14 #include "util.h"
     15 
     16 Loader::Loader() {
     17 }
     18 
     19 Loader::~Loader() {
     20 }
     21 
     22 bool Loader::load(MSettings *settings, string path,
     23                   bool suppressWarning, bool caseSensitive)
     24 {
     25 
     26     ifstream is(path.c_str());
     27 
     28     if (!is) {
     29         if (!suppressWarning) {
     30             cerr << "wmi[W " << Util::timestamp()
     31                 << "]: cannot open/read configuration file '"
     32                 << path << "', skipping" << endl;
     33         }
     34         return false;
     35     }
     36 
     37     string key = "";
     38     string value = "";
     39     string buf = "";
     40     bool comment = false;
     41     bool ignoreWhitespaces = true;
     42     bool escape = false; // provides using {#, ", =, \n} characters
     43     int c;
     44 
     45     while (!is.eof()) {
     46 
     47         c = is.get();
     48 
     49         switch (c) {
     50         case ' ':
     51         case '\t':
     52             if (!comment && !ignoreWhitespaces) {
     53                 buf += c;
     54             }
     55             escape = false;
     56             break;
     57         case '"': // toggle ignore whitespace/or escape this character
     58             if (!comment) {
     59                 if (escape) {
     60                     buf += c;
     61                 }
     62                 else {
     63                     ignoreWhitespaces = !ignoreWhitespaces;
     64                 }
     65             }
     66             escape = false;
     67             break;
     68         case '\\': // escape
     69             if (!comment) {
     70                 if (escape) {
     71                     buf += c;
     72                     escape = false;
     73                 }
     74                 else {
     75                     escape = true;
     76                 }
     77             }
     78             break;
     79         case '#': // comment
     80             if (escape) {
     81                 buf += c;
     82             }
     83             else {
     84                 comment = true;
     85             }
     86             escape = false;
     87             break;
     88         case '=':
     89             if (!comment) {
     90                 if (escape) {
     91                     buf += c;
     92                 }
     93                 else {
     94                     key = buf;
     95                     buf = "";
     96                 }
     97             }
     98             escape = false;
     99             break;
    100         case '\n':
    101 
    102 #define ENDLINE \
    103             if (!escape) { \
    104                 comment = false; \
    105                 ignoreWhitespaces = true; \
    106                 value = buf; \
    107                 if ((key != "") && (value != "")) { \
    108                     value = buf; \
    109                     if (caseSensitive) { \
    110                         (*settings)[key] = value; \
    111                     } \
    112                     else { \
    113                         (*settings)[Util::lowerCase(key)] = value; \
    114                     } \
    115                 } \
    116                 buf = key = value = ""; \
    117             } \
    118             escape = false; \
    119             break; \
    120 	    
    121             ENDLINE
    122 	case EOF :
    123 	    ENDLINE
    124         default:
    125             if (!comment) {
    126                 buf += c;
    127             }
    128             escape = false;
    129             break;
    130         }
    131     }
    132     is.close();
    133 
    134     return true;
    135 }
    136 
    137 bool Loader::saveSettings(MSettings *settings, string path) {
    138 
    139     ostringstream content; 
    140 
    141     for (MSettings::iterator it = settings->begin();
    142             it != settings->end(); it++)
    143     {
    144         string value = Util::encodeEscapes((*it).second);
    145         if (Util::containsWhitespaces(value)) {
    146             content << (*it).first << "=\"" << value << "\"" << endl;
    147         }
    148         else {
    149             content << (*it).first << "=" << value << endl;
    150         }
    151     }
    152 
    153     return saveFile(path, content.str());
    154 }
    155 
    156 bool Loader::saveFile(string path, string content) {
    157 
    158     string dir = Util::canonicalDir(path);
    159     if (!Util::exists(dir.c_str())) {
    160 
    161         mode_t mode = umask(0);
    162         mode = (mode ^ (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IWUSR | S_IXUSR;
    163         if (mkdir(dir.c_str(), mode) != 0) {
    164             cerr << "wmi[W " << Util::timestamp()
    165                 << "]: cannot create non-existing directory '"
    166                 << dir << "', skipping" << endl;
    167         }
    168     }
    169 
    170     ofstream os(path.c_str());
    171 
    172     if (!os) {
    173         cerr << "wmi[W " << Util::timestamp()
    174              << "]: cannot open/write configuration file '"
    175              << path << "', skipping" << endl;
    176         return false;
    177     }
    178 
    179     os << content;
    180     os.close();
    181 
    182     return true;
    183 
    184 }
    185 
    186 void Loader::print(MSettings *settings) {
    187 
    188     MSettings::iterator it = settings->begin();
    189     while (it != settings->end()) {
    190         cout << (*it).first << "=" << (*it).second << endl;
    191         it++;
    192     }
    193 }