common/stringutility.h (196 lines of code) (raw):
#pragma once
#include "logger.h"
#include "tokenize.h"
#include "schema.h"
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/hex.hpp>
#include <inttypes.h>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
#include <sstream>
#include <cctype>
namespace swss {
template<typename T>
static inline void lexical_convert(const std::string &str, T &t)
{
t = boost::lexical_cast<T>(str);
}
namespace lexical_convert_detail
{
template <typename T, typename... Args>
void lexical_convert(
std::vector<std::string>::const_iterator begin,
std::vector<std::string>::const_iterator end,
T &t)
{
if (begin == end)
{
SWSS_LOG_THROW("Insufficient corpus");
}
auto cur_itr = begin++;
if (begin != end)
{
SWSS_LOG_THROW("Too much corpus");
}
swss::lexical_convert(*cur_itr, t);
}
template <typename T, typename... Args>
void lexical_convert(
std::vector<std::string>::const_iterator begin,
std::vector<std::string>::const_iterator end,
T &t,
Args &... args)
{
if (begin == end)
{
SWSS_LOG_THROW("Insufficient corpus");
}
swss::lexical_convert(*(begin++), t);
return lexical_convert(begin, end, args...);
}
}
template <typename T, typename... Args>
void lexical_convert(const std::vector<std::string> &strs, T &t, Args &... args)
{
lexical_convert_detail::lexical_convert(strs.begin(), strs.end(), t, args...);
}
namespace join_detail
{
template <typename D, typename T>
void join(std::ostringstream &ostream, D, const T &t)
{
ostream << t;
}
template <typename D, typename T, typename... Args>
void join(std::ostringstream &ostream, const D &delimiter, const T &t, const Args &... args)
{
ostream << t << delimiter;
join(ostream, delimiter, args...);
}
template <typename D, typename Iterator>
void join(std::ostringstream &ostream, const D &delimiter, Iterator begin, Iterator end)
{
if (begin == end)
{
return;
}
ostream << *begin;
while(++begin != end)
{
ostream << delimiter << *begin;
}
}
}
template <typename D, typename T, typename... Args>
static inline std::string join(const D &delimiter, const T &t, const Args &... args)
{
std::ostringstream ostream;
join_detail::join(ostream, delimiter, t, args...);
return ostream.str();
}
template <typename D, typename Iterator>
static inline std::string join(const D &delimiter, Iterator begin, Iterator end)
{
std::ostringstream ostream;
join_detail::join(ostream, delimiter, begin, end);
return ostream.str();
}
template <typename D, typename Iterator>
static inline std::string join(const D &delimiter, char beginsym, char endsym, Iterator begin, Iterator end)
{
std::ostringstream ostream;
ostream << beginsym;
join_detail::join(ostream, delimiter, begin, end);
ostream << endsym;
return ostream.str();
}
static inline bool hex_to_binary(const std::string &hex_str, std::uint8_t *buffer, size_t buffer_length)
{
if (hex_str.length() != (buffer_length * 2))
{
SWSS_LOG_DEBUG("Buffer length isn't sufficient");
return false;
}
try
{
boost::algorithm::unhex(hex_str, buffer);
}
catch(const boost::algorithm::non_hex_input &e)
{
SWSS_LOG_DEBUG("Invalid hex string %s", hex_str.c_str());
return false;
}
return true;
}
template<typename T>
static inline void hex_to_binary(const std::string &s, T &value)
{
return hex_to_binary(s, &value, sizeof(T));
}
static inline std::string binary_to_hex(const void *buffer, size_t length)
{
std::string s;
auto buf = static_cast<const std::uint8_t *>(buffer);
boost::algorithm::hex(
buf,
buf + length,
std::back_inserter<std::string>(s));
return s;
}
static inline std::string binary_to_printable(const void *buffer, size_t length)
{
std::string printable;
printable.reserve(length * 4);
auto buf = static_cast<const std::uint8_t *>(buffer);
for (size_t i = 0; i < length; i++)
{
std::uint8_t c = buf[i];
if (std::isprint(c))
{
if (c == '\\')
{
printable.push_back('\\');
printable.push_back('\\');
}
else
{
printable.push_back(c);
}
}
else if (std::isspace(c))
{
printable.push_back('\\');
if (c == '\n')
{
printable.push_back('n');
}
else if (c == '\r')
{
printable.push_back('r');
}
else if (c == '\t')
{
printable.push_back('t');
}
else if (c == '\v')
{
printable.push_back('v');
}
else if (c == '\f')
{
printable.push_back('f');
}
}
else
{
printable.push_back('\\');
printable.push_back('x');
printable.push_back("0123456789ABCDEF"[c >> 4]);
printable.push_back("0123456789ABCDEF"[c & 0xf]);
}
}
return printable;
}
}