diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/include/str_map.h | |
parent | Initial commit. (diff) | |
download | ceph-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 '')
-rw-r--r-- | src/include/str_map.h | 180 |
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 |