]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/string_util.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
6 #include "util/string_util.h"
8 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
23 #include "rocksdb/env.h"
24 #include "rocksdb/slice.h"
28 const std::string kNullptrString
= "nullptr";
30 std::vector
<std::string
> StringSplit(const std::string
& arg
, char delim
) {
31 std::vector
<std::string
> splits
;
32 std::stringstream
ss(arg
);
34 while (std::getline(ss
, item
, delim
)) {
35 splits
.push_back(item
);
40 // for micros < 10ms, print "XX us".
41 // for micros < 10sec, print "XX ms".
42 // for micros >= 10 sec, print "XX sec".
43 // for micros <= 1 hour, print Y:X M:S".
44 // for micros > 1 hour, print Z:Y:X H:M:S".
45 int AppendHumanMicros(uint64_t micros
, char* output
, int len
,
47 if (micros
< 10000 && !fixed_format
) {
48 return snprintf(output
, len
, "%" PRIu64
" us", micros
);
49 } else if (micros
< 10000000 && !fixed_format
) {
50 return snprintf(output
, len
, "%.3lf ms",
51 static_cast<double>(micros
) / 1000);
52 } else if (micros
< 1000000l * 60 && !fixed_format
) {
53 return snprintf(output
, len
, "%.3lf sec",
54 static_cast<double>(micros
) / 1000000);
55 } else if (micros
< 1000000ll * 60 * 60 && !fixed_format
) {
56 return snprintf(output
, len
, "%02" PRIu64
":%05.3f M:S",
57 micros
/ 1000000 / 60,
58 static_cast<double>(micros
% 60000000) / 1000000);
60 return snprintf(output
, len
, "%02" PRIu64
":%02" PRIu64
":%05.3f H:M:S",
61 micros
/ 1000000 / 3600, (micros
/ 1000000 / 60) % 60,
62 static_cast<double>(micros
% 60000000) / 1000000);
66 // for sizes >=10TB, print "XXTB"
67 // for sizes >=10GB, print "XXGB"
69 // append file size summary to output and return the len
70 int AppendHumanBytes(uint64_t bytes
, char* output
, int len
) {
71 const uint64_t ull10
= 10;
72 if (bytes
>= ull10
<< 40) {
73 return snprintf(output
, len
, "%" PRIu64
"TB", bytes
>> 40);
74 } else if (bytes
>= ull10
<< 30) {
75 return snprintf(output
, len
, "%" PRIu64
"GB", bytes
>> 30);
76 } else if (bytes
>= ull10
<< 20) {
77 return snprintf(output
, len
, "%" PRIu64
"MB", bytes
>> 20);
78 } else if (bytes
>= ull10
<< 10) {
79 return snprintf(output
, len
, "%" PRIu64
"KB", bytes
>> 10);
81 return snprintf(output
, len
, "%" PRIu64
"B", bytes
);
85 void AppendNumberTo(std::string
* str
, uint64_t num
) {
87 snprintf(buf
, sizeof(buf
), "%" PRIu64
, num
);
91 void AppendEscapedStringTo(std::string
* str
, const Slice
& value
) {
92 for (size_t i
= 0; i
< value
.size(); i
++) {
94 if (c
>= ' ' && c
<= '~') {
98 snprintf(buf
, sizeof(buf
), "\\x%02x",
99 static_cast<unsigned int>(c
) & 0xff);
105 std::string
NumberToString(uint64_t num
) {
107 AppendNumberTo(&r
, num
);
111 std::string
NumberToHumanString(int64_t num
) {
113 int64_t absnum
= num
< 0 ? -num
: num
;
114 if (absnum
< 10000) {
115 snprintf(buf
, sizeof(buf
), "%" PRIi64
, num
);
116 } else if (absnum
< 10000000) {
117 snprintf(buf
, sizeof(buf
), "%" PRIi64
"K", num
/ 1000);
118 } else if (absnum
< 10000000000LL) {
119 snprintf(buf
, sizeof(buf
), "%" PRIi64
"M", num
/ 1000000);
121 snprintf(buf
, sizeof(buf
), "%" PRIi64
"G", num
/ 1000000000);
123 return std::string(buf
);
126 std::string
BytesToHumanString(uint64_t bytes
) {
127 const char* size_name
[] = {"KB", "MB", "GB", "TB"};
128 double final_size
= static_cast<double>(bytes
);
131 // always start with KB
135 while (size_idx
< 3 && final_size
>= 1024) {
141 snprintf(buf
, sizeof(buf
), "%.2f %s", final_size
, size_name
[size_idx
]);
142 return std::string(buf
);
145 std::string
EscapeString(const Slice
& value
) {
147 AppendEscapedStringTo(&r
, value
);
151 bool ConsumeDecimalNumber(Slice
* in
, uint64_t* val
) {
154 while (!in
->empty()) {
156 if (c
>= '0' && c
<= '9') {
158 const unsigned int delta
= (c
- '0');
159 static const uint64_t kMaxUint64
= ~static_cast<uint64_t>(0);
160 if (v
> kMaxUint64
/ 10 ||
161 (v
== kMaxUint64
/ 10 && delta
> kMaxUint64
% 10)) {
165 v
= (v
* 10) + delta
;
166 in
->remove_prefix(1);
175 bool isSpecialChar(const char c
) {
176 if (c
== '\\' || c
== '#' || c
== ':' || c
== '\r' || c
== '\n') {
183 using CharMap
= std::pair
<char, char>;
186 char UnescapeChar(const char c
) {
187 static const CharMap convert_map
[] = {{'r', '\r'}, {'n', '\n'}};
189 auto iter
= std::find_if(std::begin(convert_map
), std::end(convert_map
),
190 [c
](const CharMap
& p
) { return p
.first
== c
; });
192 if (iter
== std::end(convert_map
)) {
198 char EscapeChar(const char c
) {
199 static const CharMap convert_map
[] = {{'\n', 'n'}, {'\r', 'r'}};
201 auto iter
= std::find_if(std::begin(convert_map
), std::end(convert_map
),
202 [c
](const CharMap
& p
) { return p
.first
== c
; });
204 if (iter
== std::end(convert_map
)) {
210 std::string
EscapeOptionString(const std::string
& raw_string
) {
212 for (auto c
: raw_string
) {
213 if (isSpecialChar(c
)) {
215 output
+= EscapeChar(c
);
224 std::string
UnescapeOptionString(const std::string
& escaped_string
) {
225 bool escaped
= false;
228 for (auto c
: escaped_string
) {
230 output
+= UnescapeChar(c
);
243 std::string
trim(const std::string
& str
) {
244 if (str
.empty()) return std::string();
246 size_t end
= str
.size() - 1;
247 while (isspace(str
[start
]) != 0 && start
<= end
) {
250 while (isspace(str
[end
]) != 0 && start
<= end
) {
254 return str
.substr(start
, end
- start
+ 1);
256 return std::string();
261 bool ParseBoolean(const std::string
& type
, const std::string
& value
) {
262 if (value
== "true" || value
== "1") {
264 } else if (value
== "false" || value
== "0") {
267 throw std::invalid_argument(type
);
270 uint32_t ParseUint32(const std::string
& value
) {
271 uint64_t num
= ParseUint64(value
);
272 if ((num
>> 32LL) == 0) {
273 return static_cast<uint32_t>(num
);
275 throw std::out_of_range(value
);
281 uint64_t ParseUint64(const std::string
& value
) {
284 uint64_t num
= std::stoull(value
.c_str(), &endchar
);
287 uint64_t num
= std::strtoul(value
.c_str(), &endptr
, 0);
288 endchar
= endptr
- value
.c_str();
291 if (endchar
< value
.length()) {
292 char c
= value
[endchar
];
293 if (c
== 'k' || c
== 'K')
295 else if (c
== 'm' || c
== 'M')
297 else if (c
== 'g' || c
== 'G')
299 else if (c
== 't' || c
== 'T')
306 int ParseInt(const std::string
& value
) {
309 int num
= std::stoi(value
.c_str(), &endchar
);
312 int num
= std::strtoul(value
.c_str(), &endptr
, 0);
313 endchar
= endptr
- value
.c_str();
316 if (endchar
< value
.length()) {
317 char c
= value
[endchar
];
318 if (c
== 'k' || c
== 'K')
320 else if (c
== 'm' || c
== 'M')
322 else if (c
== 'g' || c
== 'G')
329 double ParseDouble(const std::string
& value
) {
331 return std::stod(value
);
333 return std::strtod(value
.c_str(), 0);
337 size_t ParseSizeT(const std::string
& value
) {
338 return static_cast<size_t>(ParseUint64(value
));
341 std::vector
<int> ParseVectorInt(const std::string
& value
) {
342 std::vector
<int> result
;
344 while (start
< value
.size()) {
345 size_t end
= value
.find(':', start
);
346 if (end
== std::string::npos
) {
347 result
.push_back(ParseInt(value
.substr(start
)));
350 result
.push_back(ParseInt(value
.substr(start
, end
- start
)));
357 bool SerializeIntVector(const std::vector
<int>& vec
, std::string
* value
) {
359 for (size_t i
= 0; i
< vec
.size(); ++i
) {
363 *value
+= ToString(vec
[i
]);
368 } // namespace rocksdb