Skip to content

Commit

Permalink
[FOLD] Basic C++20 support
Browse files Browse the repository at this point in the history
fix #21
  • Loading branch information
alandefreitas committed May 19, 2022
1 parent 9386cea commit d6340c6
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 25 deletions.
24 changes: 20 additions & 4 deletions include/small/detail/algorithm/utf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ namespace small {
/// Set the types for UTF in C++
#ifdef cpp_char8_t
// there's no operator<<(stream, char8_t) in C++20
// using utf8_char_type = char8_t;
using utf8_char_type = char;
using utf8_char_type = char8_t;
#else
using utf8_char_type = char;
#endif
Expand Down Expand Up @@ -262,7 +261,8 @@ namespace small {
template <class Char32, class Size = size_t, class Result = uint8_t>
constexpr Result
utf32_size(Char32, Size available_code_units = 1) noexcept {
return static_cast<Result>((std::min)(Size(1), available_code_units));
return static_cast<Result>(
(std::min)(Size(1), available_code_units));
}

/// \brief Get size a utf32 char would have when/if converted to utf8
Expand Down Expand Up @@ -740,7 +740,8 @@ namespace small {
source + (std::min)(source_count, dest_count),
dest,
[](auto in) { return static_cast<output_value_type>(in); });
return static_cast<uint8_t>((std::min)(source_count, dest_count));
return static_cast<uint8_t>(
(std::min)(source_count, dest_count));
} else {
return static_cast<uint8_t>(
from_utf8_to_utf16(source, source_count, dest, dest_count));
Expand Down Expand Up @@ -805,7 +806,22 @@ namespace small {
return to_utf8(source, source_count, dest, dest_count);
}
}

} // namespace detail
} // namespace small

#ifdef cpp_char8_t
inline
std::ostream&
operator<<(std::ostream& os, char8_t c) {
return os << static_cast<char>(c);
}

inline
std::ostream&
operator<<(std::ostream& os, const char8_t* c) {
return os << reinterpret_cast<const char*>(c);
}
#endif

#endif // SMALL_DETAIL_ALGORITHM_UTF_HPP
12 changes: 9 additions & 3 deletions include/small/detail/iterator/codepoint_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,14 @@ namespace small {
const codepoint_reference_impl &impl) {
if constexpr (not is_utf32_v<value_type>) {
if (impl.size() == 1) {
os << static_cast<char>(impl.container_->operator[](impl.byte_index_));
os << static_cast<char>(
impl.container_->operator[](impl.byte_index_));
} else {
console_unicode_guard g(os, impl.size(), 1);
os << std::string_view(
reinterpret_cast<const char*>(impl.container_->data()) + impl.byte_index_,
reinterpret_cast<const char *>(
impl.container_->data())
+ impl.byte_index_,
impl.size());
}
} else {
Expand Down Expand Up @@ -234,7 +237,10 @@ namespace small {
// Compare codepoints now
for (size_type i = 0; i < rhs_utf8_size; ++i) {
if (lhs.container_->operator[](lhs.byte_index_ + i)
!= rhs[i]) {
!= static_cast<
typename codepoint_reference_impl::
string_type::value_type>(rhs[i]))
{
return false;
}
}
Expand Down
54 changes: 41 additions & 13 deletions include/small/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4061,7 +4061,16 @@ namespace small {
// on is, which may throw std::ios_base::failure 3) Finally, calls
// is.width(0) to cancel the effects of std::setw, if any
std::ios_base::iostate state = std::ios_base::goodbit;
typename std::basic_istream<CharT, Traits>::sentry sen(is);
using sentry_char_type = std::conditional_t<
std::is_same_v<detail::utf8_char_type, CharT>,
char,
CharT>;
using sentry_traits_type = std::conditional_t<
std::is_same_v<detail::utf8_char_type, CharT>,
std::char_traits<char>,
Traits>;
typename std::basic_istream<sentry_char_type, sentry_traits_type>::
sentry sen(is);
if (sen) {
#ifndef SMALL_DISABLE_EXCEPTIONS
try {
Expand All @@ -4073,15 +4082,15 @@ namespace small {
if (n <= 0)
n = std::numeric_limits<std::streamsize>::max();
std::streamsize c = 0;
const std::ctype<CharT>
&ct = std::use_facet<std::ctype<CharT>>(is.getloc());
const std::ctype<sentry_char_type>
&ct = std::use_facet<std::ctype<sentry_char_type>>(is.getloc());
while (c < n) {
typename Traits::int_type i = is.rdbuf()->sgetc();
if (Traits::eq_int_type(i, Traits::eof())) {
state |= std::ios_base::eofbit;
break;
}
CharT ch = Traits::to_char_type(i);
sentry_char_type ch = Traits::to_char_type(i);
if (ct.is(ct.space, ch))
break;
str.push_back(ch);
Expand Down Expand Up @@ -4135,7 +4144,16 @@ namespace small {
// 3) If no characters were extracted for whatever reason (not even
// the discarded delimiter), getline sets failbit and returns
std::ios_base::iostate state = std::ios_base::goodbit;
typename std::basic_istream<CharT, Traits>::sentry sen(is, true);
using sentry_char_type = std::conditional_t<
std::is_same_v<detail::utf8_char_type, CharT>,
char,
CharT>;
using sentry_traits_type = std::conditional_t<
std::is_same_v<detail::utf8_char_type, CharT>,
std::char_traits<char>,
Traits>;
typename std::basic_istream<sentry_char_type, sentry_traits_type>::
sentry sen(is, true);
if (sen) {
#ifndef SMALL_DISABLE_EXCEPTIONS
try {
Expand Down Expand Up @@ -4768,6 +4786,16 @@ namespace small {
/// \brief Typedef of u8string (data type char8_t)
using u8string = basic_string<detail::utf8_char_type>;

/// \brief Typedef of string (data type: char)
using string_view = std::basic_string_view<
detail::utf8_char_type,
std::char_traits<detail::utf8_char_type>>;

/// \brief Typedef of string (data type: char8_t)
using u8_string_view = std::basic_string_view<
detail::utf8_char_type,
std::char_traits<detail::utf8_char_type>>;

/// \brief Forms a string literal of the desired type
/// returns std::string{str, len}
inline small::string operator""_ss(const char *str, std::size_t len) {
Expand All @@ -4785,7 +4813,7 @@ namespace small {
errno = 0;
char *p_end;
// this is OK because numbers are in the same value range
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const long i = std::strtol(s_begin, &p_end, base);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand Down Expand Up @@ -4815,7 +4843,7 @@ namespace small {
stol(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const long i = std::strtol(s_begin, &p_end, base);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand All @@ -4842,7 +4870,7 @@ namespace small {
stoll(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const long long i = std::strtoll(s_begin, &p_end, base);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand All @@ -4869,7 +4897,7 @@ namespace small {
stoul(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const unsigned long i = std::strtoul(s_begin, &p_end, base);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand All @@ -4896,7 +4924,7 @@ namespace small {
stoull(const small::string &str, std::size_t *pos = nullptr, int base = 10) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const unsigned long long i = std::strtoull(s_begin, &p_end, base);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand All @@ -4923,7 +4951,7 @@ namespace small {
stof(const small::string &str, std::size_t *pos = nullptr) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const float i = std::strtof(s_begin, &p_end);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand All @@ -4950,7 +4978,7 @@ namespace small {
stod(const small::string &str, std::size_t *pos = nullptr) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const double i = std::strtod(s_begin, &p_end);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand All @@ -4977,7 +5005,7 @@ namespace small {
stold(const small::string &str, std::size_t *pos = nullptr) {
errno = 0;
char *p_end;
auto s_begin = reinterpret_cast<const char*>(str.c_str());
auto s_begin = reinterpret_cast<const char *>(str.c_str());
const long double i = std::strtold(s_begin, &p_end);
if (s_begin == p_end) {
detail::throw_exception<std::invalid_argument>(
Expand Down
4 changes: 2 additions & 2 deletions test/unit/small_string_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ TEST_CASE("String") {

SECTION("Data") {
string s = "1😀2😀3😀5";
std::string_view sv(s.data(), s.size());
string_view sv(s.data(), s.size());
REQUIRE(s == sv);
REQUIRE(s.data() == s.c_str());
REQUIRE(s.operator std::string_view() == sv);
REQUIRE(s.operator string_view() == sv);
}
}

Expand Down
1 change: 1 addition & 0 deletions test/unit/small_string_non_member.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ TEST_CASE("String Non-Member") {
SECTION("Input") {
std::stringstream ss;
ss << "123";
REQUIRE(ss.str() == "123");
ss >> a;
REQUIRE(a == "123");
}
Expand Down
6 changes: 3 additions & 3 deletions test/unit/unicode_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ TEST_CASE("Unicode") {
utf8_char_type a = 'g';
// utf8_char_type b = 'á'; // <- can't fit in 8 bits
// utf8_char_type c = '😀';
std::basic_string<utf8_char_type> d = "g";
std::basic_string<utf8_char_type> e = "á";
std::basic_string<utf8_char_type> f = "😀";
std::basic_string<utf8_char_type> d = u8"g";
std::basic_string<utf8_char_type> e = u8"á";
std::basic_string<utf8_char_type> f = u8"😀";
SECTION("Check") {
// Check container sizes
REQUIRE(d.size() == 1);
Expand Down

0 comments on commit d6340c6

Please sign in to comment.