]>
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 both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 #include "util/string_util.h"
8 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
23 #include "rocksdb/env.h"
24 #include "port/port.h"
25 #include "rocksdb/slice.h"
29 const std::string kNullptrString
= "nullptr";
31 std::vector
<std::string
> StringSplit(const std::string
& arg
, char delim
) {
32 std::vector
<std::string
> splits
;
33 std::stringstream
ss(arg
);
35 while (std::getline(ss
, item
, delim
)) {
36 splits
.push_back(item
);
41 // for micros < 10ms, print "XX us".
42 // for micros < 10sec, print "XX ms".
43 // for micros >= 10 sec, print "XX sec".
44 // for micros <= 1 hour, print Y:X M:S".
45 // for micros > 1 hour, print Z:Y:X H:M:S".
46 int AppendHumanMicros(uint64_t micros
, char* output
, int len
,
48 if (micros
< 10000 && !fixed_format
) {
49 return snprintf(output
, len
, "%" PRIu64
" us", micros
);
50 } else if (micros
< 10000000 && !fixed_format
) {
51 return snprintf(output
, len
, "%.3lf ms",
52 static_cast<double>(micros
) / 1000);
53 } else if (micros
< 1000000l * 60 && !fixed_format
) {
54 return snprintf(output
, len
, "%.3lf sec",
55 static_cast<double>(micros
) / 1000000);
56 } else if (micros
< 1000000ll * 60 * 60 && !fixed_format
) {
57 return snprintf(output
, len
, "%02" PRIu64
":%05.3f M:S",
58 micros
/ 1000000 / 60,
59 static_cast<double>(micros
% 60000000) / 1000000);
61 return snprintf(output
, len
, "%02" PRIu64
":%02" PRIu64
":%05.3f H:M:S",
62 micros
/ 1000000 / 3600, (micros
/ 1000000 / 60) % 60,
63 static_cast<double>(micros
% 60000000) / 1000000);
67 // for sizes >=10TB, print "XXTB"
68 // for sizes >=10GB, print "XXGB"
70 // append file size summary to output and return the len
71 int AppendHumanBytes(uint64_t bytes
, char* output
, int len
) {
72 const uint64_t ull10
= 10;
73 if (bytes
>= ull10
<< 40) {
74 return snprintf(output
, len
, "%" PRIu64
"TB", bytes
>> 40);
75 } else if (bytes
>= ull10
<< 30) {
76 return snprintf(output
, len
, "%" PRIu64
"GB", bytes
>> 30);
77 } else if (bytes
>= ull10
<< 20) {
78 return snprintf(output
, len
, "%" PRIu64
"MB", bytes
>> 20);
79 } else if (bytes
>= ull10
<< 10) {
80 return snprintf(output
, len
, "%" PRIu64
"KB", bytes
>> 10);
82 return snprintf(output
, len
, "%" PRIu64
"B", bytes
);
86 void AppendNumberTo(std::string
* str
, uint64_t num
) {
88 snprintf(buf
, sizeof(buf
), "%" PRIu64
, num
);
92 void AppendEscapedStringTo(std::string
* str
, const Slice
& value
) {
93 for (size_t i
= 0; i
< value
.size(); i
++) {
95 if (c
>= ' ' && c
<= '~') {
99 snprintf(buf
, sizeof(buf
), "\\x%02x",
100 static_cast<unsigned int>(c
) & 0xff);
106 std::string
NumberToString(uint64_t num
) {
108 AppendNumberTo(&r
, num
);
112 std::string
NumberToHumanString(int64_t num
) {
114 int64_t absnum
= num
< 0 ? -num
: num
;
115 if (absnum
< 10000) {
116 snprintf(buf
, sizeof(buf
), "%" PRIi64
, num
);
117 } else if (absnum
< 10000000) {
118 snprintf(buf
, sizeof(buf
), "%" PRIi64
"K", num
/ 1000);
119 } else if (absnum
< 10000000000LL) {
120 snprintf(buf
, sizeof(buf
), "%" PRIi64
"M", num
/ 1000000);
122 snprintf(buf
, sizeof(buf
), "%" PRIi64
"G", num
/ 1000000000);
124 return std::string(buf
);
127 std::string
BytesToHumanString(uint64_t bytes
) {
128 const char* size_name
[] = {"KB", "MB", "GB", "TB"};
129 double final_size
= static_cast<double>(bytes
);
132 // always start with KB
136 while (size_idx
< 3 && final_size
>= 1024) {
142 snprintf(buf
, sizeof(buf
), "%.2f %s", final_size
, size_name
[size_idx
]);
143 return std::string(buf
);
146 std::string
EscapeString(const Slice
& value
) {
148 AppendEscapedStringTo(&r
, value
);
152 bool ConsumeDecimalNumber(Slice
* in
, uint64_t* val
) {
155 while (!in
->empty()) {
157 if (c
>= '0' && c
<= '9') {
159 const unsigned int delta
= (c
- '0');
160 static const uint64_t kMaxUint64
= ~static_cast<uint64_t>(0);
161 if (v
> kMaxUint64
/ 10 ||
162 (v
== kMaxUint64
/ 10 && delta
> kMaxUint64
% 10)) {
166 v
= (v
* 10) + delta
;
167 in
->remove_prefix(1);
176 bool isSpecialChar(const char c
) {
177 if (c
== '\\' || c
== '#' || c
== ':' || c
== '\r' || c
== '\n') {
184 using CharMap
= std::pair
<char, char>;
187 char UnescapeChar(const char c
) {
188 static const CharMap convert_map
[] = {{'r', '\r'}, {'n', '\n'}};
190 auto iter
= std::find_if(std::begin(convert_map
), std::end(convert_map
),
191 [c
](const CharMap
& p
) { return p
.first
== c
; });
193 if (iter
== std::end(convert_map
)) {
199 char EscapeChar(const char c
) {
200 static const CharMap convert_map
[] = {{'\n', 'n'}, {'\r', 'r'}};
202 auto iter
= std::find_if(std::begin(convert_map
), std::end(convert_map
),
203 [c
](const CharMap
& p
) { return p
.first
== c
; });
205 if (iter
== std::end(convert_map
)) {
211 std::string
EscapeOptionString(const std::string
& raw_string
) {
213 for (auto c
: raw_string
) {
214 if (isSpecialChar(c
)) {
216 output
+= EscapeChar(c
);
225 std::string
UnescapeOptionString(const std::string
& escaped_string
) {
226 bool escaped
= false;
229 for (auto c
: escaped_string
) {
231 output
+= UnescapeChar(c
);
244 std::string
trim(const std::string
& str
) {
245 if (str
.empty()) return std::string();
247 size_t end
= str
.size() - 1;
248 while (isspace(str
[start
]) != 0 && start
< end
) {
251 while (isspace(str
[end
]) != 0 && start
< end
) {
255 return str
.substr(start
, end
- start
+ 1);
257 return std::string();
262 bool ParseBoolean(const std::string
& type
, const std::string
& value
) {
263 if (value
== "true" || value
== "1") {
265 } else if (value
== "false" || value
== "0") {
268 throw std::invalid_argument(type
);
271 uint32_t ParseUint32(const std::string
& value
) {
272 uint64_t num
= ParseUint64(value
);
273 if ((num
>> 32LL) == 0) {
274 return static_cast<uint32_t>(num
);
276 throw std::out_of_range(value
);
280 int32_t ParseInt32(const std::string
& value
) {
281 int64_t num
= ParseInt64(value
);
282 if (num
<= port::kMaxInt32
&& num
>= port::kMinInt32
) {
283 return static_cast<int32_t>(num
);
285 throw std::out_of_range(value
);
291 uint64_t ParseUint64(const std::string
& value
) {
294 uint64_t num
= std::stoull(value
.c_str(), &endchar
);
297 uint64_t num
= std::strtoul(value
.c_str(), &endptr
, 0);
298 endchar
= endptr
- value
.c_str();
301 if (endchar
< value
.length()) {
302 char c
= value
[endchar
];
303 if (c
== 'k' || c
== 'K')
305 else if (c
== 'm' || c
== 'M')
307 else if (c
== 'g' || c
== 'G')
309 else if (c
== 't' || c
== 'T')
316 int64_t ParseInt64(const std::string
& value
) {
319 int64_t num
= std::stoll(value
.c_str(), &endchar
);
322 int64_t num
= std::strtoll(value
.c_str(), &endptr
, 0);
323 endchar
= endptr
- value
.c_str();
326 if (endchar
< value
.length()) {
327 char c
= value
[endchar
];
328 if (c
== 'k' || c
== 'K')
330 else if (c
== 'm' || c
== 'M')
332 else if (c
== 'g' || c
== 'G')
334 else if (c
== 't' || c
== 'T')
341 int ParseInt(const std::string
& value
) {
344 int num
= std::stoi(value
.c_str(), &endchar
);
347 int num
= std::strtoul(value
.c_str(), &endptr
, 0);
348 endchar
= endptr
- value
.c_str();
351 if (endchar
< value
.length()) {
352 char c
= value
[endchar
];
353 if (c
== 'k' || c
== 'K')
355 else if (c
== 'm' || c
== 'M')
357 else if (c
== 'g' || c
== 'G')
364 double ParseDouble(const std::string
& value
) {
366 return std::stod(value
);
368 return std::strtod(value
.c_str(), 0);
372 size_t ParseSizeT(const std::string
& value
) {
373 return static_cast<size_t>(ParseUint64(value
));
376 std::vector
<int> ParseVectorInt(const std::string
& value
) {
377 std::vector
<int> result
;
379 while (start
< value
.size()) {
380 size_t end
= value
.find(':', start
);
381 if (end
== std::string::npos
) {
382 result
.push_back(ParseInt(value
.substr(start
)));
385 result
.push_back(ParseInt(value
.substr(start
, end
- start
)));
392 bool SerializeIntVector(const std::vector
<int>& vec
, std::string
* value
) {
394 for (size_t i
= 0; i
< vec
.size(); ++i
) {
398 *value
+= ToString(vec
[i
]);
403 } // namespace rocksdb