]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/str_map.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / str_map.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
7 *
8 * Author: Loic Dachary <loic@dachary.org>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 */
16
17 #include <errno.h>
18
19 #include "include/str_map.h"
20 #include "include/str_list.h"
21
22 #include "json_spirit/json_spirit.h"
23
24 using namespace std;
25
26 int get_json_str_map(
27 const string &str,
28 ostream &ss,
29 map<string,string> *str_map,
30 bool fallback_to_plain)
31 {
32 json_spirit::mValue json;
33 try {
34 // try json parsing first
35
36 json_spirit::read_or_throw(str, json);
37
38 if (json.type() != json_spirit::obj_type) {
39 ss << str << " must be a JSON object but is of type "
40 << json.type() << " instead";
41 return -EINVAL;
42 }
43
44 json_spirit::mObject o = json.get_obj();
45
46 for (map<string, json_spirit::mValue>::iterator i = o.begin();
47 i != o.end();
48 ++i) {
49 (*str_map)[i->first] = i->second.get_str();
50 }
51 } catch (json_spirit::Error_position &e) {
52 if (fallback_to_plain) {
53 // fallback to key=value format
54 get_str_map(str, str_map, "\t\n ");
55 } else {
56 return -EINVAL;
57 }
58 }
59 return 0;
60 }
61 string trim(const string& str) {
62 size_t start = 0;
63 size_t end = str.size() - 1;
64 while (isspace(str[start]) != 0 && start <= end) {
65 ++start;
66 }
67 while (isspace(str[end]) != 0 && start <= end) {
68 --end;
69 }
70 if (start <= end) {
71 return str.substr(start, end - start + 1);
72 }
73 return string();
74 }
75
76 int get_str_map(
77 const string &str,
78 map<string,string> *str_map,
79 const char *delims)
80 {
81 list<string> pairs;
82 get_str_list(str, delims, pairs);
83 for (list<string>::iterator i = pairs.begin(); i != pairs.end(); ++i) {
84 size_t equal = i->find('=');
85 if (equal == string::npos)
86 (*str_map)[*i] = string();
87 else {
88 const string key = trim(i->substr(0, equal));
89 equal++;
90 const string value = trim(i->substr(equal));
91 (*str_map)[key] = value;
92 }
93 }
94 return 0;
95 }
96
97 string get_str_map_value(
98 const map<string,string> &str_map,
99 const string &key,
100 const string *def_val)
101 {
102 map<string,string>::const_iterator p = str_map.find(key);
103
104 // key exists in str_map
105 if (p != str_map.end()) {
106 // but value is empty
107 if (p->second.empty())
108 return p->first;
109 // and value is not empty
110 return p->second;
111 }
112
113 // key DNE in str_map and def_val was specified
114 if (def_val != NULL)
115 return *def_val;
116
117 // key DNE in str_map, no def_val was specified
118 return string();
119 }
120
121 string get_str_map_key(
122 const map<string,string> &str_map,
123 const string &key,
124 const string *fallback_key)
125 {
126 map<string,string>::const_iterator p = str_map.find(key);
127 if (p != str_map.end())
128 return p->second;
129
130 if (fallback_key != NULL) {
131 p = str_map.find(*fallback_key);
132 if (p != str_map.end())
133 return p->second;
134 }
135 return string();
136 }
137
138 // This function's only purpose is to check whether a given map has only
139 // ONE key with an empty value (which would mean that 'get_str_map()' read
140 // a map in the form of 'VALUE', without any KEY/VALUE pairs) and, in such
141 // event, to assign said 'VALUE' to a given 'def_key', such that we end up
142 // with a map of the form "m = { 'def_key' : 'VALUE' }" instead of the
143 // original "m = { 'VALUE' : '' }".
144 int get_conf_str_map_helper(
145 const string &str,
146 ostringstream &oss,
147 map<string,string> *m,
148 const string &def_key)
149 {
150 int r = get_str_map(str, m);
151
152 if (r < 0) {
153 return r;
154 }
155
156 if (r >= 0 && m->size() == 1) {
157 map<string,string>::iterator p = m->begin();
158 if (p->second.empty()) {
159 string s = p->first;
160 m->erase(s);
161 (*m)[def_key] = s;
162 }
163 }
164 return r;
165 }