25#ifndef JAU_STRING_UTIL_HPP_
26#define JAU_STRING_UTIL_HPP_
36#include <unordered_map>
37#include <unordered_set>
61 return 0 != std::iscntrl(c) || 0 != std::isprint(c);
80 std::string
trim(
const std::string &s)
noexcept;
83 std::vector<std::string>
split_string(
const std::string &str,
const std::string &separator)
noexcept;
87 std::string
toLower(
const std::string &s)
noexcept;
126 SizeBoolPair
fromHexString(std::vector<uint8_t> &out,
const uint8_t hexstr[],
const size_t hexstr_len,
193 template<
class value_type>
200#if defined(__EMSCRIPTEN__)
202 const uintptr_t v_le =
reinterpret_cast<uintptr_t
>(v);
204 byteOrder, capitalization,
prefix);
206 const uintptr_t v_le =
jau::cpu_to_le(
reinterpret_cast<uintptr_t
>(v));
208 byteOrder, capitalization,
prefix);
224 template<
class u
int8_container_type>
226 std::convertible_to<typename uint8_container_type::value_type, uint8_t>
231 return toHexString((
const uint8_t *)bytes.data(), bytes.size(), byteOrder, capitalization, skipPrefix);
246 template<
class value_type>
256 byteOrder, capitalization,
prefix);
260 byteOrder, capitalization,
prefix);
292 SizeBoolPair
fromBitString(std::vector<uint8_t> &out,
const uint8_t bitstr[],
const size_t bitstr_len,
333 size_t bit_len=0) noexcept;
347 template<class uint8_container_type>
348 requires
jau::req::contiguous_container<uint8_container_type> &&
349 std::convertible_to<typename uint8_container_type::value_type, uint8_t>
352 return toBitString((
const uint8_t *)bytes.data(), bytes.size(), bitOrder,
prefix, bit_len);
367 template<
class value_type>
377 bitOrder,
prefix, bit_len);
381 bitOrder,
prefix, bit_len);
399 template<
class value_type,
400 std::enable_if_t<std::is_integral_v<value_type>,
402 std::string
to_decstring(
const value_type &v,
const char separator =
',',
const nsize_t width = 0) noexcept {
405 const size_t digit10_count2 = v_sign < 0 ? digit10_count1 - 1 : digit10_count1;
407 const size_t separator_count = separator ? (digit10_count1 - 1) / 3 : 0;
408 const size_t net_chars = digit10_count1 + separator_count;
409 const size_t total_chars = std::max<size_t>(width, net_chars);
410 std::string res(total_chars,
' ');
413 size_t char_iter = 0;
415 for (
size_t digit10_iter = 0; digit10_iter < digit10_count2 ; digit10_iter++ ) {
416 const int digit = v_sign < 0 ?
invert_sign(n % 10) : n % 10;
418 if ( separator && 0 < digit10_iter && 0 == digit10_iter % 3 ) {
419 res[total_chars - 1 - (char_iter++)] = separator;
421 res[total_chars - 1 - (char_iter++)] =
'0' + digit;
424 res[total_chars - 1 - (char_iter++)] =
'-';
446 template<
class value_type,
447 std::enable_if_t<std::is_integral_v<value_type> &&
448 std::is_unsigned_v<value_type>,
451 size_t min_width = 0,
const char separator = 0,
const char padding =
'0') noexcept
455 case 16: shift = 4;
break;
456 case 10: shift = 0;
break;
457 case 8: shift = 3;
break;
458 case 2: shift = 1;
break;
461 const nsize_t mask = radix - 1;
464 const size_t separator_gap = 10 == radix ? 3 : 4;
465 size_t separator_count;
466 if ( separator &&
'0' == padding ) {
468 if ( min_width > prefix_len ) {
469 const size_t len0 = std::max<size_t>(min_width - prefix_len, val_digits);
470 separator_count = (len0 - 1) / separator_gap;
471 if ( val_digits + separator_count + prefix_len > min_width ) {
475 separator_count = (val_digits - 1) / separator_gap;
477 }
else if ( separator ) {
479 separator_count = (val_digits - 1) / separator_gap;
483 size_t len = std::max<size_t>(min_width, val_digits + separator_count + prefix_len);
485 std::string str(len,
' ');
486 size_t digit_idx = 0, separator_idx = 0;
487 while ( len > prefix_len ) {
488 if ( separator_idx < separator_count && 0 < digit_idx && 0 == digit_idx % separator_gap ) {
489 str[--len] = separator;
492 if ( len > prefix_len ) {
497 str[--len] = digit_idx < val_digits ?
'0' + (v % 10) : padding;
505 case 16: str[--len] =
'x';
break;
506 case 8: str[--len] =
'0';
break;
507 case 2: str[--len] =
'b';
break;
523 template<
typename... Args>
524 constexpr std::string
format_string_n(
const std::size_t maxStrLen,
const std::string_view &format,
const Args &...args) {
526 str.reserve(maxStrLen + 1);
527 str.resize(maxStrLen);
534 const size_t nchars = std::snprintf(&str[0], maxStrLen + 1, format.data(), args...);
536 if ( nchars < maxStrLen + 1 ) {
543 template <
typename... Args>
544 constexpr std::string
format_string_h(
const std::size_t strLenHint,
const std::string_view format,
const Args &...args) {
548 const size_t bsz = strLenHint + 1;
557 nchars = std::snprintf(&str[0], bsz, format.data(), args...);
559 if ( nchars < bsz ) {
566 const size_t bsz = std::min<size_t>(nchars + 1, str.max_size() + 1);
575 nchars = std::snprintf(&str[0], bsz, format.data(), args...);
598 template<
typename... Args>
599 constexpr std::string
format_string_n(
const std::size_t maxStrLen,
const std::string_view &format,
const Args &...args) {
621 template <StringLiteral format,
typename... Args>
640 template <
typename... Args>
641 constexpr std::string
format_string_h(
const std::size_t strLenHint,
const std::string_view format,
const Args &...args) {
661 template <
typename... Args>
662 constexpr std::string
format_string(
const std::string_view format,
const Args &...args) {
678 template <StringLiteral format,
typename... Args>
690 template<
class value_type,
691 std::enable_if_t<(std::is_integral_v<value_type> && !std::is_same_v<bool, value_type>) ||
692 std::is_floating_point_v<value_type>,
695 return std::to_string(ref);
698 template<
class value_type,
699 std::enable_if_t<std::is_same_v<bool, value_type>,
701 inline std::string
to_string(
const value_type &ref) {
702 return ref ?
"T" :
"F";
705 template<
class value_type,
706 std::enable_if_t<!std::is_integral_v<value_type> &&
707 !std::is_floating_point_v<value_type> &&
708 std::is_base_of_v<std::string, value_type>,
710 inline std::string
to_string(
const value_type &ref) {
714 template<
class value_type,
715 std::enable_if_t<!std::is_integral_v<value_type> &&
716 !std::is_floating_point_v<value_type> &&
717 !std::is_base_of_v<std::string, value_type> &&
718 std::is_base_of_v<std::string_view, value_type>,
720 inline std::string
to_string(
const value_type &ref) {
721 return std::string(ref);
724 template<
class value_type,
725 std::enable_if_t<!std::is_integral_v<value_type> &&
726 !std::is_floating_point_v<value_type> &&
727 !std::is_base_of_v<std::string, value_type> &&
728 !std::is_base_of_v<std::string_view, value_type> &&
729 std::is_pointer_v<value_type>,
731 inline std::string
to_string(
const value_type &ref) {
735 template<
class value_type,
736 std::enable_if_t<!std::is_integral_v<value_type> &&
737 !std::is_floating_point_v<value_type> &&
738 !std::is_base_of_v<std::string, value_type> &&
739 !std::is_base_of_v<std::string_view, value_type> &&
740 !std::is_pointer_v<value_type> &&
743 inline std::string
to_string(
const value_type &ref) {
744 return ref.toString();
747 template<
class value_type,
748 std::enable_if_t<!std::is_integral_v<value_type> &&
749 !std::is_floating_point_v<value_type> &&
750 !std::is_base_of_v<std::string, value_type> &&
751 !std::is_base_of_v<std::string_view, value_type> &&
752 !std::is_pointer_v<value_type> &&
756 inline std::string
to_string(
const value_type &ref) {
757 return ref.to_string();
760 template<
class value_type,
761 std::enable_if_t<!std::is_integral_v<value_type> &&
762 !std::is_floating_point_v<value_type> &&
763 !std::is_base_of_v<std::string, value_type> &&
764 !std::is_base_of_v<std::string_view, value_type> &&
765 !std::is_pointer_v<value_type> &&
770 inline std::string
to_string(
const value_type &ref) {
774 template<
class value_type,
775 std::enable_if_t<!std::is_integral_v<value_type> &&
776 !std::is_floating_point_v<value_type> &&
777 !std::is_base_of_v<std::string, value_type> &&
778 !std::is_base_of_v<std::string_view, value_type> &&
779 !std::is_pointer_v<value_type> &&
784 inline std::string
to_string(
const value_type &ref) {
790 std::string
to_string(std::vector<T>
const &list,
const std::string &delim) {
791 if ( list.empty() ) {
792 return std::string();
794 bool need_delim =
false;
796 for (
const T &e : list ) {
809 std::string
to_string(std::vector<T>
const &list,
const std::string &delim,
const nsize_t radix) {
810 if ( list.empty() ) {
811 return std::string();
813 bool need_delim =
false;
815 for (
const T &e : list ) {
834 Int64SizeBoolTuple
to_integer(
const char *str,
size_t str_len,
const nsize_t radix = 10,
const char limiter =
'\0',
const char *limiter_pos =
nullptr);
845 return to_integer(str.data(), str.length(), radix, limiter, limiter_pos);
856 return std::hash<std::string_view>{}(txt);
858 [[nodiscard]]
size_t operator()(std::string_view txt)
const {
859 return std::hash<std::string_view>{}(txt);
861 [[nodiscard]]
size_t operator()(
const std::string &txt)
const {
862 return std::hash<std::string>{}(txt);
867 using StringHashMap = std::unordered_map<std::string, T, string_hash, std::equal_to<>>;
869 using StringHashSet = std::unordered_set<std::string, string_hash, std::equal_to<>>;
875#define jau_format_string_static(...) \
876 jau::format_string(__VA_ARGS__); \
877 static_assert(0 <= jau::cfmt::checkR(__VA_ARGS__).argCount());
std::string toString() const noexcept
C++ Named Requirement Container (partial)
C++ Named Requirement ContiguousContainer (partial)
Concept of type-trait std::is_pointer.
Concept of type-trait std::is_standard_layout.
Concept of type-trait std::is_trivially_copyable.
constexpr bool is_little_endian() noexcept
Evaluates true if platform is running in little endian mode, i.e.
constexpr uint16_t bswap(uint16_t const source) noexcept
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
constexpr uint16_t cpu_to_le(uint16_t const h) noexcept
const uint8_t * cast_char_ptr_to_uint8(const char *s) noexcept
@ big
Identifier for big endian.
@ big
Identifier for big endian, equivalent to endian::big.
#define PRAGMA_DISABLE_WARNING_FORMAT_SECURITY
constexpr bool value(const Bool rhs) noexcept
constexpr bool has_toString_v
constexpr bool has_member_of_pointer_v
constexpr bool has_to_string_v
#define PRAGMA_DISABLE_WARNING_PUSH
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_pointer_v< Source > &&std::is_pointer_v< Dest >, Dest > pointer_cast(const Source &src) noexcept
A constexpr pointer cast implementation for C++17, inspired by C++20 bit_cast<>(arg).
const jau::type_info & static_ctti() noexcept
Returns a static global reference of make_ctti<T>(true) w/ identity instance.
#define consteval_cxx20
consteval qualifier replacement for C++20 consteval.
#define PRAGMA_DISABLE_WARNING_POP
#define PRAGMA_DISABLE_WARNING_FORMAT_NONLITERAL
Bool
Boolean type without implicit conversion, safe for function parameter.
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an arithmetic number w/ branching in O(1)
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
constexpr size_t digits(const T x, const nsize_t radix) noexcept
Returns the number of digits of the given unsigned integral value number and the given radix.
constexpr size_t digits10(const T x, const snsize_t x_sign, const bool sign_is_digit=true) noexcept
Returns the number of decimal digits of the given integral value number using std::log10<T>().
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
constexpr int sign(const T x) noexcept
Returns the value of the sign function (w/o branching ?) in O(1).
std::string & toLowerInPlace(std::string &s) noexcept
std::string trim(const std::string &s) noexcept
trim copy
void trimInPlace(std::string &s) noexcept
trim in place
std::string toBitString(const void *data, const nsize_t length, const bit_order_t bitOrder=bit_order_t::msb, const PrefixOpt prefix=PrefixOpt::prefix, size_t bit_len=0) noexcept
Produce a binary string representation of the given lsb-first byte values.
constexpr PResult checkR2(const std::string_view fmt) noexcept
Strict type validation of arguments against the format string.
constexpr std::string format_string_n(const std::size_t maxStrLen, const std::string_view &format, const Args &...args)
Safely returns a (potentially truncated) string according to snprintf() formatting rules and variable...
std::string get_string(const uint8_t *buffer, nsize_t const buffer_len, nsize_t const max_len) noexcept
Returns a C++ String taken from buffer with maximum length of min(max_len, max_len).
constexpr std::string format_string(const std::string_view format, const Args &...args)
Safely returns a (non-truncated) string according to snprintf() formatting rules and variable number ...
std::unordered_set< std::string, string_hash, std::equal_to<> > StringHashSet
Int64SizeBoolTuple to_integer(const char *str, size_t str_len, const nsize_t radix=10, const char limiter='\0', const char *limiter_pos=nullptr)
Returns tuple [int64_t result, size_t consumed_chars, bool complete] of string to integer conversion ...
SizeBoolPair fromBitString(std::vector< uint8_t > &out, const uint8_t bitstr[], const size_t bitstr_len, const bit_order_t bitOrder=bit_order_t::msb, const Bool checkPrefix=Bool::True) noexcept
Converts a given binary string representation into a byte vector, lsb-first.
std::unordered_map< std::string, T, string_hash, std::equal_to<> > StringHashMap
std::vector< std::string > split_string(const std::string &str, const std::string &separator) noexcept
Split given string str at separator into the resulting std::vector excluding the separator sequence .
constexpr const char * HexadecimalArray
constexpr std::string format_string_h(const std::size_t strLenHint, const std::string_view format, const Args &...args)
Safely returns a (non-truncated) string according to snprintf() formatting rules and variable number ...
std::string & appendToHexString(std::string &dest, const uint8_t value, const LoUpCase capitalization=LoUpCase::lower) noexcept
Produce a hexadecimal string representation of the given byte value and appends it to the given strin...
bool is_ascii_code(int c) noexcept
std::string toLower(const std::string &s) noexcept
SizeBoolPair fromHexString(std::vector< uint8_t > &out, const uint8_t hexstr[], const size_t hexstr_len, const lb_endian_t byteOrder=lb_endian_t::big, const Bool checkPrefix=Bool::True) noexcept
Converts a given hexadecimal string representation into a byte vector, lsb-first.
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
std::string to_decstring(const value_type &v, const char separator=',', const nsize_t width=0) noexcept
Produce a decimal string representation of an integral integer value.
constexpr std::string format_string_n(const std::size_t maxStrLen, const std::string_view &format, const Args &...args)
constexpr std::string format_string_h(const std::size_t strLenHint, const std::string_view format, const Args &...args)
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
bit_order_t
Bit order type, i.e.
@ msb
Identifier for most-significant-bit (msb) first.
std::string to_string(const bit_order_t v) noexcept
Return std::string representation of the given bit_order_t.
Simple pre-defined value tuple [int64_t, size_t, bool] for structured bindings to multi-values.
Simple pre-defined value pair [size_t, bool] for structured bindings to multi-values.
constexpr ssize_t argCount() const noexcept
std::string toString() const
C++20: Heterogeneous Lookup in (Un)ordered Containers.
size_t operator()(const std::string &txt) const
size_t operator()(const char *txt) const
size_t operator()(std::string_view txt) const
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.