14#ifndef OPENVPN_COMMON_STRING_H
15#define OPENVPN_COMMON_STRING_H
35#ifdef OPENVPN_PLATFORM_WIN
36 return ::_stricmp(s1, s2);
38 return ::strcasecmp(s1, s2);
42inline int strcasecmp(
const std::string &s1,
const char *s2)
47inline int strcasecmp(
const char *s1,
const std::string &s2)
52inline int strcasecmp(
const std::string &s1,
const std::string &s2)
58inline void strncpynt(
char *dest,
const char *src,
size_t maxlen)
60 strncpy(dest, src, maxlen);
67inline void copy_fill(
void *dest,
const std::string &src,
const size_t dest_size)
71 const size_t ncopy = std::min(dest_size - 1, src.length());
72 std::memcpy(dest, src.c_str(), ncopy);
73 std::memset(
static_cast<unsigned char *
>(dest) + ncopy, 0, dest_size - ncopy);
83template <
typename STRING>
86 if (prefix.length() <
str.length())
87 return str[prefix.length()] == delim &&
str.starts_with(prefix);
92template <
typename STRING>
95 return str.ends_with(
'\n');
99template <
typename STRING>
104 const char c =
str.back();
105 return c ==
'\n' || c ==
'\r';
112inline std::string
add_leading(
const std::string &
str,
const size_t min_len,
const char c)
114 if (min_len <=
str.length())
116 size_t len = min_len -
str.length();
118 ret.reserve(min_len);
128 if (
str.ends_with(c))
136 if (!
str.ends_with(c))
143 if (
str.ends_with(
"\r\n"))
145 else if (
str.ends_with(
'\r'))
147 else if (
str.ends_with(
'\n'))
166 if (
str.empty() ||
str.ends_with(c))
172template <
typename STRING>
198 while (len > 0 &&
str[len - 1] ==
'\0')
206 return str.find_first_of(
'\n') != std::string::npos;
211inline std::string
to_delim(
const std::string &
str,
const char delim)
213 const size_t pos =
str.find_first_of(delim);
214 if (pos != std::string::npos)
215 return str.substr(0, pos);
241 return std::isspace(
static_cast<unsigned char>(c)) != 0;
246 return std::isdigit(
static_cast<unsigned char>(c)) != 0;
251 return std::isalpha(
static_cast<unsigned char>(c)) != 0;
256 return std::isalnum(
static_cast<unsigned char>(c)) != 0;
261 return std::isprint(
static_cast<unsigned char>(c)) != 0;
266 return std::isprint(c) != 0;
271 return std::iscntrl(
static_cast<unsigned char>(c)) != 0;
276 return std::iscntrl(c) != 0;
309 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
319 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
332 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
348 bool last_space =
true;
349 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
355 if (!(space && last_space))
359 if (last_space && !
ret.empty())
365inline std::string
repeat(
const char c,
size_t n)
381inline std::string
indent(
const std::string &
str,
const int first,
const int remaining)
384 int n_spaces = first;
392 n_spaces = remaining;
398inline std::string
replace_copy(
const std::string &
str,
const char from,
const char to)
401 ret.reserve(
str.length());
403 ret.push_back(c == from ? to : c);
410 for (
const auto &c :
str)
422 while ((c = *
str++) !=
'\0')
429inline std::string
unix2dos(
const std::string &
str,
const bool force_eol =
false)
432 bool last_char_was_cr =
false;
434 ret.reserve(
str.length() +
str.length() / 8);
435 for (std::string::const_iterator i =
str.begin(); i !=
str.end(); ++i)
438 if (c ==
'\n' && !last_char_was_cr)
441 last_char_was_cr = (c ==
'\r');
453 const typename T::value_type sep,
454 const int maxsplit = -1)
457 static_assert(std::is_same_v<T, std::string> || std::is_same_v<T, std::wstring>);
463 ret.reserve(maxsplit + 1);
465 for (
const auto c :
str)
467 if (c == sep && (maxsplit < 0 || nterms < maxsplit))
469 ret.push_back(std::move(term));
476 ret.push_back(std::move(term));
481inline auto join(
const T &strings,
482 const typename T::value_type &delim,
483 const bool tail =
false)
486 static_assert(std::is_same_v<typename T::value_type, std::string> || std::is_same_v<typename T::value_type, std::wstring>);
487 typename T::value_type
ret;
489 for (
const auto &s : strings)
496 if (tail && !
ret.empty())
501inline std::vector<std::string>
from_argv(
int argc,
char *argv[],
const bool skip_first)
503 std::vector<std::string>
ret;
504 for (
int i = (skip_first ? 1 : 0); i < argc; ++i)
505 ret.emplace_back(argv[i]);
511 for (
size_t i = 0; i <
str.length(); ++i)
514 return str.substr(i);
516 return std::string();
521 for (
size_t i = 0; i <
str.length(); ++i)
525 size_t last_nonspace = i;
526 for (
size_t j = i + 1; j <
str.length(); ++j)
531 return str.substr(i, last_nonspace - i + 1);
534 return std::string();
541 ret.reserve(
str.length());
542 for (
const auto &c :
str)
543 ret.push_back(std::toupper(c, loc));
551 ret.reserve(
str.length());
552 for (
const auto &c :
str)
553 ret.push_back(std::tolower(c, loc));
583 ret.reserve(
str.length() + 1);
586 bool in_space =
false;
634 ret.reserve(
str.length());
635 for (
const auto c :
str)
658template <
typename... ArgsT>
659inline auto args_to_string(std::string_view delim, ArgsT &&...args) -> std::string
662 ((result += std::string(result.empty() ?
"" : delim) + fmt::format(
"{}", args)), ...);
680template <
typename... ArgsT>
681inline auto format_safe(std::string format, ArgsT &&...args)
noexcept -> std::optional<std::string>
685 return fmt::vformat(format, fmt::make_format_args(args...));
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)
auto args_to_string(std::string_view delim, ArgsT &&...args) -> std::string
Convert variadic arguments to a string.
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 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)
auto format_safe(std::string format, ArgsT &&...args) noexcept -> std::optional< std::string >
Format a string with error handling.
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)
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'