/*********************************************************************** * fstring.h - Unicode string class with UTF-8 support * * * * This file is part of the FINAL CUT widget toolkit * * * * Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * FINAL CUT is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this program. If not, see * * . * ***********************************************************************/ /* Standalone class * ════════════════ * * ▕▔▔▔▔▔▔▔▔▔▏ * ▕ FString ▏ * ▕▁▁▁▁▁▁▁▁▁▏ */ #ifndef FSTRING_H #define FSTRING_H #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT) #error "Only can be included directly." #endif #include #include #include #include // for read errno #include #include #include #include // need for va_list, va_start and va_end #include // need for vsprintf #include #include #include #include #include #include #include #include #include #include #include #include #include "final/fc.h" #include "final/ftypes.h" namespace finalcut { // class forward declaration class FString; // Global using-declaration using FStringList = std::vector; //---------------------------------------------------------------------- // class FString //---------------------------------------------------------------------- class FString { public: // Using-declarations using iterator = std::wstring::iterator; using const_iterator = std::wstring::const_iterator; using reference = std::wstring::reference; using const_reference = std::wstring::const_reference; using difference_type = std::wstring::difference_type; // Constructors FString () = default; explicit FString (int); explicit FString (std::size_t); FString (std::size_t, wchar_t); FString (std::size_t, const UniChar&); FString (const FString&); // copy constructor FString (FString&&) noexcept; // move constructor FString (const std::wstring&); // implicit conversion constructor FString (const wchar_t[]); // implicit conversion constructor FString (const std::string&); // implicit conversion constructor FString (const char[]); // implicit conversion constructor FString (const UniChar&); // implicit conversion constructor FString (const wchar_t); // implicit conversion constructor FString (const char); // implicit conversion constructor // Destructor virtual ~FString (); // Overloaded operators FString& operator = (const FString&); FString& operator = (FString&&) noexcept; const FString& operator += (const FString&); FString& operator << (const FString&); FString& operator << (const UniChar&); FString& operator << (const wchar_t); FString& operator << (const char); template ::value && ! std::is_same::value && ! std::is_pointer::value ) || ( std::is_floating_point::value && ! std::is_pointer::value ) , int>::type = 0 > FString& operator << (const NumT); const FString& operator >> (FString&) const; const FString& operator >> (std::wstring&) const; const FString& operator >> (std::string&) const; const FString& operator >> (wchar_t&) const; const FString& operator >> (char&) const; const FString& operator >> (sInt16&) const; const FString& operator >> (uInt16&) const; const FString& operator >> (sInt32&) const; const FString& operator >> (uInt32&) const; const FString& operator >> (sInt64&) const; const FString& operator >> (uInt64&) const; const FString& operator >> (double&) const; const FString& operator >> (float&) const; template reference operator [] (const IndexT); template const_reference operator [] (const IndexT) const; explicit operator bool () const; const FString& operator () () const; bool operator < (const FString&) const; template bool operator < (const CharT&) const; bool operator <= (const FString&) const; template bool operator <= (const CharT&) const; bool operator == (const FString&) const; template bool operator == (const CharT&) const; bool operator != (const FString&) const; template bool operator != (const CharT&) const; bool operator >= (const FString&) const; template bool operator >= (const CharT&) const; bool operator > (const FString&) const; template bool operator > (const CharT&) const; // Accessor virtual FString getClassName() const; // inquiries bool isNull() const noexcept; // deprecated bool isEmpty() const noexcept; // Methods std::size_t getLength() const noexcept; std::size_t capacity() const noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; reference front(); reference back(); const_reference front() const; const_reference back() const; template FString& sprintf (const FString&, Args&&...); FString clear(); const wchar_t* wc_str() const; wchar_t* wc_str(); const char* c_str() const; char* c_str(); std::string toString() const; FString toLower() const; FString toUpper() const; sInt16 toShort() const; uInt16 toUShort() const; int toInt() const; uInt toUInt() const; long toLong() const; uLong toULong() const; float toFloat() const; double toDouble() const; FString ltrim() const; FString rtrim() const; FString trim() const; FString left (std::size_t) const; FString right (std::size_t) const; FString mid (std::size_t, std::size_t) const; FStringList split (const FString&) const; FString& setString (const FString&); template FString& setNumber (NumT, int = getPrecision()); FString& setNumber (sInt64); FString& setNumber (uInt64); FString& setNumber (lDouble, int = getPrecision()); template FString& setFormatedNumber (NumT, char = nl_langinfo(THOUSEP)[0]); FString& setFormatedNumber (sInt64, char = nl_langinfo(THOUSEP)[0]); FString& setFormatedNumber (uInt64, char = nl_langinfo(THOUSEP)[0]); const FString& insert (const FString&, int); const FString& insert (const FString&, std::size_t); FString replace (const FString&, const FString&) const; FString replaceControlCodes() const; FString expandTabs (int = 8) const; FString removeDel() const; FString removeBackspaces() const; const FString& overwrite (const FString&, int); const FString& overwrite (const FString&, std::size_t = 0); const FString& remove (std::size_t, std::size_t); bool includes (const FString&) const; private: // Constants static constexpr uInt INPBUFFER = 200; // Methods void _assign (std::wstring&); std::string _toCharString (const std::wstring&) const; std::wstring _toWideString (const std::string&) const; // Data members std::wstring string{}; mutable std::string char_string{}; static wchar_t null_char; static const wchar_t const_null_char; // Friend Non-member operator functions friend FString operator + (const FString&, const FString&); friend std::ostream& operator << (std::ostream&, const FString&); friend std::istream& operator >> (std::istream&, FString& s); friend std::wostream& operator << (std::wostream&, const FString&); friend std::wistream& operator >> (std::wistream&, FString&); }; // FString inline functions //---------------------------------------------------------------------- template ::value && ! std::is_same::value && ! std::is_pointer::value ) || ( std::is_floating_point::value && ! std::is_pointer::value ) , int>::type > inline FString& FString::operator << (const NumT val) { const FString numstr(FString().setNumber(val)); string.append(numstr.string); return *this; } //---------------------------------------------------------------------- template inline FString::reference FString::operator [] (const IndexT pos) { if ( isNegative(pos) || pos > IndexT(string.length()) ) throw std::out_of_range(""); // Invalid index position if ( std::size_t(pos) == string.length() ) return null_char; return string[std::size_t(pos)]; } //---------------------------------------------------------------------- template inline FString::const_reference FString::operator [] (const IndexT pos) const { if ( isNegative(pos) || pos > IndexT(string.length()) ) throw std::out_of_range(""); // Invalid index position if ( std::size_t(pos) == string.length() ) return const_null_char; return string[std::size_t(pos)]; } //---------------------------------------------------------------------- template inline bool FString::operator < (const CharT& s) const { const FString tmp(s); return *this < tmp; } //---------------------------------------------------------------------- template inline bool FString::operator <= (const CharT& s) const { const FString tmp(s); return *this <= tmp; } //---------------------------------------------------------------------- template inline bool FString::operator == (const CharT& s) const { const FString tmp(s); return *this == tmp; } //---------------------------------------------------------------------- template inline bool FString::operator != (const CharT& s) const { const FString tmp(s); return *this != tmp; } //---------------------------------------------------------------------- template inline bool FString::operator >= (const CharT& s) const { const FString tmp(s); return *this >= tmp; } //---------------------------------------------------------------------- template inline bool FString::operator > (const CharT& s) const { const FString tmp(s); return *this > tmp; } //---------------------------------------------------------------------- inline FString FString::getClassName() const { return "FString"; } //---------------------------------------------------------------------- inline bool FString::isNull() const noexcept // deprecated { return false; } //---------------------------------------------------------------------- inline bool FString::isEmpty() const noexcept { return string.empty(); } //---------------------------------------------------------------------- inline std::size_t FString::getLength() const noexcept { return string.length(); } //---------------------------------------------------------------------- inline std::size_t FString::capacity() const noexcept { return string.capacity(); } //---------------------------------------------------------------------- inline FString::iterator FString::begin() noexcept { return string.begin(); } //---------------------------------------------------------------------- inline FString::iterator FString::end() noexcept { return string.end(); } //---------------------------------------------------------------------- inline FString::const_iterator FString::begin() const noexcept { return string.cbegin(); } //---------------------------------------------------------------------- inline FString::const_iterator FString::end() const noexcept { return string.cend(); } //---------------------------------------------------------------------- inline FString::reference FString::front() { assert ( ! isEmpty() ); return string.front(); } //---------------------------------------------------------------------- inline FString::reference FString::back() { assert( ! isEmpty() ); return string.back(); } //---------------------------------------------------------------------- inline FString::const_reference FString::front() const { assert ( ! isEmpty() ); return string.front(); } //---------------------------------------------------------------------- inline FString::const_reference FString::back() const { assert( ! isEmpty() ); return string.back(); } //---------------------------------------------------------------------- template inline FString& FString::sprintf (const FString& format, Args&&... args) { std::array buf{}; if ( format.isEmpty() ) { clear(); return *this; } std::swprintf ( buf.data(), buf.size(), format.wc_str() , std::forward(args)... ); setString(buf.data()); return *this; } //---------------------------------------------------------------------- template inline FString& FString::setNumber (NumT num, int precision) { if ( std::is_floating_point::value ) return setNumber (lDouble(num), precision); if ( isNegative(num) ) return setNumber (sInt64(num)); return setNumber (uInt64(num)); } //---------------------------------------------------------------------- template inline FString& FString::setFormatedNumber (NumT num, char separator) { if ( isNegative(num) ) return setFormatedNumber (sInt64(num), separator); return setFormatedNumber (uInt64(num), separator); } } // namespace finalcut #endif // FSTRING_H