diff options
-rw-r--r-- | src/utils/info.txt | 11 | ||||
-rw-r--r-- | src/utils/parsing.h | 16 | ||||
-rw-r--r-- | src/utils/read_cfg.cpp | 115 |
3 files changed, 131 insertions, 11 deletions
diff --git a/src/utils/info.txt b/src/utils/info.txt index 33f38386d..0e8edeb00 100644 --- a/src/utils/info.txt +++ b/src/utils/info.txt @@ -2,17 +2,6 @@ define UTIL_FUNCTIONS 20131128 load_on always -<source> -assert.cpp -calendar.cpp -charset.cpp -cpuid.cpp -parsing.cpp -semaphore.cpp -version.cpp -zero_mem.cpp -</source> - <header:internal> bit_ops.h prefetch.h diff --git a/src/utils/parsing.h b/src/utils/parsing.h index 88c5a7bc0..b37e3cb62 100644 --- a/src/utils/parsing.h +++ b/src/utils/parsing.h @@ -13,6 +13,10 @@ #include <vector> #include <set> +#include <istream> +#include <functional> +#include <map> + namespace Botan { /** @@ -112,6 +116,18 @@ BOTAN_DLL u32bit string_to_ipv4(const std::string& ip_str); */ BOTAN_DLL std::string ipv4_to_string(u32bit ip_addr); +void BOTAN_DLL lex_cfg(std::istream& is, + std::function<void (std::string)> cb); + +void BOTAN_DLL lex_cfg_w_headers(std::istream& is, + std::function<void (std::string)> cb, + std::function<void (std::string)> header_cb); + +std::map<std::string, std::map<std::string, std::string>> +BOTAN_DLL +parse_cfg(std::istream& is); + + } #endif diff --git a/src/utils/read_cfg.cpp b/src/utils/read_cfg.cpp new file mode 100644 index 000000000..ad57a8b3e --- /dev/null +++ b/src/utils/read_cfg.cpp @@ -0,0 +1,115 @@ +/* +* Simple config/test file reader +* (C) 2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/parsing.h> +#include <boost/algorithm/string.hpp> + +namespace Botan { + +void lex_cfg(std::istream& is, + std::function<void (std::string)> cb) + { + while(is.good()) + { + std::string s; + + std::getline(is, s); + + while(is.good() && s.back() == '\\') + { + boost::trim_if(s, boost::is_any_of("\\\n")); + std::string x; + std::getline(is, x); + boost::trim_left(x); + s += x; + } + + auto comment = s.find('#'); + if(comment) + s = s.substr(0, comment); + + if(s.empty()) + continue; + + std::vector<std::string> parts; + boost::split(parts, s, boost::is_any_of(" \t\n"), boost::token_compress_on); + + for(auto p : parts) + { + if(p.empty()) + continue; + + auto eq = p.find("="); + + if(eq == std::string::npos || p.size() < 2) + { + cb(p); + } + else if(eq == 0) + { + cb("="); + cb(p.substr(1, std::string::npos)); + } + else if(eq == p.size() - 1) + { + cb(p.substr(0, p.size() - 1)); + cb("="); + } + else if(eq != std::string::npos) + { + cb(p.substr(0, eq)); + cb("="); + cb(p.substr(eq + 1, std::string::npos)); + } + } + } + } + +void lex_cfg_w_headers(std::istream& is, + std::function<void (std::string)> cb, + std::function<void (std::string)> hdr_cb) + { + auto intercept = [cb,hdr_cb](const std::string& s) + { + if(s[0] == '[' && s[s.length()-1] == ']') + hdr_cb(s.substr(1, s.length()-2)); + else + cb(s); + }; + + lex_cfg(is, intercept); + } + +std::map<std::string, std::map<std::string, std::string>> + parse_cfg(std::istream& is) + { + std::string header = "default"; + std::map<std::string, std::map<std::string, std::string>> vals; + std::string key; + + auto header_cb = [&header](const std::string i) { header = i; }; + auto cb = [&header,&key,&vals](const std::string s) + { + if(s == "=") + { + BOTAN_ASSERT(!key.empty(), "Valid assignment in config"); + } + else if(key.empty()) + key = s; + else + { + vals[header][key] = s; + key = ""; + } + }; + + lex_cfg_w_headers(is, cb, header_cb); + + return vals; + } + +} |