osrm-backend/include/util/string_util.hpp
Daniel J. Hofmann 21804aecdb Prefer inline over static inline for free standing functions
When you mark free standing functions as `static inline` instead
of just `inline` they can not get merged across TUs and therefore
produce code bloat which is bad for the binaries size, the CPUs
instruction cache, and so on.

Please also see the discussion at:

- https://groups.google.com/forum/#!topic/mozilla.dev.platform/Ulw9HoZbSyQ
- http://stackoverflow.com/a/12836392

Note that non-fully specialized templates (i.e. with a kind of at
least `Template :: * -> *`) are `inline` by default.
2016-01-08 23:33:31 +01:00

133 lines
3.1 KiB
C++

#ifndef STRING_UTIL_HPP
#define STRING_UTIL_HPP
#include <cctype>
#include <random>
#include <string>
#include <vector>
namespace osrm
{
namespace util
{
// precision: position after decimal point
// length: maximum number of digits including comma and decimals
// work with negative values to prevent overflowing when taking -value
template <int length, int precision> char *printInt(char *buffer, int value)
{
static_assert(length > 0, "length must be positive");
static_assert(precision > 0, "precision must be positive");
const bool minus = [&value]
{
if (value >= 0)
{
value = -value;
return false;
}
return true;
}();
buffer += length - 1;
for (int i = 0; i < precision; ++i)
{
*buffer = '0' - (value % 10);
value /= 10;
--buffer;
}
*buffer = '.';
--buffer;
for (int i = precision + 1; i < length; ++i)
{
*buffer = '0' - (value % 10);
value /= 10;
if (value == 0)
{
break;
}
--buffer;
}
if (minus)
{
--buffer;
*buffer = '-';
}
return buffer;
}
inline std::string escape_JSON(const std::string &input)
{
// escape and skip reallocations if possible
std::string output;
output.reserve(input.size() + 4); // +4 assumes two backslashes on avg
for (const char letter : input)
{
switch (letter)
{
case '\\':
output += "\\\\";
break;
case '"':
output += "\\\"";
break;
case '/':
output += "\\/";
break;
case '\b':
output += "\\b";
break;
case '\f':
output += "\\f";
break;
case '\n':
output += "\\n";
break;
case '\r':
output += "\\r";
break;
case '\t':
output += "\\t";
break;
default:
output.append(1, letter);
break;
}
}
return output;
}
inline std::size_t URIDecode(const std::string &input, std::string &output)
{
auto src_iter = std::begin(input);
const auto src_end = std::end(input);
output.resize(input.size() + 1);
std::size_t decoded_length = 0;
for (decoded_length = 0; src_iter != src_end; ++decoded_length)
{
if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) &&
isxdigit(src_iter[2]))
{
std::string::value_type a = src_iter[1];
std::string::value_type b = src_iter[2];
a -= src_iter[1] < 58 ? 48 : src_iter[1] < 71 ? 55 : 87;
b -= src_iter[2] < 58 ? 48 : src_iter[2] < 71 ? 55 : 87;
output[decoded_length] = 16 * a + b;
src_iter += 3;
continue;
}
output[decoded_length] = *src_iter++;
}
output.resize(decoded_length);
return decoded_length;
}
inline std::size_t URIDecodeInPlace(std::string &URI) { return URIDecode(URI, URI); }
}
}
#endif // STRING_UTIL_HPP