aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-09-06 19:55:48 -0400
committerJack Lloyd <[email protected]>2018-09-09 11:37:25 -0400
commitfb656ae863fd5b755e4bc0e779b95d34e1106219 (patch)
tree8b53a3a43ebe836c5b4c63b78e7d56c9f16b8c0e /src/lib
parent992d2803181b34415c25e013a40ab935eb71a9e3 (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.h29
-rw-r--r--src/lib/utils/read_kv.cpp85
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;
+ }
+
+}