summaryrefslogtreecommitdiffstats
path: root/src/include/str_map.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/include/str_map.h
parentInitial commit. (diff)
downloadceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz
ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/include/str_map.h')
-rw-r--r--src/include/str_map.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/include/str_map.h b/src/include/str_map.h
new file mode 100644
index 000000000..7f354fd46
--- /dev/null
+++ b/src/include/str_map.h
@@ -0,0 +1,180 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef CEPH_STRMAP_H
+#define CEPH_STRMAP_H
+
+#define CONST_DELIMS ",;\t\n "
+
+#include <map>
+#include <string>
+#include <sstream>
+
+template <typename Func>
+void for_each_pair(std::string_view s, const char* delims, Func&& f)
+{
+ auto pos = s.find_first_not_of(delims);
+ while (pos != s.npos) {
+ s.remove_prefix(pos); // trim delims from the front
+ auto end = s.find_first_of(delims);
+ auto kv = s.substr(0, end);
+ if (auto equal = kv.find('='); equal != kv.npos) {
+ f(kv.substr(0, equal), kv.substr(equal + 1));
+ } else {
+ f(kv.substr(0, equal), std::string_view());
+ }
+ pos = s.find_first_not_of(delims, end);
+ }
+}
+
+using str_map_t = std::map<std::string,std::string>;
+
+/**
+ * Parse **str** and set **str_map** with the key/value pairs read
+ * from it. The format of **str** is either a well formed JSON object
+ * or a custom key[=value] plain text format.
+ *
+ * JSON is tried first. If successfully parsed into a JSON object, it
+ * is copied into **str_map** verbatim. If it is not a JSON object ( a
+ * string, integer etc. ), -EINVAL is returned and **ss** is set to
+ * a human readable error message.
+ *
+ * If **str** is no valid JSON and if **fallback_to_plain** is set to true
+ * (default: true) it is assumed to be a string containing white space
+ * separated key=value pairs. A white space is either space, tab or newline.
+ * Function **get_str_map** will be leveraged to parse the plain-text
+ * key/value pairs.
+ *
+ * @param [in] str JSON or plain text key/value pairs
+ * @param [out] ss human readable message on error
+ * @param [out] str_map key/value pairs read from str
+ * @param [in] fallback_to_plain attempt parsing as plain-text if json fails
+ * @return **0** on success or a -EINVAL on error.
+ */
+int get_json_str_map(
+ const std::string &str,
+ std::ostream &ss,
+ str_map_t* str_map,
+ bool fallback_to_plain = true);
+
+/**
+ * Parse **str** and set **str_map** with the key/value pairs read from
+ * it. The format of **str** is a number of custom key[=value] pairs in
+ * plain text format.
+ *
+ * The string will be parsed taking **delims** as field delimiters for
+ * key/values. The value is optional resulting in an empty string when
+ * not provided. For example, using white space as delimiters:
+ *
+ * insert your own=political/ideological statement=here
+ *
+ * will be parsed into:
+ *
+ * { "insert": "",
+ * "your": "",
+ * "own": "political/ideological",
+ * "statement": "here" }
+ *
+ * Alternative delimiters may be provided. For instance, specifying
+ * "white space and slash", for the above statement, would be parsed
+ * into:
+ *
+ * { "insert": "",
+ * "your": "",
+ * "own": "political",
+ * "ideological": "",
+ * "statement": "here" }
+ *
+ * See how adding '/' to the delimiters field will spawn a new key without
+ * a set value.
+ *
+ * Always returns 0, as there is no condition for failure.
+ *
+ * @param [in] str plain text key/value pairs
+ * @param [in] delims field delimiters to be used for parsing str
+ * @param [out] str_map key/value pairs parsed from str
+ * @return **0**
+ */
+int get_str_map(
+ const std::string &str,
+ str_map_t* str_map,
+ const char *delims = CONST_DELIMS);
+
+// an alternate form (as we never fail):
+str_map_t get_str_map(
+ const std::string& str,
+ const char* delim = CONST_DELIMS);
+
+/**
+ * Returns the value of **key** in **str_map** if available.
+ *
+ * If **key** is not available in **str_map**, and if **def_val** is
+ * not-NULL then returns **def_val**. Otherwise checks if the value of
+ * **key** is an empty string and if so will return **key**.
+ * If the map contains **key**, the function returns the value of **key**.
+ *
+ * @param[in] str_map Map to obtain **key** from
+ * @param[in] key The key to search for in the map
+ * @param[in] def_val The value to return in case **key** is not present
+ */
+std::string get_str_map_value(
+ const str_map_t& str_map,
+ const std::string &key,
+ const std::string *def_val = nullptr);
+
+/**
+ * Returns the value of **key** in **str_map** if available.
+ *
+ * If **key** is available in **str_map** returns the value of **key**.
+ *
+ * If **key** is not available in **str_map**, and if **def_key**
+ * is not-NULL and available in **str_map**, then returns the value
+ * of **def_key**.
+ *
+ * Otherwise returns an empty string.
+ *
+ * @param[in] str_map Map to obtain **key** or **def_key** from
+ * @param[in] key Key to obtain the value of from **str_map**
+ * @param[in] def_key Key to fallback to if **key** is not present
+ * in **str_map**
+ */
+std::string get_str_map_key(
+ const str_map_t& str_map,
+ const std::string &key,
+ const std::string *fallback_key = nullptr);
+
+// This function's only purpose is to check whether a given map has only
+// ONE key with an empty value (which would mean that 'get_str_map()' read
+// a map in the form of 'VALUE', without any KEY/VALUE pairs) and, in such
+// event, to assign said 'VALUE' to a given 'def_key', such that we end up
+// with a map of the form "m = { 'def_key' : 'VALUE' }" instead of the
+// original "m = { 'VALUE' : '' }".
+int get_conf_str_map_helper(
+ const std::string &str,
+ std::ostringstream &oss,
+ str_map_t* str_map,
+ const std::string &default_key);
+
+std::string get_value_via_strmap(
+ const std::string& conf_string,
+ std::string_view default_key);
+
+std::string get_value_via_strmap(
+ const std::string& conf_string,
+ const std::string& key,
+ std::string_view default_key);
+
+#endif