14#ifndef OPENVPN_COMMON_STRING_H
15#define OPENVPN_COMMON_STRING_H
31#ifdef OPENVPN_PLATFORM_WIN
32 return ::_stricmp(s1, s2);
34 return ::strcasecmp(s1, s2);
38inline int strcasecmp(
const std::string &s1,
const char *s2)
43inline int strcasecmp(
const char *s1,
const std::string &s2)
48inline int strcasecmp(
const std::string &s1,
const std::string &s2)
54inline void strncpynt(
char *dest,
const char *src,
size_t maxlen)
56 strncpy(dest, src, maxlen);
63inline void copy_fill(
void *dest,
const std::string &src,
const size_t dest_size)
67 const size_t ncopy = std::min(dest_size - 1, src.length());
68 std::memcpy(dest, src.c_str(), ncopy);
69 std::memset(
static_cast<unsigned char *
>(dest) + ncopy, 0, dest_size - ncopy);
78template <
typename STRING>
81 const size_t len =
str.length();
82 const size_t plen = prefix.length();
84 return std::memcmp(
str.c_str(), prefix.c_str(), plen) == 0;
89template <
typename STRING>
92 const size_t len =
str.length();
93 const size_t plen = std::strlen(prefix);
95 return std::memcmp(
str.c_str(), prefix, plen) == 0;
101template <
typename STRING>
104 if (prefix.length() <
str.length())
107 return prefix ==
str;
110template <
typename STRING>
113 const size_t len =
str.length();
114 const size_t slen = suffix.length();
116 return std::memcmp(
str.c_str() + (len - slen), suffix.c_str(), slen) == 0;
121template <
typename STRING>
124 const size_t len =
str.length();
125 const size_t slen = std::strlen(suffix);
127 return std::memcmp(
str.c_str() + (len - slen), suffix, slen) == 0;
133template <
typename STRING>
136 return str.length() &&
str.back() == c;
140template <
typename STRING>
147template <
typename STRING>
152 const char c =
str.back();
153 return c ==
'\n' || c ==
'\r';
161inline std::string
add_leading(
const std::string &
str,
const size_t min_len,
const char c)
163 if (min_len <=
str.length())
165 size_t len = min_len -
str.length();
167 ret.reserve(min_len);
223template <
typename STRING>
249 while (len > 0 &&
str[len - 1] ==
'\0')
257 return str.find_first_of(
'\n') != std::string::npos;
262inline std::string
to_delim(
const std::string &
str,
const char delim)
264 const size_t pos =
str.find_first_of(delim);
265 if (pos != std::string::npos)
266 return str.substr(0, pos);
281 return std::isspace(
static_cast<unsigned char>(c)) != 0;
286 return std::isdigit(
static_cast<unsigned char>(c)) != 0;
291 return std::isalpha(
static_cast<unsigned char>(c)) != 0;
296 return std::isalnum(
static_cast<unsigned char>(c)) != 0;
301 return std::isprint(
static_cast<unsigned char>(c)) != 0;
306 return std::isprint(c) != 0;
311 return std::iscntrl(
static_cast<unsigned char>(c)) != 0;
316 return std::iscntrl(c) != 0;
349 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
359 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
372 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
388 bool last_space =
true;
389 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
395 if (!(space && last_space))
399 if (last_space && !
ret.empty())
405inline std::string
repeat(
const char c,
size_t n)
421inline std::string
indent(
const std::string &
str,
const int first,
const int remaining)
424 int n_spaces = first;
432 n_spaces = remaining;
438inline std::string
replace_copy(
const std::string &
str,
const char from,
const char to)
441 ret.reserve(
str.length());
443 ret.push_back(c == from ? to : c);
450 for (
const auto &c :
str)
462 while ((c = *
str++) !=
'\0')
469inline std::string
unix2dos(
const std::string &
str,
const bool force_eol =
false)
472 bool last_char_was_cr =
false;
474 ret.reserve(
str.length() +
str.length() / 8);
475 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
478 if (c ==
'\n' && !last_char_was_cr)
481 last_char_was_cr = (c ==
'\r');
493 const typename T::value_type sep,
494 const int maxsplit = -1)
497 static_assert(std::is_same_v<T, std::string> || std::is_same_v<T, std::wstring>);
503 ret.reserve(maxsplit + 1);
505 for (
const auto c :
str)
507 if (c == sep && (maxsplit < 0 || nterms < maxsplit))
509 ret.push_back(std::move(term));
516 ret.push_back(std::move(term));
521inline auto join(
const T &strings,
522 const typename T::value_type &delim,
523 const bool tail =
false)
526 static_assert(std::is_same_v<typename T::value_type, std::string> || std::is_same_v<typename T::value_type, std::wstring>);
527 typename T::value_type
ret;
529 for (
const auto &s : strings)
536 if (tail && !
ret.empty())
541inline std::vector<std::string>
from_argv(
int argc,
char *argv[],
const bool skip_first)
543 std::vector<std::string>
ret;
544 for (
int i = (skip_first ? 1 : 0); i < argc; ++i)
545 ret.emplace_back(argv[i]);
551 for (
size_t i = 0; i <
str.length(); ++i)
554 return str.substr(i);
556 return std::string();
561 for (
size_t i = 0; i <
str.length(); ++i)
565 size_t last_nonspace = i;
566 for (
size_t j = i + 1; j <
str.length(); ++j)
571 return str.substr(i, last_nonspace - i + 1);
574 return std::string();
581 ret.reserve(
str.length());
582 for (
const auto &c :
str)
583 ret.push_back(std::toupper(c, loc));
591 ret.reserve(
str.length());
592 for (
const auto &c :
str)
593 ret.push_back(std::tolower(c, loc));
623 ret.reserve(
str.length() + 1);
626 bool in_space =
false;
674 ret.reserve(
str.length());
675 for (
const auto c :
str)
void strncpynt(char *dest, const char *src, size_t maxlen)
std::vector< std::string > from_argv(int argc, char *argv[], const bool skip_first)
std::string replace_copy(const std::string &str, const char from, const char to)
std::string remove_blanks(const std::string &str)
bool ends_with_crlf(const STRING &str)
bool is_alpha(const char c)
bool is_digit(const char c)
int strcasecmp(const char *s1, const char *s2)
bool contains_space(const std::string &str)
size_t len_without_trailing_nulls(const char *str, size_t len)
void add_trailing_crlf(std::string &str)
std::string add_trailing_unless_empty_copy(const std::string &str, const char c)
bool is_ctrl(const char c)
bool is_multiline(const std::string &str)
auto join(const T &strings, const typename T::value_type &delim, const bool tail=false)
void to_lower(std::string &str)
std::string remove_char(const std::string &str, const char remove)
bool ends_with_newline(const STRING &str)
void trim_crlf(STRING &str)
bool is_true(const std::string &str)
bool starts_with(const STRING &str, const std::string &prefix)
bool embedded_null(const char *str, size_t len)
std::string indent(const std::string &str, const int first, const int remaining)
std::string spaces(size_t n)
std::vector< T > split(const T &str, const typename T::value_type sep, const int maxsplit=-1)
void add_trailing(std::string &str, const char c)
std::string trim_copy(const std::string &str)
std::string add_trailing_copy(const std::string &str, const char c)
bool is_space(const char c)
std::string first_line(const std::string &str)
bool is_alphanumeric(const char c)
bool contains_non_space_ctrl(const std::string &str)
std::string unix2dos(const std::string &str, const bool force_eol=false)
bool ends_with(const STRING &str, const std::string &suffix)
void trim_left(std::string &str)
void to_upper(std::string &str)
void copy_fill(void *dest, const std::string &src, const size_t dest_size)
std::string repeat(const char c, size_t n)
std::string to_delim(const std::string &str, const char delim)
void trim(std::string &str)
std::string add_trailing_crlf_copy(std::string str)
std::string add_leading(const std::string &str, const size_t min_len, const char c)
bool starts_with_delim(const STRING &str, const std::string &prefix, const char delim)
std::string replace_spaces(const std::string &str, const char rep)
bool is_printable(const char c)
std::string to_lower_copy(const std::string &str)
bool is_empty(const std::string &str)
std::string reduce_spaces(const std::string &str, const char rep)
std::string trim_crlf_copy(std::string str)
std::string trim_left_copy(const std::string &str)
bool is_word(const std::string &str)
std::string to_upper_copy(const std::string &str)
std::string remove_spaces(const std::string &str)
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'