1#ifndef SOURCEMETA_CORE_TEXT_H_
2#define SOURCEMETA_CORE_TEXT_H_
4#ifndef SOURCEMETA_CORE_TEXT_EXPORT
5#include <sourcemeta/core/text_export.h>
34namespace sourcemeta::core {
49SOURCEMETA_CORE_TEXT_EXPORT
65template <
typename Character>
66 requires std::same_as<Character, char> ||
67 std::same_as<Character, signed char> ||
68 std::same_as<Character, unsigned char> ||
69 std::same_as<Character, wchar_t>
70constexpr auto to_lowercase(
const Character character)
noexcept -> Character {
71 return (character >=
'A' && character <=
'Z')
72 ?
static_cast<Character
>(character + (
'a' -
'A'))
89template <
typename Character,
typename Traits,
typename Allocator>
90 requires requires(Character character) {
93inline auto to_lowercase(std::basic_string<Character, Traits, Allocator> &value)
95 for (
auto &character : value) {
113SOURCEMETA_CORE_TEXT_EXPORT
128template <
typename Character>
129 requires std::same_as<Character, char> ||
130 std::same_as<Character, signed char> ||
131 std::same_as<Character, unsigned char> ||
132 std::same_as<Character, wchar_t>
133constexpr auto is_lowercase(
const Character character)
noexcept ->
bool {
134 return character <
'A' || character >
'Z';
150template <
typename String>
151 requires requires(
const String &value) {
155 for (
const auto character : value) {
176SOURCEMETA_CORE_TEXT_EXPORT
191template <
typename Character>
192 requires std::same_as<Character, char> ||
193 std::same_as<Character, signed char> ||
194 std::same_as<Character, unsigned char> ||
195 std::same_as<Character, wchar_t>
196constexpr auto is_alpha(
const Character character)
noexcept ->
bool {
197 return (character >=
'a' && character <=
'z') ||
198 (character >=
'A' && character <=
'Z');
214constexpr auto is_alpha(
const std::string_view value)
noexcept ->
bool {
218 for (
const auto character : value) {
237template <
typename Character>
238 requires std::same_as<Character, char> ||
239 std::same_as<Character, signed char> ||
240 std::same_as<Character, unsigned char> ||
241 std::same_as<Character, wchar_t>
242constexpr auto is_digit(
const Character character)
noexcept ->
bool {
243 return character >=
'0' && character <=
'9';
259constexpr auto is_digit(
const std::string_view value)
noexcept ->
bool {
263 for (
const auto character : value) {
283template <
typename Character>
284 requires std::same_as<Character, char> ||
285 std::same_as<Character, signed char> ||
286 std::same_as<Character, unsigned char> ||
287 std::same_as<Character, wchar_t>
288constexpr auto is_alphanum(
const Character character)
noexcept ->
bool {
305constexpr auto is_alphanum(
const std::string_view value)
noexcept ->
bool {
309 for (
const auto character : value) {
332template <
typename Character>
333 requires std::same_as<Character, char> ||
334 std::same_as<Character, signed char> ||
335 std::same_as<Character, unsigned char> ||
336 std::same_as<Character, wchar_t>
338 return (character >=
'!' && character <=
'/') ||
339 (character >=
':' && character <=
'@') ||
340 (character >=
'[' && character <=
'`') ||
341 (character >=
'{' && character <=
'~');
359SOURCEMETA_CORE_TEXT_EXPORT
360auto truncate(std::string &input,
const std::size_t maximum_length,
361 const std::string_view marker) -> void;
374SOURCEMETA_CORE_TEXT_EXPORT
375auto replace(
const std::string_view input,
const std::string_view target,
376 const std::string_view replacement) -> std::string;
391SOURCEMETA_CORE_TEXT_EXPORT
392auto trim(
const std::string_view input)
noexcept -> std::string_view;
406SOURCEMETA_CORE_TEXT_EXPORT
407auto strip_left(
const std::string_view input,
const char character)
noexcept
422SOURCEMETA_CORE_TEXT_EXPORT
423auto strip_right(
const std::string_view input,
const char character)
noexcept
438template <
typename Predicate>
439 requires std::predicate<Predicate &, char>
441strip_left(
const std::string_view input, Predicate predicate)
noexcept(
442 std::is_nothrow_invocable_r_v<bool, Predicate &, char> &&
443 std::is_nothrow_copy_constructible_v<Predicate>) -> std::string_view {
444 std::string_view result{input};
445 while (!result.empty() && predicate(result.front())) {
446 result.remove_prefix(1);
464template <
typename Predicate>
465 requires std::predicate<Predicate &, char>
467strip_right(
const std::string_view input, Predicate predicate)
noexcept(
468 std::is_nothrow_invocable_r_v<bool, Predicate &, char> &&
469 std::is_nothrow_copy_constructible_v<Predicate>) -> std::string_view {
470 std::string_view result{input};
471 while (!result.empty() && predicate(result.back())) {
472 result.remove_suffix(1);
491template <
typename Predicate>
492 requires std::predicate<Predicate &, char>
493constexpr auto trim(
const std::string_view input, Predicate predicate)
noexcept(
494 std::is_nothrow_invocable_r_v<bool, Predicate &, char> &&
495 std::is_nothrow_copy_constructible_v<Predicate>) -> std::string_view {
513constexpr auto unquote(
const std::string_view input,
const char quote)
noexcept
514 -> std::string_view {
515 if (input.size() < 2 || input.front() != quote || input.back() != quote) {
520 inner.remove_prefix(1);
521 inner.remove_suffix(1);
537SOURCEMETA_CORE_TEXT_EXPORT
538auto pad_left(
const std::string_view input,
const std::size_t width,
539 const char character) -> std::string;
554SOURCEMETA_CORE_TEXT_EXPORT
555auto take_until(
const std::string_view input,
const char marker)
noexcept
574SOURCEMETA_CORE_TEXT_EXPORT
575auto split_once(
const std::string_view input,
const char delimiter)
noexcept
576 -> std::optional<std::pair<std::string_view, std::string_view>>;
593SOURCEMETA_CORE_TEXT_EXPORT
595 const std::string_view delimiter)
noexcept
596 -> std::optional<std::pair<std::string_view, std::string_view>>;
614SOURCEMETA_CORE_TEXT_EXPORT
615auto rsplit_once(
const std::string_view input,
const char delimiter)
noexcept
616 -> std::optional<std::pair<std::string_view, std::string_view>>;
632template <
typename Callback>
633auto split(
const std::string_view input,
const char delimiter,
634 Callback callback) ->
void {
635 std::string_view rest{input};
638 if (!next.has_value()) {
642 callback(next->first);
662inline auto split(
const std::string_view input,
const char delimiter)
663 -> std::vector<std::string_view> {
664 std::vector<std::string_view> parts;
667 [&parts](
const std::string_view part) ->
void { parts.push_back(part); });
685template <
typename Range>
686auto join(
const Range &items,
const std::string_view separator) -> std::string {
689 for (
const auto &item : items) {
691 result.append(separator);
715template <
typename Range>
716auto join_to(std::ostream &stream,
const Range &items,
717 const std::string_view separator) ->
void {
719 for (
const auto &item : items) {
733template <
typename Type>
735 std::integral<Type> && !std::same_as<std::remove_cv_t<Type>,
bool> &&
736 sizeof(
Type) <=
sizeof(std::uint64_t);
743template <
typename Integer>
746 static_cast<std::size_t
>(std::numeric_limits<Integer>::digits10) + 1 +
747 (std::numeric_limits<Integer>::is_signed ? 1U : 0U)};
779template <
typename Integer, std::
size_t Capacity>
783 std::array<char, Capacity> &buffer)
noexcept
784 -> std::string_view {
786 std::to_chars(buffer.data(), buffer.data() + buffer.size(), value)};
787 return {buffer.data(),
static_cast<std::size_t
>(result.ptr - buffer.data())};
804template <
typename Output,
typename Integer>
805 requires text_spellable_integer<Integer>
807 std::array<char, DIGITS_CAPACITY<Integer>> buffer;
809 output.append(digits.data(), digits.size());
828template <
typename CharT,
typename Traits,
typename Integer>
829 requires text_spellable_integer<Integer>
831 const Integer value) ->
void {
832 std::array<char, DIGITS_CAPACITY<Integer>> buffer;
834 stream.write(digits.data(),
static_cast<std::streamsize
>(digits.size()));
853 static constexpr std::array<std::int8_t, 256> TABLE{
854 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
855 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
856 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5,
857 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1,
858 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
859 -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,
860 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
861 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
862 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
863 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
864 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
865 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
866 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
867 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
869 return TABLE[
static_cast<unsigned char>(character)];
902 const std::size_t position)
noexcept ->
bool {
903 return input.size() >= 3 && position < input.size() - 2 &&
904 input[position] ==
'%' &&
is_hex_digit(input[position + 1]) &&
923SOURCEMETA_CORE_TEXT_EXPORT
925 const bool allow_odd_length =
false)
926 -> std::optional<std::string>;
938SOURCEMETA_CORE_TEXT_EXPORT
957 const std::string_view right)
noexcept ->
bool {
958 if (left.size() != right.size()) {
962 for (std::size_t index{0}; index < left.size(); ++index) {
986 const std::string_view prefix)
noexcept
988 if (value.size() < prefix.size()) {
992 for (std::size_t index{0}; index < prefix.size(); ++index) {
1016 const std::string_view right)
noexcept ->
bool {
1017 const auto length{left.size() < right.size() ? left.size() : right.size()};
1018 for (std::size_t index{0}; index < length; ++index) {
1021 if (left_lower != right_lower) {
1022 return left_lower < right_lower;
1026 return left.size() < right.size();
1040SOURCEMETA_CORE_TEXT_EXPORT
1041auto squeeze(
const std::string_view input,
const char character) -> std::string;
1058template <
typename Output>
1059auto squeeze(
const std::string_view input,
const char character, Output &output)
1062 for (
const auto value : input) {
1063 if (value == character) {
1065 output.push_back(value);
1070 output.push_back(value);
1091SOURCEMETA_CORE_TEXT_EXPORT
1093 const std::string_view suffix)
noexcept
1094 -> std::string_view;
@ Type
The token type does not match the expected media type.
Definition jose_verify.h:216
constexpr auto is_digit(const char character) -> bool
Definition numeric_util.h:51
SOURCEMETA_CORE_TEXT_EXPORT auto truncate(std::string &input, const std::size_t maximum_length, const std::string_view marker) -> void
SOURCEMETA_CORE_TEXT_EXPORT auto to_title_case(std::string &value) -> void
auto join_to(std::ostream &stream, const Range &items, const std::string_view separator) -> void
Definition text.h:716
SOURCEMETA_CORE_TEXT_EXPORT auto bytes_to_hex(const std::string_view input) -> std::string
constexpr auto is_alphanum(const Character character) noexcept -> bool
Definition text.h:288
auto less_ignore_case(const std::string_view left, const std::string_view right) noexcept -> bool
Definition text.h:1015
constexpr auto is_alpha(const Character character) noexcept -> bool
Definition text.h:196
constexpr auto is_lowercase(const Character character) noexcept -> bool
Definition text.h:133
auto is_hex_digit(const char character) noexcept -> bool
Definition text.h:884
std::array< char, std::max(DIGITS_CAPACITY< std::uint64_t >, DIGITS_CAPACITY< std::int64_t >)> DigitsBuffer
Definition text.h:754
auto digits_view(const Integer value, std::array< char, Capacity > &buffer) noexcept -> std::string_view
Definition text.h:782
auto split(const std::string_view input, const char delimiter, Callback callback) -> void
Definition text.h:633
SOURCEMETA_CORE_TEXT_EXPORT auto hex_to_bytes(const std::string_view input, const bool allow_odd_length=false) -> std::optional< std::string >
auto equals_ignore_case(const std::string_view left, const std::string_view right) noexcept -> bool
Definition text.h:956
SOURCEMETA_CORE_TEXT_EXPORT auto strip_left(const std::string_view input, const char character) noexcept -> std::string_view
constexpr auto unquote(const std::string_view input, const char quote) noexcept -> std::string_view
Definition text.h:513
SOURCEMETA_CORE_TEXT_EXPORT auto replace(const std::string_view input, const std::string_view target, const std::string_view replacement) -> std::string
auto hex_digit_value(const char character) noexcept -> std::int8_t
Definition text.h:850
SOURCEMETA_CORE_TEXT_EXPORT auto remove_suffix_ignore_case(const std::string_view input, const std::string_view suffix) noexcept -> std::string_view
auto digits_write(std::basic_ostream< CharT, Traits > &stream, const Integer value) -> void
Definition text.h:830
auto join(const Range &items, const std::string_view separator) -> std::string
Definition text.h:686
SOURCEMETA_CORE_TEXT_EXPORT auto strip_right(const std::string_view input, const char character) noexcept -> std::string_view
constexpr auto is_punctuation(const Character character) noexcept -> bool
Definition text.h:337
SOURCEMETA_CORE_TEXT_EXPORT auto trim(const std::string_view input) noexcept -> std::string_view
SOURCEMETA_CORE_TEXT_EXPORT auto squeeze(const std::string_view input, const char character) -> std::string
SOURCEMETA_CORE_TEXT_EXPORT auto take_until(const std::string_view input, const char marker) noexcept -> std::string_view
constexpr auto to_lowercase(const Character character) noexcept -> Character
Definition text.h:70
SOURCEMETA_CORE_TEXT_EXPORT auto rsplit_once(const std::string_view input, const char delimiter) noexcept -> std::optional< std::pair< std::string_view, std::string_view > >
SOURCEMETA_CORE_TEXT_EXPORT auto pad_left(const std::string_view input, const std::size_t width, const char character) -> std::string
auto is_percent_triplet(const std::string_view input, const std::size_t position) noexcept -> bool
Definition text.h:901
SOURCEMETA_CORE_TEXT_EXPORT auto split_once(const std::string_view input, const char delimiter) noexcept -> std::optional< std::pair< std::string_view, std::string_view > >
constexpr std::size_t DIGITS_CAPACITY
Definition text.h:745
auto digits_append(Output &output, const Integer value) -> void
Definition text.h:806
auto starts_with_ignore_case(const std::string_view value, const std::string_view prefix) noexcept -> bool
Definition text.h:985