Config.cc revision 10447
1#include "Config.h" 2 3#include <fstream> 4 5#include "Assert.h" 6 7namespace LibUtil 8{ 9 Config::Config(const String& delimiter_, const String& comment_, const String& sentry_) 10 : mDelimiter(delimiter_), mComment(comment_), mSentry(sentry_) 11 {} 12 13 Config::Config(const Config& config_) 14 : StringMap(config_) 15 { 16 mDelimiter = config_.mDelimiter; 17 mComment = config_.mComment; 18 mSentry = config_.mSentry; 19 } 20 21 Config::~Config() 22 {} 23 24 Config* Config::clone() const 25 { 26 return new Config(*this); 27 } 28 29 void Config::readFile(const String& filename_) 30 { 31 std::ifstream fin(filename_.c_str()); 32 33 ASSERT(fin, "File not found: " + filename_); 34 fin >> (*this); 35 return; 36 } 37 38 void Config::readString(const String& str_) 39 { 40 String newString = str_; 41 newString.substitute(";", "\n"); 42 std::istringstream iss(newString, std::istringstream::in); 43 44 iss >> (*this); 45 } 46 47 std::ostream& operator<<(std::ostream& ost_, const Config& config_) 48 { 49 Config::ConstIterator it; 50 for(it = config_.begin(); it != config_.end(); it++) 51 { 52 ost_ << it->first << " " << config_.mDelimiter << " "; 53 ost_ << it->second << std::endl; 54 } 55 return ost_; 56 } 57 58 std::istream& operator>>(std::istream& ist_, Config& config_) 59 { 60 // Set a Config from ist_ 61 // Read in keys and values, keeping internal whitespace 62 typedef String::size_type pos; 63 const String& delim = config_.mDelimiter; // separator 64 const String& comm = config_.mComment; // comment 65 const String& sentry = config_.mSentry; // end of file sentry 66 const pos skip = delim.length(); // length of separator 67 68 String nextline = ""; // might need to read ahead to see where value ends 69 70 while(ist_ || nextline.length() > 0) 71 { 72 // Read an entire line at a time 73 String line; 74 if(nextline.length() > 0) 75 { 76 line = nextline; // we read ahead; use it now 77 nextline = ""; 78 } 79 else 80 { 81 //std::getline(ist_, line); 82 safeGetline(ist_, line); 83 } 84 85 // Ignore comments and the spaces on both ends 86 line = line.substr(0, line.find(comm)); 87 line.trim(); 88 89 // Check for end of file sentry 90 if((sentry != "") && (line.find(sentry) != String::npos)) return ist_; 91 92 if(line.length() == 0) 93 continue; 94 95 // Parse the line if it contains a delimiter 96 pos delimPos = line.find(delim); 97 ASSERT((delimPos < String::npos), "Invalid config line: '" + line + "'"); 98 99 // Extract the key 100 String key = line.substr(0, delimPos); 101 line.replace(0, delimPos+skip, ""); 102 103 // See if value continues on the next line 104 // Stop at blank line, next line with a key, end of stream, 105 // or end of file sentry 106 bool terminate = false; 107 while(!terminate && ist_) 108 { 109 if(line.at(line.size() - 1) == '\\') 110 line.erase(line.size() - 1); 111 else 112 break; 113 114 //std::getline(ist_, nextline); 115 safeGetline(ist_, nextline); 116 terminate = true; 117 118 String nlcopy = nextline; 119 nlcopy.trim(); 120 if(nlcopy == "") continue; 121 122 nextline = nextline.substr(0, nextline.find(comm)); 123 //if(nextline.find(delim) != String::npos) 124 // continue; 125 if((sentry != "") && (nextline.find(sentry) != String::npos)) 126 continue; 127 128 //nlcopy = nextline; 129 //nlcopy.trim(); 130 //if(nlcopy != "") line += "\n"; 131 line += nextline; 132 nextline = ""; 133 terminate = false; 134 } 135 136 // Store key and value 137 key.trim(); 138 line.trim(); 139 config_.set(key, line); // overwrites if key is repeated 140 } 141 return ist_; 142 } 143} 144 145