Browse Source

std::basic_string<CharT> has a FAT interface... I'll forward most of it to the embedded string.

master
roker 4 years ago
parent
commit
f71397426b
  1. 19
      src/nfc.cc
  2. 82
      src/nfc.hh

19
src/nfc.cc

@ -554,6 +554,25 @@ std::u32string createNFC(std::u32string nfd)
} }
template<>
IsNFC UTF<char>::isNFC(char c)
{
if( c & 0x80 )
throw illegal_utf("Single octet >0x80 is invalid UTF-8");
return IsNFC::Yes; // all ASCII characters are valid NFC.
}
template<>
IsNFC UTF<char16_t>::isNFC(char16_t c)
{
if(NFC_No.count(c)) return IsNFC::No;
if(NFC_Maybe.count(c)) return IsNFC::Maybe;
return IsNFC::Yes;
}
template<class CharT> template<class CharT>
IsNFC UTF<CharT>::isNFC_quick_check(std::basic_string_view<CharT> s) IsNFC UTF<CharT>::isNFC_quick_check(std::basic_string_view<CharT> s)
{ {

82
src/nfc.hh

@ -27,7 +27,6 @@ class illegal_utf : public std::runtime_error
public: public:
illegal_utf( std::string_view, unsigned position, const std::string& reason); illegal_utf( std::string_view, unsigned position, const std::string& reason);
illegal_utf(std::u16string_view, unsigned position, const std::string& reason); illegal_utf(std::u16string_view, unsigned position, const std::string& reason);
protected:
explicit illegal_utf(const std::string& message); explicit illegal_utf(const std::string& message);
}; };
@ -48,7 +47,11 @@ public:
void generate(const char32_t c, OutIter& out); void generate(const char32_t c, OutIter& out);
/// return No or Maybe, if at least one character with NFC_Quickcheck class is "No" or "Maybe" /// returns the NFC class of a single character
static
IsNFC isNFC(CharT c);
/// returns No or Maybe, if at least one character with NFC_Quickcheck class is "No" or "Maybe"
/// might throw illegal_utf exception /// might throw illegal_utf exception
static static
IsNFC isNFC_quick_check(std::basic_string_view<CharT> s); IsNFC isNFC_quick_check(std::basic_string_view<CharT> s);
@ -92,6 +95,8 @@ public:
/// only forward iterator. Does a backward_iterator make sense in UTF-encoded strings? /// only forward iterator. Does a backward_iterator make sense in UTF-encoded strings?
typedef typename String::const_iterator const_iterator; typedef typename String::const_iterator const_iterator;
static const size_t npos = String::npos;
explicit nfc_string(StringView src); explicit nfc_string(StringView src);
explicit nfc_string(String && src); explicit nfc_string(String && src);
@ -126,13 +131,86 @@ public:
std::size_t size() const noexcept { return s.size(); } std::size_t size() const noexcept { return s.size(); }
bool empty() const noexcept { return s.empty(); } bool empty() const noexcept { return s.empty(); }
std::size_t capacity() const noexcept { return s.capacity(); }
void reserve(std::size_t new_capacity) { s.reserve(new_capacity); }
void shrink_to_fit() { s.shrink_to_fit(); }
const_reference operator[](std::size_t ofs) const noexcept { return s[ofs]; }
const_reference at(std::size_t ofs) const { return s.at(ofs); }
const_reference front() const noexcept { return s.front(); }
const_reference back() const noexcept { return s.back(); }
operator StringView() const noexcept { return StringView{s}; }
const_iterator begin() const noexcept { return s.cbegin(); } const_iterator begin() const noexcept { return s.cbegin(); }
const_iterator cbegin() const noexcept { return s.cbegin(); } /// r/o access only const_iterator cbegin() const noexcept { return s.cbegin(); } /// r/o access only
const_iterator end() const noexcept { return s.cend(); } const_iterator end() const noexcept { return s.cend(); }
const_iterator cend() const noexcept { return s.cend(); } /// r/o access only const_iterator cend() const noexcept { return s.cend(); } /// r/o access only
void clear() { s.clear(); }
/// I am lazy and delegate all the 10 different insert() overloads directly to s.
template<typename... Args>
nfc_string& insert(Args&& ...args)
{
s.insert( std::forward<Args>(args)... );
normalize();
return *this;
}
/// delegates all erase() overloads to s.
template<typename... Args>
nfc_string& erase(Args&& ...args)
{
s.erase( std::forward<Args>(args)... );
normalize();
return *this;
}
nfc_string& push_back(CharT c);
/// delegates all 9 append() overloads to s.
template<typename... Args>
nfc_string& append(Args&& ...args)
{
s.append( std::forward<Args>(args)... );
normalize();
return *this;
}
nfc_string& operator+=(const StringView& s);
/// optimization possible to avoid re-normalization in most cases.
nfc_string& operator+=(const nfc_string& s);
/// optimization possible to avoid re-normalization in most cases.
nfc_string& operator+=(CharT c);
/// delegates all 9 compare() overloads to s
template<typename... Args>
int compare(Args&& ...args) const
{
return s.compare( std::forward<Args>(args)... );
}
/// stolen from C++20
bool starts_with(StringView s) const;
/// stolen from C++20
bool ends_with(StringView s) const;
/// delegates all 5 find() overloads to s
template<typename... Args>
std::size_t find(Args&& ...args) const
{
return s.find( std::forward<Args>(args)... );
}
private: private:
std::basic_string<CharT> s; std::basic_string<CharT> s;
/// (re-)normalize the content string s.
void normalize();
}; };
}; };

Loading…
Cancel
Save