diff options
author | Jack Lloyd <[email protected]> | 2018-09-06 19:55:48 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-09-09 11:37:25 -0400 |
commit | fb656ae863fd5b755e4bc0e779b95d34e1106219 (patch) | |
tree | 8b53a3a43ebe836c5b4c63b78e7d56c9f16b8c0e /src/lib | |
parent | 992d2803181b34415c25e013a40ab935eb71a9e3 (diff) |
Add read_kv for parsing strings with key/value pairs
This is a contribution by Ribose Inc (@riboseinc)
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/utils/parsing.h | 29 | ||||
-rw-r--r-- | src/lib/utils/read_kv.cpp | 85 |
2 files changed, 111 insertions, 3 deletions
diff --git a/src/lib/utils/parsing.h b/src/lib/utils/parsing.h index 9185cfaad..12cb3fa34 100644 --- a/src/lib/utils/parsing.h +++ b/src/lib/utils/parsing.h @@ -5,8 +5,8 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#ifndef BOTAN_PARSER_H_ -#define BOTAN_PARSER_H_ +#ifndef BOTAN_PARSING_UTILS_H_ +#define BOTAN_PARSING_UTILS_H_ #include <botan/types.h> #include <string> @@ -40,6 +40,8 @@ BOTAN_PUBLIC_API(2,0) std::vector<std::string> split_on( * Split a string on a character predicate * @param str the input string * @param pred the predicate +* +* This function will likely be removed in a future release */ BOTAN_PUBLIC_API(2,0) std::vector<std::string> split_on_pred(const std::string& str, @@ -143,9 +145,30 @@ BOTAN_PUBLIC_API(2,0) std::string ipv4_to_string(uint32_t ip_addr); std::map<std::string, std::string> BOTAN_PUBLIC_API(2,0) read_cfg(std::istream& is); +/** +* Accepts key value pairs deliminated by commas: +* +* "" (returns empty map) +* "K=V" (returns map {'K': 'V'}) +* "K1=V1,K2=V2" +* "K1=V1,K2=V2,K3=V3" +* "K1=V1,K2=V2,K3=a_value\,with\,commas_and_\=equals" +* +* Values may be empty, keys must be non-empty and unique. Duplicate +* keys cause an exception. +* +* Within both key and value, comma and equals can be escaped with +* backslash. Backslash can also be escaped. +*/ +std::map<std::string, std::string> BOTAN_PUBLIC_API(2,8) read_kv(const std::string& kv); + std::string BOTAN_PUBLIC_API(2,0) clean_ws(const std::string& s); -bool BOTAN_PUBLIC_API(2,0) host_wildcard_match(const std::string& wildcard, const std::string& host); +/** +* Check if the given hostname is a match for the specified wildcard +*/ +bool BOTAN_PUBLIC_API(2,0) host_wildcard_match(const std::string& wildcard, + const std::string& host); } diff --git a/src/lib/utils/read_kv.cpp b/src/lib/utils/read_kv.cpp new file mode 100644 index 000000000..cdc84c622 --- /dev/null +++ b/src/lib/utils/read_kv.cpp @@ -0,0 +1,85 @@ +/* +* (C) 2018 Ribose Inc +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/parsing.h> +#include <botan/exceptn.h> + +namespace Botan { + +std::map<std::string, std::string> read_kv(const std::string& kv) + { + std::map<std::string, std::string> m; + if(kv == "") + return m; + + std::vector<std::string> parts; + + try + { + parts = split_on(kv, ','); + } + catch(std::exception&) + { + throw Invalid_Argument("Bad KV spec"); + } + + bool escaped = false; + bool reading_key = true; + std::string cur_key; + std::string cur_val; + + for(char c : kv) + { + if(c == '\\' && !escaped) + { + escaped = true; + } + else if(c == ',' && !escaped) + { + if(cur_key.empty()) + throw Invalid_Argument("Bad KV spec empty key"); + + if(m.find(cur_key) != m.end()) + throw Invalid_Argument("Bad KV spec duplicated key"); + m[cur_key] = cur_val; + cur_key = ""; + cur_val = ""; + reading_key = true; + } + else if(c == '=' && !escaped) + { + if(reading_key == false) + throw Invalid_Argument("Bad KV spec unexpected equals sign"); + reading_key = false; + } + else + { + if(reading_key) + cur_key += c; + else + cur_val += c; + + if(escaped) + escaped = false; + } + } + + if(!cur_key.empty()) + { + if(reading_key == false) + { + if(m.find(cur_key) != m.end()) + throw Invalid_Argument("Bad KV spec duplicated key"); + m[cur_key] = cur_val; + } + else + throw Invalid_Argument("Bad KV spec incomplete string"); + } + + return m; + } + +} |