1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "Configurator.hpp" 16 17 #include <iostream> 18 #include <fstream> 19 20 using namespace std; 21 22 #include <stdio.h> 23 #include <stdarg.h> 24 #include <ctype.h> 25 26 #if defined(__unix__) 27 #include <unistd.h> 28 #endif 29 30 namespace sw 31 { 32 Configurator::Configurator(string iniPath) 33 { 34 path = iniPath; 35 36 readFile(); 37 } 38 39 Configurator::~Configurator() 40 { 41 } 42 43 bool Configurator::readFile() 44 { 45 #if defined(__unix__) 46 if(access(path.c_str(), R_OK) != 0) 47 { 48 return false; 49 } 50 #endif 51 52 fstream file(path.c_str(), ios::in); 53 if(file.fail()) return false; 54 55 string line; 56 string keyName; 57 58 while(getline(file, line)) 59 { 60 if(line.length()) 61 { 62 if(line[line.length() - 1] == '\r') 63 { 64 line = line.substr(0, line.length() - 1); 65 } 66 67 if(!isprint(line[0])) 68 { 69 printf("Failing on char %d\n", line[0]); 70 file.close(); 71 return false; 72 } 73 74 string::size_type pLeft = line.find_first_of(";#[="); 75 76 if(pLeft != string::npos) 77 { 78 switch(line[pLeft]) 79 { 80 case '[': 81 { 82 string::size_type pRight = line.find_last_of("]"); 83 84 if(pRight != string::npos && pRight > pLeft) 85 { 86 keyName = line.substr(pLeft + 1, pRight - pLeft - 1); 87 addKeyName(keyName); 88 } 89 } 90 break; 91 case '=': 92 { 93 string valueName = line.substr(0, pLeft); 94 string value = line.substr(pLeft + 1); 95 addValue(keyName, valueName, value); 96 } 97 break; 98 case ';': 99 case '#': 100 // Ignore comments 101 break; 102 } 103 } 104 } 105 } 106 107 file.close(); 108 109 if(names.size()) 110 { 111 return true; 112 } 113 114 return false; 115 } 116 117 void Configurator::writeFile(std::string title) 118 { 119 #if defined(__unix__) 120 if(access(path.c_str(), W_OK) != 0) 121 { 122 return; 123 } 124 #endif 125 126 fstream file(path.c_str(), ios::out); 127 if(file.fail()) return; 128 129 file << "; " << title << endl << endl; 130 131 for(unsigned int keyID = 0; keyID < sections.size(); keyID++) 132 { 133 file << "[" << names[keyID] << "]" << endl; 134 135 for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); valueID++) 136 { 137 file << sections[keyID].names[valueID] << "=" << sections[keyID].values[valueID] << endl; 138 } 139 140 file << endl; 141 } 142 143 file.close(); 144 } 145 146 int Configurator::findKey(string keyName) const 147 { 148 for(unsigned int keyID = 0; keyID < names.size(); keyID++) 149 { 150 if(names[keyID] == keyName) 151 { 152 return keyID; 153 } 154 } 155 156 return -1; 157 } 158 159 int Configurator::findValue(unsigned int keyID, string valueName) const 160 { 161 if(!sections.size() || keyID >= sections.size()) 162 { 163 return -1; 164 } 165 166 for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); ++valueID) 167 { 168 if(sections[keyID].names[valueID] == valueName) 169 { 170 return valueID; 171 } 172 } 173 174 return -1; 175 } 176 177 unsigned int Configurator::addKeyName(string keyName) 178 { 179 names.resize(names.size() + 1, keyName); 180 sections.resize(sections.size() + 1); 181 return (unsigned int)names.size() - 1; 182 } 183 184 void Configurator::addValue(string const keyName, string const valueName, string const value) 185 { 186 int keyID = findKey(keyName); 187 188 if(keyID == -1) 189 { 190 keyID = addKeyName(keyName); 191 } 192 193 int valueID = findValue(keyID, valueName); 194 195 if(valueID == -1) 196 { 197 sections[keyID].names.resize(sections[keyID].names.size() + 1, valueName); 198 sections[keyID].values.resize(sections[keyID].values.size() + 1, value); 199 } 200 else 201 { 202 sections[keyID].values[valueID] = value; 203 } 204 } 205 206 string Configurator::getValue(string keyName, string valueName, string defaultValue) const 207 { 208 int keyID = findKey(keyName); 209 if(keyID == -1) return defaultValue; 210 int valueID = findValue((unsigned int)keyID, valueName); 211 if(valueID == -1) return defaultValue; 212 213 return sections[keyID].values[valueID]; 214 } 215 216 int Configurator::getInteger(string keyName, string valueName, int defaultValue) const 217 { 218 char svalue[256]; 219 220 sprintf(svalue, "%d", defaultValue); 221 222 return atoi(getValue(keyName, valueName, svalue).c_str()); 223 } 224 225 bool Configurator::getBoolean(string keyName, string valueName, bool defaultValue) const 226 { 227 return getInteger(keyName, valueName, (int)defaultValue) != 0; 228 } 229 230 double Configurator::getFloat(string keyName, string valueName, double defaultValue) const 231 { 232 char svalue[256]; 233 234 sprintf(svalue, "%f", defaultValue); 235 236 return atof(getValue(keyName, valueName, svalue).c_str()); 237 } 238 239 unsigned int Configurator::getFormatted(string keyName, string valueName, char *format, 240 void *v1, void *v2, void *v3, void *v4, 241 void *v5, void *v6, void *v7, void *v8, 242 void *v9, void *v10, void *v11, void *v12, 243 void *v13, void *v14, void *v15, void *v16) 244 { 245 string value = getValue(keyName, valueName); 246 247 if(!value.length()) return false; 248 249 unsigned int nVals = sscanf(value.c_str(), format, 250 v1, v2, v3, v4, v5, v6, v7, v8, 251 v9, v10, v11, v12, v13, v14, v15, v16); 252 253 return nVals; 254 } 255 } 256