Copyright 2014->2015
[folly.git] / folly / String.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <folly/String.h>
18
19 #include <folly/Format.h>
20 #include <folly/ScopeGuard.h>
21
22 #include <cerrno>
23 #include <cstdarg>
24 #include <cstring>
25 #include <stdexcept>
26 #include <iterator>
27 #include <cctype>
28 #include <glog/logging.h>
29
30 namespace folly {
31
32 namespace {
33
34 int stringAppendfImplHelper(char* buf,
35                             size_t bufsize,
36                             const char* format,
37                             va_list args) {
38   va_list args_copy;
39   va_copy(args_copy, args);
40   int bytes_used = vsnprintf(buf, bufsize, format, args_copy);
41   va_end(args_copy);
42   return bytes_used;
43 }
44
45 void stringAppendfImpl(std::string& output, const char* format, va_list args) {
46   // Very simple; first, try to avoid an allocation by using an inline
47   // buffer.  If that fails to hold the output string, allocate one on
48   // the heap, use it instead.
49   //
50   // It is hard to guess the proper size of this buffer; some
51   // heuristics could be based on the number of format characters, or
52   // static analysis of a codebase.  Or, we can just pick a number
53   // that seems big enough for simple cases (say, one line of text on
54   // a terminal) without being large enough to be concerning as a
55   // stack variable.
56   std::array<char, 128> inline_buffer;
57
58   int bytes_used = stringAppendfImplHelper(
59       inline_buffer.data(), inline_buffer.size(), format, args);
60   if (bytes_used < 0) {
61     throw std::runtime_error(to<std::string>(
62         "Invalid format string; snprintf returned negative "
63         "with format string: ",
64         format));
65   }
66
67   if (static_cast<size_t>(bytes_used) < inline_buffer.size()) {
68     output.append(inline_buffer.data(), bytes_used);
69     return;
70   }
71
72   // Couldn't fit.  Heap allocate a buffer, oh well.
73   std::unique_ptr<char[]> heap_buffer(new char[bytes_used + 1]);
74   int final_bytes_used =
75       stringAppendfImplHelper(heap_buffer.get(), bytes_used + 1, format, args);
76   // The second call should require the same length, which is 1 less
77   // than the buffer size (we don't keep the trailing \0 byte in our
78   // output string).
79   CHECK(bytes_used == final_bytes_used);
80
81   output.append(heap_buffer.get(), bytes_used);
82 }
83
84 } // anon namespace
85
86 std::string stringPrintf(const char* format, ...) {
87   va_list ap;
88   va_start(ap, format);
89   SCOPE_EXIT {
90     va_end(ap);
91   };
92   return stringVPrintf(format, ap);
93 }
94
95 std::string stringVPrintf(const char* format, va_list ap) {
96   std::string ret;
97   stringAppendfImpl(ret, format, ap);
98   return ret;
99 }
100
101 // Basic declarations; allow for parameters of strings and string
102 // pieces to be specified.
103 std::string& stringAppendf(std::string* output, const char* format, ...) {
104   va_list ap;
105   va_start(ap, format);
106   SCOPE_EXIT {
107     va_end(ap);
108   };
109   return stringVAppendf(output, format, ap);
110 }
111
112 std::string& stringVAppendf(std::string* output,
113                             const char* format,
114                             va_list ap) {
115   stringAppendfImpl(*output, format, ap);
116   return *output;
117 }
118
119 void stringPrintf(std::string* output, const char* format, ...) {
120   va_list ap;
121   va_start(ap, format);
122   SCOPE_EXIT {
123     va_end(ap);
124   };
125   return stringVPrintf(output, format, ap);
126 }
127
128 void stringVPrintf(std::string* output, const char* format, va_list ap) {
129   output->clear();
130   stringAppendfImpl(*output, format, ap);
131 };
132
133 namespace {
134
135 struct PrettySuffix {
136   const char* suffix;
137   double val;
138 };
139
140 const PrettySuffix kPrettyTimeSuffixes[] = {
141   { "s ", 1e0L },
142   { "ms", 1e-3L },
143   { "us", 1e-6L },
144   { "ns", 1e-9L },
145   { "ps", 1e-12L },
146   { "s ", 0 },
147   { 0, 0 },
148 };
149
150 const PrettySuffix kPrettyBytesMetricSuffixes[] = {
151   { "TB", 1e12L },
152   { "GB", 1e9L },
153   { "MB", 1e6L },
154   { "kB", 1e3L },
155   { "B ", 0L },
156   { 0, 0 },
157 };
158
159 const PrettySuffix kPrettyBytesBinarySuffixes[] = {
160   { "TB", int64_t(1) << 40 },
161   { "GB", int64_t(1) << 30 },
162   { "MB", int64_t(1) << 20 },
163   { "kB", int64_t(1) << 10 },
164   { "B ", 0L },
165   { 0, 0 },
166 };
167
168 const PrettySuffix kPrettyBytesBinaryIECSuffixes[] = {
169   { "TiB", int64_t(1) << 40 },
170   { "GiB", int64_t(1) << 30 },
171   { "MiB", int64_t(1) << 20 },
172   { "KiB", int64_t(1) << 10 },
173   { "B  ", 0L },
174   { 0, 0 },
175 };
176
177 const PrettySuffix kPrettyUnitsMetricSuffixes[] = {
178   { "tril", 1e12L },
179   { "bil",  1e9L },
180   { "M",    1e6L },
181   { "k",    1e3L },
182   { " ",      0  },
183   { 0, 0 },
184 };
185
186 const PrettySuffix kPrettyUnitsBinarySuffixes[] = {
187   { "T", int64_t(1) << 40 },
188   { "G", int64_t(1) << 30 },
189   { "M", int64_t(1) << 20 },
190   { "k", int64_t(1) << 10 },
191   { " ", 0 },
192   { 0, 0 },
193 };
194
195 const PrettySuffix kPrettyUnitsBinaryIECSuffixes[] = {
196   { "Ti", int64_t(1) << 40 },
197   { "Gi", int64_t(1) << 30 },
198   { "Mi", int64_t(1) << 20 },
199   { "Ki", int64_t(1) << 10 },
200   { "  ", 0 },
201   { 0, 0 },
202 };
203
204 const PrettySuffix kPrettySISuffixes[] = {
205   { "Y", 1e24L },
206   { "Z", 1e21L },
207   { "E", 1e18L },
208   { "P", 1e15L },
209   { "T", 1e12L },
210   { "G", 1e9L },
211   { "M", 1e6L },
212   { "k", 1e3L },
213   { "h", 1e2L },
214   { "da", 1e1L },
215   { "d", 1e-1L },
216   { "c", 1e-2L },
217   { "m", 1e-3L },
218   { "u", 1e-6L },
219   { "n", 1e-9L },
220   { "p", 1e-12L },
221   { "f", 1e-15L },
222   { "a", 1e-18L },
223   { "z", 1e-21L },
224   { "y", 1e-24L },
225   { " ", 0 },
226   { 0, 0}
227 };
228
229 const PrettySuffix* const kPrettySuffixes[PRETTY_NUM_TYPES] = {
230   kPrettyTimeSuffixes,
231   kPrettyBytesMetricSuffixes,
232   kPrettyBytesBinarySuffixes,
233   kPrettyBytesBinaryIECSuffixes,
234   kPrettyUnitsMetricSuffixes,
235   kPrettyUnitsBinarySuffixes,
236   kPrettyUnitsBinaryIECSuffixes,
237   kPrettySISuffixes,
238 };
239
240 }  // namespace
241
242 std::string prettyPrint(double val, PrettyType type, bool addSpace) {
243   char buf[100];
244
245   // pick the suffixes to use
246   assert(type >= 0);
247   assert(type < PRETTY_NUM_TYPES);
248   const PrettySuffix* suffixes = kPrettySuffixes[type];
249
250   // find the first suffix we're bigger than -- then use it
251   double abs_val = fabs(val);
252   for (int i = 0; suffixes[i].suffix; ++i) {
253     if (abs_val >= suffixes[i].val) {
254       snprintf(buf, sizeof buf, "%.4g%s%s",
255                (suffixes[i].val ? (val / suffixes[i].val)
256                                 : val),
257                (addSpace ? " " : ""),
258                suffixes[i].suffix);
259       return std::string(buf);
260     }
261   }
262
263   // no suffix, we've got a tiny value -- just print it in sci-notation
264   snprintf(buf, sizeof buf, "%.4g", val);
265   return std::string(buf);
266 }
267
268 //TODO:
269 //1) Benchmark & optimize
270 double prettyToDouble(folly::StringPiece *const prettyString,
271                       const PrettyType type) {
272   double value = folly::to<double>(prettyString);
273   while (prettyString->size() > 0 && std::isspace(prettyString->front())) {
274     prettyString->advance(1); //Skipping spaces between number and suffix
275   }
276   const PrettySuffix* suffixes = kPrettySuffixes[type];
277   int longestPrefixLen = -1;
278   int bestPrefixId = -1;
279   for (int j = 0 ; suffixes[j].suffix; ++j) {
280     if (suffixes[j].suffix[0] == ' '){//Checking for " " -> number rule.
281       if (longestPrefixLen == -1) {
282         longestPrefixLen = 0; //No characters to skip
283         bestPrefixId = j;
284       }
285     } else if (prettyString->startsWith(suffixes[j].suffix)) {
286       int suffixLen = strlen(suffixes[j].suffix);
287       //We are looking for a longest suffix matching prefix of the string
288       //after numeric value. We need this in case suffixes have common prefix.
289       if (suffixLen > longestPrefixLen) {
290         longestPrefixLen = suffixLen;
291         bestPrefixId = j;
292       }
293     }
294   }
295   if (bestPrefixId == -1) { //No valid suffix rule found
296     throw std::invalid_argument(folly::to<std::string>(
297             "Unable to parse suffix \"",
298             prettyString->toString(), "\""));
299   }
300   prettyString->advance(longestPrefixLen);
301   return suffixes[bestPrefixId].val ? value * suffixes[bestPrefixId].val :
302                                       value;
303 }
304
305 double prettyToDouble(folly::StringPiece prettyString, const PrettyType type){
306   double result = prettyToDouble(&prettyString, type);
307   detail::enforceWhitespace(prettyString.data(),
308                             prettyString.data() + prettyString.size());
309   return result;
310 }
311
312 std::string hexDump(const void* ptr, size_t size) {
313   std::ostringstream os;
314   hexDump(ptr, size, std::ostream_iterator<StringPiece>(os, "\n"));
315   return os.str();
316 }
317
318 fbstring errnoStr(int err) {
319   int savedErrno = errno;
320
321   // Ensure that we reset errno upon exit.
322   auto guard(makeGuard([&] { errno = savedErrno; }));
323
324   char buf[1024];
325   buf[0] = '\0';
326
327   fbstring result;
328
329   // https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/strerror_r.3.html
330   // http://www.kernel.org/doc/man-pages/online/pages/man3/strerror.3.html
331 #if defined(__APPLE__) || defined(__FreeBSD__) ||\
332     defined(__CYGWIN__) || defined(__ANDROID__) ||\
333     ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
334   // Using XSI-compatible strerror_r
335   int r = strerror_r(err, buf, sizeof(buf));
336
337   // OSX/FreeBSD use EINVAL and Linux uses -1 so just check for non-zero
338   if (r != 0) {
339     result = to<fbstring>(
340       "Unknown error ", err,
341       " (strerror_r failed with error ", errno, ")");
342   } else {
343     result.assign(buf);
344   }
345 #else
346   // Using GNU strerror_r
347   result.assign(strerror_r(err, buf, sizeof(buf)));
348 #endif
349
350   return result;
351 }
352
353 StringPiece skipWhitespace(StringPiece sp) {
354   // Spaces other than ' ' characters are less common but should be
355   // checked.  This configuration where we loop on the ' '
356   // separately from oddspaces was empirically fastest.
357   auto oddspace = [] (char c) {
358     return c == '\n' || c == '\t' || c == '\r';
359   };
360
361 loop:
362   for (; !sp.empty() && sp.front() == ' '; sp.pop_front()) {
363   }
364   if (!sp.empty() && oddspace(sp.front())) {
365     sp.pop_front();
366     goto loop;
367   }
368
369   return sp;
370 }
371
372 namespace {
373
374 void toLowerAscii8(char& c) {
375   // Branchless tolower, based on the input-rotating trick described
376   // at http://www.azillionmonkeys.com/qed/asmexample.html
377   //
378   // This algorithm depends on an observation: each uppercase
379   // ASCII character can be converted to its lowercase equivalent
380   // by adding 0x20.
381
382   // Step 1: Clear the high order bit. We'll deal with it in Step 5.
383   unsigned char rotated = c & 0x7f;
384   // Currently, the value of rotated, as a function of the original c is:
385   //   below 'A':   0- 64
386   //   'A'-'Z':    65- 90
387   //   above 'Z':  91-127
388
389   // Step 2: Add 0x25 (37)
390   rotated += 0x25;
391   // Now the value of rotated, as a function of the original c is:
392   //   below 'A':   37-101
393   //   'A'-'Z':    102-127
394   //   above 'Z':  128-164
395
396   // Step 3: clear the high order bit
397   rotated &= 0x7f;
398   //   below 'A':   37-101
399   //   'A'-'Z':    102-127
400   //   above 'Z':    0- 36
401
402   // Step 4: Add 0x1a (26)
403   rotated += 0x1a;
404   //   below 'A':   63-127
405   //   'A'-'Z':    128-153
406   //   above 'Z':   25- 62
407
408   // At this point, note that only the uppercase letters have been
409   // transformed into values with the high order bit set (128 and above).
410
411   // Step 5: Shift the high order bit 2 spaces to the right: the spot
412   // where the only 1 bit in 0x20 is.  But first, how we ignored the
413   // high order bit of the original c in step 1?  If that bit was set,
414   // we may have just gotten a false match on a value in the range
415   // 128+'A' to 128+'Z'.  To correct this, need to clear the high order
416   // bit of rotated if the high order bit of c is set.  Since we don't
417   // care about the other bits in rotated, the easiest thing to do
418   // is invert all the bits in c and bitwise-and them with rotated.
419   rotated &= ~c;
420   rotated >>= 2;
421
422   // Step 6: Apply a mask to clear everything except the 0x20 bit
423   // in rotated.
424   rotated &= 0x20;
425
426   // At this point, rotated is 0x20 if c is 'A'-'Z' and 0x00 otherwise
427
428   // Step 7: Add rotated to c
429   c += rotated;
430 }
431
432 void toLowerAscii32(uint32_t& c) {
433   // Besides being branchless, the algorithm in toLowerAscii8() has another
434   // interesting property: None of the addition operations will cause
435   // an overflow in the 8-bit value.  So we can pack four 8-bit values
436   // into a uint32_t and run each operation on all four values in parallel
437   // without having to use any CPU-specific SIMD instructions.
438   uint32_t rotated = c & uint32_t(0x7f7f7f7fL);
439   rotated += uint32_t(0x25252525L);
440   rotated &= uint32_t(0x7f7f7f7fL);
441   rotated += uint32_t(0x1a1a1a1aL);
442
443   // Step 5 involves a shift, so some bits will spill over from each
444   // 8-bit value into the next.  But that's okay, because they're bits
445   // that will be cleared by the mask in step 6 anyway.
446   rotated &= ~c;
447   rotated >>= 2;
448   rotated &= uint32_t(0x20202020L);
449   c += rotated;
450 }
451
452 void toLowerAscii64(uint64_t& c) {
453   // 64-bit version of toLower32
454   uint64_t rotated = c & uint64_t(0x7f7f7f7f7f7f7f7fL);
455   rotated += uint64_t(0x2525252525252525L);
456   rotated &= uint64_t(0x7f7f7f7f7f7f7f7fL);
457   rotated += uint64_t(0x1a1a1a1a1a1a1a1aL);
458   rotated &= ~c;
459   rotated >>= 2;
460   rotated &= uint64_t(0x2020202020202020L);
461   c += rotated;
462 }
463
464 } // anon namespace
465
466 void toLowerAscii(char* str, size_t length) {
467   static const size_t kAlignMask64 = 7;
468   static const size_t kAlignMask32 = 3;
469
470   // Convert a character at a time until we reach an address that
471   // is at least 32-bit aligned
472   size_t n = (size_t)str;
473   n &= kAlignMask32;
474   n = std::min(n, length);
475   size_t offset = 0;
476   if (n != 0) {
477     n = std::min(4 - n, length);
478     do {
479       toLowerAscii8(str[offset]);
480       offset++;
481     } while (offset < n);
482   }
483
484   n = (size_t)(str + offset);
485   n &= kAlignMask64;
486   if ((n != 0) && (offset + 4 <= length)) {
487     // The next address is 32-bit aligned but not 64-bit aligned.
488     // Convert the next 4 bytes in order to get to the 64-bit aligned
489     // part of the input.
490     toLowerAscii32(*(uint32_t*)(str + offset));
491     offset += 4;
492   }
493
494   // Convert 8 characters at a time
495   while (offset + 8 <= length) {
496     toLowerAscii64(*(uint64_t*)(str + offset));
497     offset += 8;
498   }
499
500   // Convert 4 characters at a time
501   while (offset + 4 <= length) {
502     toLowerAscii32(*(uint32_t*)(str + offset));
503     offset += 4;
504   }
505
506   // Convert any characters remaining after the last 4-byte aligned group
507   while (offset < length) {
508     toLowerAscii8(str[offset]);
509     offset++;
510   }
511 }
512
513 namespace detail {
514
515 size_t hexDumpLine(const void* ptr, size_t offset, size_t size,
516                    std::string& line) {
517   // Line layout:
518   // 8: address
519   // 1: space
520   // (1+2)*16: hex bytes, each preceded by a space
521   // 1: space separating the two halves
522   // 3: "  |"
523   // 16: characters
524   // 1: "|"
525   // Total: 78
526   line.clear();
527   line.reserve(78);
528   const uint8_t* p = reinterpret_cast<const uint8_t*>(ptr) + offset;
529   size_t n = std::min(size - offset, size_t(16));
530   format("{:08x} ", offset).appendTo(line);
531
532   for (size_t i = 0; i < n; i++) {
533     if (i == 8) {
534       line.push_back(' ');
535     }
536     format(" {:02x}", p[i]).appendTo(line);
537   }
538
539   // 3 spaces for each byte we're not printing, one separating the halves
540   // if necessary
541   line.append(3 * (16 - n) + (n <= 8), ' ');
542   line.append("  |");
543
544   for (size_t i = 0; i < n; i++) {
545     char c = (p[i] >= 32 && p[i] <= 126 ? static_cast<char>(p[i]) : '.');
546     line.push_back(c);
547   }
548   line.append(16 - n, ' ');
549   line.push_back('|');
550   DCHECK_EQ(line.size(), 78);
551
552   return n;
553 }
554
555 } // namespace detail
556
557 }   // namespace folly
558
559 #ifdef FOLLY_DEFINED_DMGL
560 # undef FOLLY_DEFINED_DMGL
561 # undef DMGL_NO_OPTS
562 # undef DMGL_PARAMS
563 # undef DMGL_ANSI
564 # undef DMGL_JAVA
565 # undef DMGL_VERBOSE
566 # undef DMGL_TYPES
567 # undef DMGL_RET_POSTFIX
568 #endif