diff --git a/include/SCL/SCL.hpp b/include/SCL/SCL.hpp index b274afe..992eb23 100644 --- a/include/SCL/SCL.hpp +++ b/include/SCL/SCL.hpp @@ -13,27 +13,27 @@ namespace scl { //internal identifiers for writing comments/empty lines const std::string COMMENT_LINE = "#{_COMMENT_LINE}"; const std::string EMPTY_LINE = "#{_EMPTY_LINE}"; - + //small helper class for writing comments to a file class comment { public: std::string text; - + comment(std::string cmnt) { text = cmnt; } }; - + //small helper class for writing empty lines to a file class empty_lines { public: unsigned int num_lines; - + empty_lines(unsigned int num = 1) { num_lines = num; } }; - + //exception thrown if the file could not be opened class could_not_open_error : public std::exception { public: @@ -41,27 +41,27 @@ namespace scl { return "SCL: File could not be opened!"; } }; - + class config_file { private: //map to store all loaded data std::unordered_map data; - + //vector to store the order it was added std::vector data_order; - + //handle to the file std::fstream file; - + //the mode for the opened file const int mode; - + //the character used to seperate parts of a key for a list of values const char separator; - + //function to split a string into two pieces around a phrase static std::vector split(std::string s, std::string phrase) { - int pos = s.find(phrase); + size_t pos = s.find(phrase); if (pos != std::string::npos) { std::vector out; out.push_back(s.substr(0, pos)); @@ -76,7 +76,7 @@ namespace scl { return out; } } - + //a function for read mode that reads the data from the file into a buffer void load() { //read the file line by line, loading in the key - value pairs @@ -89,7 +89,7 @@ namespace scl { } } } - + void open(const std::string& filename) { if (this->mode == READ) { //open the fstream @@ -114,16 +114,16 @@ namespace scl { public: constexpr static int READ = 0; constexpr static int WRITE = 1; - + //iterator class class iterator { private: //nternal iterator for data_order std::vector::iterator it; - + //pointer to the config_file's data std::unordered_map *data; - + //does a string start with a value? static bool starts_with(std::string s, std::string phrase) { if (phrase.length() > s.length()) { @@ -132,32 +132,32 @@ namespace scl { return (s.substr(0, phrase.length()) == phrase); } } - + //make config_file friend friend class config_file; - + //private constructor (for begin/end) iterator(std::vector::iterator it, std::unordered_map *data) { this->it = it; this->data = data; } public: - + //empty constructor iterator() {} - + //copy constructor iterator(const iterator& other) { this->it = other.it; this->data = other.data; } - + //assignment operator void operator=(const iterator& other) { this->it = other.it; this->data = other.data; } - + //binary operators //addition iterator operator+(const int& i) { @@ -166,10 +166,10 @@ namespace scl { it.it = this->it + i; //and use the previous data pointer it.data = this->data; - + return it; } - + //subtaction iterator operator-(const int& i) { iterator it; @@ -177,30 +177,30 @@ namespace scl { it.it = this->it - i; //and use the previous data pointer it.data = this->data; - + return it; } - + //compound assignment operators //addition void operator+=(const int& i) { this->it += i; } - + //subtraction void operator-=(const int& i) { this->it -= i; } - + //dereference operator (TODO: Make this work for write operations as well) std::pair operator*() { if (data == nullptr) { throw std::runtime_error("iterator is uninitialized!"); } - + //pair to output - std::pair p; - + std::pair p; + //set the second part to the value, if it isn't a comment or empty line if (*it == EMPTY_LINE) { p.first = EMPTY_LINE; @@ -213,26 +213,26 @@ namespace scl { p.first = *it; p.second = (*data)[*it]; } - + return p; } - + //subscript operator std::pair operator[](unsigned int index) { return *(*this + index); } - + //relational operators //equality operator bool operator==(const iterator& other) { return (this->it == other.it); } - + //inequality operator bool operator!=(const iterator& other) { return (this->it != other.it); } - + //greater than bool operator>(const iterator& other) { return (this->it > other.it); @@ -241,7 +241,7 @@ namespace scl { bool operator>=(const iterator& other) { return (*this > other || *this == other); } - + //less than bool operator<(const iterator& other) { return (this->it < other.it); @@ -250,7 +250,7 @@ namespace scl { bool operator<=(const iterator& other) { return (*this < other || *this == other); } - + //prefix increment operator iterator operator++() { //increment the data_order iterator @@ -264,7 +264,7 @@ namespace scl { ++(*this); return temp; } - + //prefix decrement operator iterator operator--() { (this->it)--; @@ -276,45 +276,45 @@ namespace scl { --(*this); return temp; } - + ~iterator() { //currently empty } }; - + iterator begin() { iterator it; it.it = this->data_order.begin(); it.data = &(this->data); - + return it; } - + iterator end() { iterator it; it.it = this->data_order.end(); it.data = &(this->data); - + return it; } - + //initialize the file config_file(const std::string& filename, const int mode, const char separator = ' ') : mode(mode), separator(separator) { open(filename); } - + //make this object non-copyable //can't be copied in a construction config_file(const config_file&) = delete; //can't be copy assigned config_file& operator=(const config_file&) = delete; - + //default move constructor config_file (config_file&&) = default; //default move assignment config_file& operator=(config_file&&) = default; - + //a function for write mode that saves changes from the buffer (the data variable) to the file bool write_changes() { //if the file is in the wrong mode, or no changes have been made @@ -332,25 +332,25 @@ namespace scl { this->file << name << '=' << this->data[name] << '\n'; } } - + //and report success return true; } } - + //brief function to close the file and free up memory void close() { this->file.close(); this->data.erase(this->data.begin(), this->data.end()); this->data_order.erase(this->data_order.begin(), this->data_order.end()); } - + ~config_file() { close(); } - + //A series of functions to retrieve values of various types from the buffer - + template T get(const std::string& name, const T& def = {}) const { //if the file is in write mode, or data hasn't been loaded yet @@ -361,14 +361,14 @@ namespace scl { if (this->data.find(name) != this->data.end()) { //use a stringstream to format the data std::stringstream ss(this->data.at(name)); - + T out; ss >> out; - + if (ss.fail()) { return def; } - + return out; //if no data exists with the name } else { @@ -377,7 +377,7 @@ namespace scl { } } } - + template std::vector gets(const std::string& name, const std::vector& def = {}) const { //if the file is in write mode, or data hasn't been loaded yet @@ -390,19 +390,19 @@ namespace scl { std::vector out; std::stringstream ss(this->data.at(name)); std::string temp; - + while (std::getline(ss, temp, separator)) { std::stringstream conv(temp); T t; conv >> t; - + if (conv.fail()) { break; } - + out.push_back(t); } - + return out; //if no data exists with the name } else { @@ -411,9 +411,9 @@ namespace scl { } } } - + //a series of functions to write to the data variable, which acts as a buffer before a final write - + //put a single name-value pair template bool put(const std::string& name, const T& val) { @@ -427,11 +427,11 @@ namespace scl { ss << val; this->data[name] = ss.str(); this->data_order.push_back(name); - + return true; } } - + //ditto as above, but with an std::pair template bool put(const std::pair& val) { @@ -445,11 +445,11 @@ namespace scl { ss << val.second; this->data[val.first] = ss.str(); this->data_order.push_back(val.first); - + return true; } } - + //put multiple values under one identifier //with vector template @@ -464,14 +464,14 @@ namespace scl { for (T temp : val) { ss << temp << separator; } - + this->data[name] = ss.str(); this->data_order.push_back(name); - + return true; } } - + //ditto as above, but with std::pair template bool put(const std::pair>& val) { @@ -485,14 +485,14 @@ namespace scl { for (T temp : val.second) { ss << temp << separator; } - + this->data[val.first] = ss.str(); this->data_order.push_back(val.first); - + return true; } } - + bool put(const comment& c) { //if the file isn't in write mode if (this->mode != WRITE) { @@ -501,11 +501,11 @@ namespace scl { } else { //add comment text to the config file this->data_order.push_back(COMMENT_LINE + c.text); - + return true; } } - + bool put(const empty_lines& lines) { //if the file isn't in write mode if (this->mode != WRITE) { @@ -519,12 +519,12 @@ namespace scl { } } }; - + //functions to return iterators for a given config_file (range-based for loops) config_file::iterator begin(config_file& file) { return file.begin(); } - + config_file::iterator end(config_file& file) { return file.end(); }