2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/String.h"
18 #include "folly/Format.h"
25 #include <glog/logging.h>
29 #if defined(__GNUG__) && __GNUG__ >= 4
31 # define FOLLY_DEMANGLE 1
35 // TODO(tudorb): Detect this with autoconf for the open-source version.
37 // __attribute__((weak)) doesn't work, because cplus_demangle_v3_callback
38 // is exported by an object file in libiberty.a, and the ELF spec says
39 // "The link editor does not extract archive members to resolve undefined weak
40 // symbols" (but, interestingly enough, will resolve undefined weak symbols
41 // with definitions from archive members that were extracted in order to
42 // resolve an undefined global (strong) symbol)
43 extern "C" int cplus_demangle_v3_callback(
45 int options, // We use DMGL_PARAMS | DMGL_TYPES, aka 0x11
46 void (*callback)(const char*, size_t, void*),
55 inline void stringPrintfImpl(std::string& output, const char* format,
57 // Tru to the space at the end of output for our output buffer.
58 // Find out write point then inflate its size temporarily to its
59 // capacity; we will later shrink it to the size needed to represent
60 // the formatted string. If this buffer isn't large enough, we do a
61 // resize and try again.
63 const auto write_point = output.size();
64 auto remaining = output.capacity() - write_point;
65 output.resize(output.capacity());
68 va_copy(args_copy, args);
69 int bytes_used = vsnprintf(&output[write_point], remaining, format,
73 throw std::runtime_error(
74 to<std::string>("Invalid format string; snprintf returned negative "
75 "with format string: ", format));
76 } else if (bytes_used < remaining) {
77 // There was enough room, just shrink and return.
78 output.resize(write_point + bytes_used);
80 output.resize(write_point + bytes_used + 1);
81 remaining = bytes_used + 1;
83 va_copy(args_copy, args);
84 bytes_used = vsnprintf(&output[write_point], remaining, format,
87 if (bytes_used + 1 != remaining) {
88 throw std::runtime_error(
89 to<std::string>("vsnprint retry did not manage to work "
90 "with format string: ", format));
92 output.resize(write_point + bytes_used);
98 std::string stringPrintf(const char* format, ...) {
99 // snprintf will tell us how large the output buffer should be, but
100 // we then have to call it a second time, which is costly. By
101 // guestimating the final size, we avoid the double snprintf in many
102 // cases, resulting in a performance win. We use this constructor
103 // of std::string to avoid a double allocation, though it does pad
104 // the resulting string with nul bytes. Our guestimation is twice
105 // the format string size, or 32 bytes, whichever is larger. This
106 // is a hueristic that doesn't affect correctness but attempts to be
107 // reasonably fast for the most common cases.
108 std::string ret(std::max(32UL, strlen(format) * 2), '\0');
112 va_start(ap, format);
113 stringPrintfImpl(ret, format, ap);
118 // Basic declarations; allow for parameters of strings and string
119 // pieces to be specified.
120 std::string& stringAppendf(std::string* output, const char* format, ...) {
122 va_start(ap, format);
123 stringPrintfImpl(*output, format, ap);
128 void stringPrintf(std::string* output, const char* format, ...) {
131 va_start(ap, format);
132 stringPrintfImpl(*output, format, ap);
138 struct PrettySuffix {
143 const PrettySuffix kPrettyTimeSuffixes[] = {
153 const PrettySuffix kPrettyBytesMetricSuffixes[] = {
162 const PrettySuffix kPrettyBytesBinarySuffixes[] = {
163 { "TB", int64_t(1) << 40 },
164 { "GB", int64_t(1) << 30 },
165 { "MB", int64_t(1) << 20 },
166 { "kB", int64_t(1) << 10 },
171 const PrettySuffix kPrettyBytesBinaryIECSuffixes[] = {
172 { "TiB", int64_t(1) << 40 },
173 { "GiB", int64_t(1) << 30 },
174 { "MiB", int64_t(1) << 20 },
175 { "KiB", int64_t(1) << 10 },
180 const PrettySuffix kPrettyUnitsMetricSuffixes[] = {
189 const PrettySuffix kPrettyUnitsBinarySuffixes[] = {
190 { "T", int64_t(1) << 40 },
191 { "G", int64_t(1) << 30 },
192 { "M", int64_t(1) << 20 },
193 { "k", int64_t(1) << 10 },
198 const PrettySuffix kPrettyUnitsBinaryIECSuffixes[] = {
199 { "Ti", int64_t(1) << 40 },
200 { "Gi", int64_t(1) << 30 },
201 { "Mi", int64_t(1) << 20 },
202 { "Ki", int64_t(1) << 10 },
207 const PrettySuffix* const kPrettySuffixes[PRETTY_NUM_TYPES] = {
209 kPrettyBytesMetricSuffixes,
210 kPrettyBytesBinarySuffixes,
211 kPrettyBytesBinaryIECSuffixes,
212 kPrettyUnitsMetricSuffixes,
213 kPrettyUnitsBinarySuffixes,
214 kPrettyUnitsBinaryIECSuffixes,
219 std::string prettyPrint(double val, PrettyType type, bool addSpace) {
222 // pick the suffixes to use
224 assert(type < PRETTY_NUM_TYPES);
225 const PrettySuffix* suffixes = kPrettySuffixes[type];
227 // find the first suffix we're bigger than -- then use it
228 double abs_val = fabs(val);
229 for (int i = 0; suffixes[i].suffix; ++i) {
230 if (abs_val >= suffixes[i].val) {
231 snprintf(buf, sizeof buf, "%.4g%s%s",
232 (suffixes[i].val ? (val / suffixes[i].val)
234 (addSpace ? " " : ""),
236 return std::string(buf);
240 // no suffix, we've got a tiny value -- just print it in sci-notation
241 snprintf(buf, sizeof buf, "%.4g", val);
242 return std::string(buf);
245 std::string hexDump(const void* ptr, size_t size) {
246 std::ostringstream os;
247 hexDump(ptr, size, std::ostream_iterator<StringPiece>(os, "\n"));
251 fbstring errnoStr(int err) {
252 int savedErrno = errno;
254 // Ensure that we reset errno upon exit.
255 auto guard(makeGuard([&] { errno = savedErrno; }));
262 // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/strerror_r.3.html
263 // http://www.kernel.org/doc/man-pages/online/pages/man3/strerror.3.html
264 #if defined(__APPLE__) || defined(__FreeBSD__) || \
265 ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
266 // Using XSI-compatible strerror_r
267 int r = strerror_r(err, buf, sizeof(buf));
269 // OSX/FreeBSD use EINVAL and Linux uses -1 so just check for non-zero
271 result = to<fbstring>(
272 "Unknown error ", err,
273 " (strerror_r failed with error ", errno, ")");
278 // Using GNU strerror_r
279 result.assign(strerror_r(err, buf, sizeof(buf)));
287 // glibc doesn't have strlcpy
288 size_t my_strlcpy(char* dest, const char* src, size_t size) {
289 size_t len = strlen(src);
291 size_t n = std::min(len, size - 1); // always null terminate!
292 memcpy(dest, src, n);
300 #ifdef FOLLY_DEMANGLE
302 fbstring demangle(const char* name) {
305 // malloc() memory for the demangled type name
306 char* demangled = abi::__cxa_demangle(name, nullptr, &len, &status);
310 // len is the length of the buffer (including NUL terminator and maybe
312 return fbstring(demangled, strlen(demangled), len, AcquireMallocatedString());
323 void demangleCallback(const char* str, size_t size, void* p) {
324 DemangleBuf* buf = static_cast<DemangleBuf*>(p);
325 size_t n = std::min(buf->remaining, size);
326 memcpy(buf->dest, str, n);
334 size_t demangle(const char* name, char* out, size_t outSize) {
337 dbuf.remaining = outSize ? outSize - 1 : 0; // leave room for null term
340 // Unlike most library functions, this returns 1 on success and 0 on failure
341 int status = cplus_demangle_v3_callback(
343 0x11, // DMGL_PARAMS | DMGL_TYPES
346 if (status == 0) { // failed, return original
347 return my_strlcpy(out, name, outSize);
357 fbstring demangle(const char* name) {
361 size_t demangle(const char* name, char* out, size_t outSize) {
362 return my_strlcpy(out, name, outSize);
366 #undef FOLLY_DEMANGLE
370 size_t hexDumpLine(const void* ptr, size_t offset, size_t size,
375 // (1+2)*16: hex bytes, each preceded by a space
376 // 1: space separating the two halves
383 const uint8_t* p = reinterpret_cast<const uint8_t*>(ptr) + offset;
384 size_t n = std::min(size - offset, size_t(16));
385 format("{:08x} ", offset).appendTo(line);
387 for (size_t i = 0; i < n; i++) {
391 format(" {:02x}", p[i]).appendTo(line);
394 // 3 spaces for each byte we're not printing, one separating the halves
396 line.append(3 * (16 - n) + (n <= 8), ' ');
399 for (size_t i = 0; i < n; i++) {
400 char c = (p[i] >= 32 && p[i] <= 126 ? static_cast<char>(p[i]) : '.');
403 line.append(16 - n, ' ');
405 DCHECK_EQ(line.size(), 78);
410 } // namespace detail