| // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #include "Configurator.hpp" | 
 |  | 
 | #include <iostream> | 
 | #include <fstream> | 
 |  | 
 | using namespace std; | 
 |  | 
 | #include <stdio.h> | 
 | #include <stdarg.h> | 
 | #include <ctype.h> | 
 |  | 
 | #if defined(__unix__) | 
 | #include <unistd.h> | 
 | #endif | 
 |  | 
 | namespace sw | 
 | { | 
 | 	Configurator::Configurator(string iniPath) | 
 | 	{ | 
 | 		path = iniPath; | 
 |  | 
 | 		readFile(); | 
 | 	} | 
 |  | 
 | 	Configurator::~Configurator() | 
 | 	{ | 
 | 	} | 
 |  | 
 | 	bool Configurator::readFile() | 
 | 	{ | 
 | 		#if defined(__unix__) | 
 | 			if(access(path.c_str(), R_OK) != 0) | 
 | 			{ | 
 | 				return false; | 
 | 			} | 
 | 		#endif | 
 |  | 
 | 		fstream file(path.c_str(), ios::in); | 
 | 		if(file.fail()) return false; | 
 |  | 
 | 		string line; | 
 | 		string keyName; | 
 |  | 
 | 		while(getline(file, line)) | 
 | 		{ | 
 | 			if(line.length()) | 
 | 			{ | 
 | 				if(line[line.length() - 1] == '\r') | 
 | 				{ | 
 | 					line = line.substr(0, line.length() - 1); | 
 | 				} | 
 |  | 
 | 				if(!isprint(line[0])) | 
 | 				{ | 
 | 				//	printf("Failing on char %d\n", line[0]); | 
 | 					file.close(); | 
 | 					return false; | 
 | 				} | 
 |  | 
 | 				string::size_type pLeft = line.find_first_of(";#[="); | 
 |  | 
 | 				if(pLeft != string::npos) | 
 | 				{ | 
 | 					switch(line[pLeft]) | 
 | 					{ | 
 | 					case '[': | 
 | 						{ | 
 | 							string::size_type pRight = line.find_last_of("]"); | 
 |  | 
 | 							if(pRight != string::npos && pRight > pLeft) | 
 | 							{ | 
 | 								keyName = line.substr(pLeft + 1, pRight - pLeft - 1); | 
 | 								addKeyName(keyName); | 
 | 							} | 
 | 						} | 
 | 						break; | 
 | 					case '=': | 
 | 						{ | 
 | 							string valueName = line.substr(0, pLeft); | 
 | 							string value = line.substr(pLeft + 1); | 
 | 							addValue(keyName, valueName, value); | 
 | 						} | 
 | 						break; | 
 | 					case ';': | 
 | 					case '#': | 
 | 						// Ignore comments | 
 | 						break; | 
 | 					} | 
 | 				} | 
 | 			} | 
 | 		} | 
 |  | 
 | 		file.close(); | 
 |  | 
 | 		if(names.size()) | 
 | 		{ | 
 | 			return true; | 
 | 		} | 
 |  | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	void Configurator::writeFile(std::string title) | 
 | 	{ | 
 | 		#if defined(__unix__) | 
 | 			if(access(path.c_str(), W_OK) != 0) | 
 | 			{ | 
 | 				return; | 
 | 			} | 
 | 		#endif | 
 |  | 
 | 		fstream file(path.c_str(), ios::out); | 
 | 		if(file.fail()) return; | 
 |  | 
 | 		file << "; " << title << endl << endl; | 
 |  | 
 | 		for(unsigned int keyID = 0; keyID < sections.size(); keyID++) | 
 | 		{ | 
 | 			file << "[" << names[keyID] << "]" << endl; | 
 |  | 
 | 			for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); valueID++) | 
 | 			{ | 
 | 				file << sections[keyID].names[valueID] << "=" << sections[keyID].values[valueID] << endl; | 
 | 			} | 
 |  | 
 | 			file << endl; | 
 | 		} | 
 |  | 
 | 		file.close(); | 
 | 	} | 
 |  | 
 | 	int Configurator::findKey(string keyName) const | 
 | 	{ | 
 | 		for(unsigned int keyID = 0; keyID < names.size(); keyID++) | 
 | 		{ | 
 | 			if(names[keyID] == keyName) | 
 | 			{ | 
 | 				return keyID; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	int Configurator::findValue(unsigned int keyID, string valueName) const | 
 | 	{ | 
 | 		if(!sections.size() || keyID >= sections.size()) | 
 | 		{ | 
 | 			return -1; | 
 | 		} | 
 |  | 
 | 		for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); ++valueID) | 
 | 		{ | 
 | 			if(sections[keyID].names[valueID] == valueName) | 
 | 			{ | 
 | 				return valueID; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	unsigned int Configurator::addKeyName(string keyName) | 
 | 	{ | 
 | 		names.resize(names.size() + 1, keyName); | 
 | 		sections.resize(sections.size() + 1); | 
 | 		return (unsigned int)names.size() - 1; | 
 | 	} | 
 |  | 
 | 	void Configurator::addValue(string const keyName, string const valueName, string const value) | 
 | 	{ | 
 | 		int keyID = findKey(keyName); | 
 |  | 
 | 		if(keyID == -1) | 
 | 		{ | 
 | 			keyID = addKeyName(keyName); | 
 | 		} | 
 |  | 
 | 		int valueID = findValue(keyID, valueName); | 
 |  | 
 | 		if(valueID == -1) | 
 | 		{ | 
 | 			sections[keyID].names.resize(sections[keyID].names.size() + 1, valueName); | 
 | 			sections[keyID].values.resize(sections[keyID].values.size() + 1, value); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			sections[keyID].values[valueID] = value; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	string Configurator::getValue(string keyName, string valueName, string defaultValue) const | 
 | 	{ | 
 | 		int keyID = findKey(keyName); | 
 | 		if(keyID == -1) return defaultValue; | 
 | 		int valueID = findValue((unsigned int)keyID, valueName); | 
 | 		if(valueID == -1) return defaultValue; | 
 |  | 
 | 		return sections[keyID].values[valueID]; | 
 | 	} | 
 |  | 
 | 	int Configurator::getInteger(string keyName, string valueName, int defaultValue) const | 
 | 	{ | 
 | 		char svalue[256]; | 
 |  | 
 | 		sprintf(svalue, "%d", defaultValue); | 
 |  | 
 | 		return atoi(getValue(keyName, valueName, svalue).c_str()); | 
 | 	} | 
 |  | 
 | 	bool Configurator::getBoolean(string keyName, string valueName, bool defaultValue) const | 
 | 	{ | 
 | 		return getInteger(keyName, valueName, (int)defaultValue) != 0; | 
 | 	} | 
 |  | 
 | 	double Configurator::getFloat(string keyName, string valueName, double defaultValue) const | 
 | 	{ | 
 | 		char svalue[256]; | 
 |  | 
 | 		sprintf(svalue, "%f", defaultValue); | 
 |  | 
 | 		return atof(getValue(keyName, valueName, svalue).c_str()); | 
 | 	} | 
 |  | 
 | 	unsigned int Configurator::getFormatted(string keyName, string valueName, char *format, | 
 | 											void *v1, void *v2, void *v3, void *v4, | 
 | 											void *v5, void *v6, void *v7, void *v8, | 
 | 											void *v9, void *v10, void *v11, void *v12, | 
 | 											void *v13, void *v14, void *v15, void *v16) | 
 | 	{ | 
 | 		string value = getValue(keyName, valueName); | 
 |  | 
 | 		if(!value.length()) return false; | 
 |  | 
 | 		unsigned int nVals = sscanf(value.c_str(), format, | 
 | 									v1, v2, v3, v4, v5, v6, v7, v8, | 
 | 									v9, v10, v11, v12, v13, v14, v15, v16); | 
 |  | 
 | 		return nVals; | 
 | 	} | 
 | } |