34 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT) 35 #error "Only <final/final.h> can be included directly." 61 #include <type_traits> 66 #include "final/ftypes.h" 75 using FStringList = std::vector<FString>;
89 using std::runtime_error::runtime_error;
95 using size_type = std::wstring::size_type;
96 using difference_type = std::wstring::difference_type;
97 using iterator = std::wstring::iterator;
98 using const_iterator = std::wstring::const_iterator;
99 using reverse_iterator = std::wstring::reverse_iterator;
100 using const_reverse_iterator = std::wstring::const_reverse_iterator;
101 using reference = std::wstring::reference;
102 using const_reference = std::wstring::const_reference;
103 using value_type = wchar_t;
106 static constexpr size_type npos = std::wstring::npos;
113 FString (size_type,
const UniChar&);
117 #if __cplusplus >= 201703L 118 FString (
const std::wstring_view&);
123 #if __cplusplus >= 201703L 124 FString (
const std::string_view&);
145 auto operator << (
const UniChar&) ->
FString&;
146 auto operator << (
const wchar_t) ->
FString&;
147 auto operator << (
const char) ->
FString&;
148 template <
typename NumT
149 , std::enable_if_t< ( std::is_integral<NumT>::value
150 && ! std::is_same<NumT, bool>::value
151 && ! std::is_pointer<NumT>::value )
152 || ( std::is_floating_point<NumT>::value
153 && ! std::is_pointer<NumT>::value )
155 auto operator << (NumT) ->
FString&;
160 rhs.string.append(lhs.toWString());
164 friend inline auto operator >> (
const FString& lhs, std::wstring& rhs) ->
const FString&
166 rhs.append(lhs.toWString());
170 friend inline auto operator >> (
const FString& lhs, std::string& rhs) ->
const FString&
172 rhs.append(lhs.toString());
176 friend inline auto operator >> (
const FString& lhs,
wchar_t& rhs) ->
const FString&
178 rhs = ( ! lhs.isEmpty() ) ? lhs.string[0] : L
'\0';
182 friend inline auto operator >> (
const FString& lhs,
char& rhs) ->
const FString&
184 rhs = ( ! lhs.isEmpty() ) ?
char(uChar(lhs.string[0])) :
'\0';
188 friend inline auto operator >> (
const FString& lhs, sInt16& rhs) ->
const FString&
194 friend inline auto operator >> (
const FString& lhs, uInt16& rhs) ->
const FString&
196 rhs = lhs.toUShort();
200 friend inline auto operator >> (
const FString& lhs, sInt32& rhs) ->
const FString&
206 friend inline auto operator >> (
const FString& lhs, uInt32& rhs) ->
const FString&
212 friend inline auto operator >> (
const FString& lhs, sInt64& rhs) ->
const FString&
218 friend inline auto operator >> (
const FString& lhs, uInt64& rhs) ->
const FString&
224 friend inline auto operator >> (
const FString& lhs,
double& rhs) ->
const FString&
226 rhs = lhs.toDouble();
230 friend inline auto operator >> (
const FString& lhs,
float& rhs) ->
const FString&
237 template <
typename IndexT>
238 constexpr
auto operator [] (
const IndexT) -> reference;
239 template <
typename IndexT>
240 constexpr
auto operator [] (
const IndexT)
const -> const_reference;
243 explicit operator bool ()
const noexcept;
244 auto operator () ()
const noexcept ->
const FString&;
247 friend inline auto operator < (
const FString& lhs,
const FString& rhs) ->
bool 249 return lhs.string < rhs.string;
252 template <
typename CharT
253 , enable_if_char_ptr_t<CharT> =
nullptr>
254 friend inline auto operator < (
const FString& lhs,
const CharT& rhs) ->
bool 256 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
257 lhs.char_string = lhs.internal_toCharString(lhs.string);
258 return rhs ? lhs.char_string.compare(rhs) < 0 : lhs.char_string.compare(
"") < 0;
261 template <
typename CharT
262 , enable_if_char_array_t<CharT> =
nullptr>
263 friend inline auto operator < (
const FString& lhs,
const CharT& rhs) ->
bool 265 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
266 lhs.char_string = lhs.internal_toCharString(lhs.string);
267 return lhs.char_string.compare(rhs) < 0;
270 template <
typename CharT
271 , enable_if_wchar_ptr_t<CharT> =
nullptr>
272 friend inline auto operator < (
const FString& lhs,
const CharT& rhs) ->
bool 274 return rhs ? lhs.string.compare(rhs) < 0 : lhs.string.compare(L
"") < 0;
277 template <
typename CharT
278 , enable_if_wchar_array_t<CharT> =
nullptr>
279 friend inline auto operator < (
const FString& lhs,
const CharT& rhs) ->
bool 281 return lhs.string.compare(rhs) < 0;
284 friend inline auto operator <= (
const FString& lhs,
const FString& rhs) ->
bool 286 return lhs.string <= rhs.string;
289 template <
typename CharT
290 , enable_if_char_ptr_t<CharT> =
nullptr>
291 friend inline auto operator <= (
const FString& lhs,
const CharT& rhs) ->
bool 293 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
294 lhs.char_string = lhs.internal_toCharString(lhs.string);
295 return rhs ? lhs.char_string.compare(rhs) <= 0 : lhs.char_string.compare(
"") <= 0;
298 template <
typename CharT
299 , enable_if_char_array_t<CharT> =
nullptr>
300 friend inline auto operator <= (
const FString& lhs,
const CharT& rhs) ->
bool 302 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
303 lhs.char_string = lhs.internal_toCharString(lhs.string);
304 return lhs.char_string.compare(rhs) <= 0;
307 template <
typename CharT
308 , enable_if_wchar_ptr_t<CharT> =
nullptr>
309 friend inline auto operator <= (
const FString& lhs,
const CharT& rhs) ->
bool 311 return rhs ? lhs.string.compare(rhs) <= 0 : lhs.string.compare(L
"") <= 0;
314 template <
typename CharT
315 , enable_if_wchar_array_t<CharT> =
nullptr>
316 friend inline auto operator <= (
const FString& lhs,
const CharT& rhs) ->
bool 318 return lhs.string.compare(rhs) <= 0;
321 friend inline auto operator == (
const FString& lhs,
const FString& rhs) ->
bool 323 return lhs.string == rhs.string;
326 template <
typename CharT
327 , enable_if_char_ptr_t<CharT> =
nullptr>
328 friend inline auto operator == (
const FString& lhs,
const CharT& rhs) ->
bool 330 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
331 lhs.char_string = lhs.internal_toCharString(lhs.string);
332 return rhs ? lhs.char_string.compare(rhs) == 0 : lhs.char_string.compare(
"") == 0;
335 template <
typename CharT
336 , enable_if_char_array_t<CharT> =
nullptr>
337 friend inline auto operator == (
const FString& lhs,
const CharT& rhs) ->
bool 339 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
340 lhs.char_string = lhs.internal_toCharString(lhs.string);
341 return lhs.char_string.compare(rhs) == 0;
344 template <
typename CharT
345 , enable_if_wchar_ptr_t<CharT> =
nullptr>
346 friend inline auto operator == (
const FString& lhs,
const CharT& rhs) ->
bool 348 return rhs ? lhs.string.compare(rhs) == 0 : lhs.string.compare(L
"") == 0;
351 template <
typename CharT
352 , enable_if_wchar_array_t<CharT> =
nullptr>
353 friend inline auto operator == (
const FString& lhs,
const CharT& rhs) ->
bool 355 return lhs.string.compare(rhs) == 0;
358 friend inline auto operator != (
const FString& lhs,
const FString& rhs) ->
bool 360 return ! ( lhs == rhs );
363 template <
typename CharT
364 , enable_if_char_ptr_t<CharT> =
nullptr>
365 friend inline auto operator != (
const FString& lhs,
const CharT& rhs) ->
bool 367 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
368 lhs.char_string = lhs.internal_toCharString(lhs.string);
369 return rhs ? lhs.char_string.compare(rhs) != 0 : lhs.char_string.compare(
"") != 0;
372 template <
typename CharT
373 , enable_if_char_array_t<CharT> =
nullptr>
374 friend inline auto operator != (
const FString& lhs,
const CharT& rhs) ->
bool 376 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
377 lhs.char_string = lhs.internal_toCharString(lhs.string);
378 return lhs.char_string.compare(rhs) != 0;
381 template <
typename CharT
382 , enable_if_wchar_ptr_t<CharT> =
nullptr>
383 friend inline auto operator != (
const FString& lhs,
const CharT& rhs) ->
bool 385 return rhs ? lhs.string.compare(rhs) != 0 : lhs.string.compare(L
"") != 0;
388 template <
typename CharT
389 , enable_if_wchar_array_t<CharT> =
nullptr>
390 friend inline auto operator != (
const FString& lhs,
const CharT& rhs) ->
bool 392 return lhs.string.compare(rhs) != 0;
395 friend inline auto operator >= (
const FString& lhs,
const FString& rhs) ->
bool 397 return lhs.string >= rhs.string;
400 template <
typename CharT
401 , enable_if_char_ptr_t<CharT> =
nullptr>
402 friend inline auto operator >= (
const FString& lhs,
const CharT& rhs) ->
bool 404 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
405 lhs.char_string = lhs.internal_toCharString(lhs.string);
406 return rhs ? lhs.char_string.compare(rhs) >= 0 : lhs.char_string.compare(
"") >= 0;
409 template <
typename CharT
410 , enable_if_char_array_t<CharT> =
nullptr>
411 friend inline auto operator >= (
const FString& lhs,
const CharT& rhs) ->
bool 413 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
414 lhs.char_string = lhs.internal_toCharString(lhs.string);
415 return lhs.char_string.compare(rhs) >= 0;
418 template <
typename CharT
419 , enable_if_wchar_ptr_t<CharT> =
nullptr>
420 friend inline auto operator >= (
const FString& lhs,
const CharT& rhs) ->
bool 422 return rhs ? lhs.string.compare(rhs) >= 0 : lhs.string.compare(L
"") >= 0;
425 template <
typename CharT
426 , enable_if_wchar_array_t<CharT> =
nullptr>
427 friend inline auto operator >= (
const FString& lhs,
const CharT& rhs) ->
bool 429 return lhs.string.compare(rhs) >= 0;
432 friend inline auto operator > (
const FString& lhs,
const FString& rhs) ->
bool 434 return lhs.string > rhs.string;
437 template <
typename CharT
438 , enable_if_char_ptr_t<CharT> =
nullptr>
439 friend inline auto operator > (
const FString& lhs,
const CharT& rhs) ->
bool 441 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
442 lhs.char_string = lhs.internal_toCharString(lhs.string);
443 return rhs ? lhs.char_string.compare(rhs) > 0 : lhs.char_string.compare(
"") > 0;
446 template <
typename CharT
447 , enable_if_char_array_t<CharT> =
nullptr>
448 friend inline auto operator > (
const FString& lhs,
const CharT& rhs) ->
bool 450 std::lock_guard<std::mutex> lock(lhs.char_string_mutex);
451 lhs.char_string = lhs.internal_toCharString(lhs.string);
452 return lhs.char_string.compare(rhs) > 0;
455 template <
typename CharT
456 , enable_if_wchar_ptr_t<CharT> =
nullptr>
457 friend inline auto operator > (
const FString& lhs,
const CharT& rhs) ->
bool 459 return rhs ? lhs.string.compare(rhs) > 0 : lhs.string.compare(L
"") > 0;
462 template <
typename CharT
463 , enable_if_wchar_array_t<CharT> =
nullptr>
464 friend inline auto operator > (
const FString& lhs,
const CharT& rhs) ->
bool 466 return lhs.string.compare(rhs) > 0;
470 virtual auto getClassName()
const ->
FString;
471 auto getLength()
const noexcept -> size_type;
472 auto capacity()
const noexcept -> size_type;
473 auto size()
const noexcept -> size_type;
474 auto length()
const noexcept -> size_type;
475 auto max_size()
const noexcept -> size_type;
478 auto isEmpty()
const noexcept -> bool;
481 auto begin() noexcept -> iterator;
482 auto end() noexcept -> iterator;
483 auto begin()
const noexcept -> const_iterator;
484 auto end()
const noexcept -> const_iterator;
485 auto cbegin()
const noexcept -> const_iterator;
486 auto cend()
const noexcept -> const_iterator;
487 auto rbegin() noexcept -> reverse_iterator;
488 auto rend() noexcept -> reverse_iterator;
489 auto crbegin()
const noexcept -> const_reverse_iterator;
490 auto crend()
const noexcept -> const_reverse_iterator;
493 auto front() -> reference;
494 auto back() -> reference;
495 auto front()
const -> const_reference;
496 auto back()
const -> const_reference;
497 auto at (size_type) -> reference;
498 auto at (size_type)
const -> const_reference;
501 template <
typename... Args>
503 auto clear() noexcept ->
FString&;
504 auto reserve (size_type) ->
FString&;
505 auto shrink_to_fit() ->
FString&;
506 auto resize (size_type) ->
FString&;
507 auto resize (size_type,
wchar_t) ->
FString&;
510 auto wc_str()
const noexcept ->
const wchar_t*;
511 auto wc_str() noexcept ->
wchar_t*;
512 auto c_str()
const ->
const char*;
513 auto c_str() ->
char*;
514 auto data()
const noexcept ->
const wchar_t*;
515 auto data() noexcept ->
wchar_t*;
516 auto toWString()
const -> std::wstring;
517 auto toString()
const -> std::string;
520 auto toLower()
const ->
FString;
521 auto toUpper()
const ->
FString;
524 auto toShort()
const -> sInt16;
525 auto toUShort()
const -> uInt16;
526 auto toInt()
const -> int;
527 auto toUInt()
const -> uInt;
528 auto toLong()
const -> long;
529 auto toULong()
const -> uLong;
530 auto toFloat()
const -> float;
531 auto toDouble()
const -> double;
537 auto left (size_type)
const ->
FString;
538 auto right (size_type)
const ->
FString;
539 auto mid (size_type, size_type)
const ->
FString;
540 auto split (
const FString&)
const -> FStringList;
544 template <
typename NumT>
546 auto setNumber (sInt64) ->
FString&;
547 auto setNumber (uInt64) ->
FString&;
550 template <
typename NumT>
551 auto setFormatedNumber (NumT,
FString&& = nl_langinfo(THOUSEP)) ->
FString&;
552 auto setFormatedNumber (sInt64,
FString&& = nl_langinfo(THOUSEP)) ->
FString&;
553 auto setFormatedNumber (uInt64,
FString&& = nl_langinfo(THOUSEP)) ->
FString&;
561 auto replaceControlCodes()
const ->
FString;
562 auto expandTabs (
int = 8)
const ->
FString;
563 auto removeDel()
const ->
FString;
564 auto removeBackspaces()
const ->
FString;
569 auto remove (size_type = 0, size_type = npos) ->
FString&;
570 auto erase (size_type pos = 0, size_type len = npos) ->
FString&;
573 auto includes (
const FString&)
const noexcept -> bool;
574 auto contains (
const FString&)
const noexcept -> bool;
575 auto find (
const FString&, size_type = 0)
const noexcept -> size_type;
576 auto rfind (
const FString&, size_type = npos)
const noexcept -> size_type;
583 enum class Sign : bool { Negative, Positive };
586 static constexpr
auto INPBUFFER = size_type(256);
587 static constexpr
auto SPRINTF_BUFFER_SIZE = size_type(4096);
588 static constexpr
auto NUMBER_BUFFER_SIZE = size_type(30);
589 static constexpr
auto NUMBER_BUFFER_LENGTH = NUMBER_BUFFER_SIZE - 1;
590 static constexpr
auto MALFORMED_STRING = size_type(-1);
591 static constexpr
auto LONG_LIMIT = long(LONG_MAX / 10);
592 static constexpr
auto LONG_MIN_LIMIT_DIGIT = long(-(LONG_MIN % 10) + 1);
593 static constexpr
auto LONG_MAX_LIMIT_DIGIT = long(LONG_MAX % 10);
594 static constexpr
auto ULONG_LIMIT = uLong(ULONG_MAX / 10);
595 static constexpr
auto ULONG_LIMIT_DIGIT = uLong(ULONG_MAX % 10);
598 void internal_assign (std::wstring) noexcept;
599 auto internal_toCharString (
const std::wstring&)
const -> std::string;
600 auto internal_toWideString (
const char[])
const -> std::wstring;
601 void internal_skipLeadingWs (const_iterator&, const_iterator)
const noexcept;
602 auto internal_parseSign (const_iterator&)
const noexcept -> Sign;
603 auto internal_parseDigits (const_iterator&, const_iterator, Sign)
const -> long;
604 auto internal_parseDigits (const_iterator&, const_iterator)
const -> uLong;
605 auto internal_isOverflowed (Sign,
long,
long)
const noexcept -> bool;
606 auto internal_isOverflowed (uLong, uLong)
const noexcept -> bool;
607 template <
typename NumT>
611 std::wstring
string{};
612 mutable std::string char_string{};
613 mutable std::mutex char_string_mutex{};
614 static wchar_t null_char;
615 static const wchar_t const_null_char;
620 const auto& tmp = s1.string + s2.string;
624 friend auto operator << (std::ostream& outstr,
const FString& s) -> std::ostream&
626 const auto width = size_type(outstr.width());
628 if ( s.string.length() > 0 )
630 outstr << s.internal_toCharString(s.string);
632 else if ( width > 0 )
634 const std::string fill_str(width, outstr.fill());
641 friend auto operator >> (std::istream& instr,
FString& s) -> std::istream&
643 std::array<char, FString::INPBUFFER + 1> buf{};
644 instr.getline (buf.data(), FString::INPBUFFER);
645 auto wide_string = s.internal_toWideString(buf.data());
647 if ( ! wide_string.empty() )
649 s.internal_assign (std::move(wide_string));
655 friend auto operator << (std::wostream& outstr,
const FString& s) -> std::wostream&
657 const auto width = size_type(outstr.width());
659 if ( s.string.length() > 0 )
663 else if ( width > 0 )
665 const std::wstring fill_str(width, outstr.fill());
672 friend auto operator >> (std::wistream& instr,
FString& s) -> std::wistream&
674 std::array<wchar_t, FString::INPBUFFER + 1> buf{};
675 instr.getline (buf.data(), FString::INPBUFFER);
676 std::wstring str(buf.data());
677 s.internal_assign (std::move(str));
682 friend struct std::hash<finalcut::
FString>;
687 auto FStringCaseCompare (const FString&, const FString&) -> int;
691 template <typename NumT
692 , std::enable_if_t< ( std::is_integral<NumT>::value
693 && ! std::is_same<NumT, bool>::value
694 && ! std::is_pointer<NumT>::value )
695 || ( std::is_floating_point<NumT>::value
696 && ! std::is_pointer<NumT>::value )
698 inline auto FString::operator << (NumT value) -> FString&
700 const FString numstr(FString().setNumber(value));
701 string.append(numstr.string);
706 template <typename IndexT>
707 constexpr auto FString::operator [] (const IndexT pos) -> reference
709 if ( isNegative(pos) || pos > IndexT(
string.length()) )
710 throw std::out_of_range(
"FString::operator[] index out of range");
712 if ( size_type(pos) ==
string.length() )
715 return string[size_type(pos)];
719 template <
typename IndexT>
720 constexpr
auto FString::operator [] (
const IndexT pos)
const -> const_reference
722 if ( isNegative(pos) || pos > IndexT(
string.length()) )
723 throw std::out_of_range(
"FString::operator[] index out of range");
725 if ( size_type(pos) ==
string.length() )
726 return const_null_char;
728 return string[size_type(pos)];
732 inline auto FString::getClassName()
const ->
FString 733 {
return "FString"; }
736 inline auto FString::getLength()
const noexcept -> size_type
737 {
return string.length(); }
740 inline auto FString::capacity()
const noexcept -> size_type
741 {
return string.capacity(); }
744 inline auto FString::size()
const noexcept -> size_type
745 {
return string.size(); }
748 inline auto FString::length()
const noexcept -> size_type
749 {
return string.length(); }
752 inline auto FString::max_size()
const noexcept -> size_type
753 {
return string.max_size(); }
756 inline auto FString::isEmpty()
const noexcept ->
bool 757 {
return string.empty(); }
760 inline auto FString::begin() noexcept -> iterator
761 {
return string.begin(); }
764 inline auto FString::end() noexcept -> iterator
765 {
return string.end(); }
768 inline auto FString::begin()
const noexcept -> const_iterator
769 {
return this->
string.begin(); }
772 inline auto FString::end()
const noexcept -> const_iterator
773 {
return this->
string.end(); }
776 inline auto FString::cbegin()
const noexcept -> const_iterator
777 {
return this->
string.cbegin(); }
780 inline auto FString::cend()
const noexcept -> const_iterator
781 {
return this->
string.cend(); }
784 inline auto FString::rbegin() noexcept -> reverse_iterator
785 {
return string.rbegin(); }
788 inline auto FString::rend() noexcept -> reverse_iterator
789 {
return string.rend(); }
792 inline auto FString::crbegin()
const noexcept -> const_reverse_iterator
793 {
return string.crbegin(); }
796 inline auto FString::crend()
const noexcept -> const_reverse_iterator
797 {
return string.crend(); }
800 inline auto FString::front() -> reference
802 assert ( ! isEmpty() &&
"FString::front() called on empty string" );
803 return string.front();
807 inline auto FString::back() -> reference
809 assert( ! isEmpty() &&
"FString::back() called on empty string" );
810 return string.back();
814 inline auto FString::front()
const -> const_reference
816 assert ( ! isEmpty() &&
"FString::front() called on empty string" );
817 return string.front();
821 inline auto FString::back()
const -> const_reference
823 assert( ! isEmpty() &&
"FString::back() called on empty string" );
824 return string.back();
828 inline auto FString::at (size_type pos) -> reference
829 {
return string.at(pos); }
832 inline auto FString::at (size_type pos)
const -> const_reference
833 {
return string.at(pos); }
836 template <
typename... Args>
837 inline auto FString::sprintf (
const FString& format, Args&&... args) ->
FString&
839 std::array<wchar_t, SPRINTF_BUFFER_SIZE> buf{};
841 if ( format.isEmpty() )
847 const auto written = std::swprintf ( buf.data()
850 , std::forward<Args>(args)... );
852 if ( written < 0 || size_type(written) >= buf.size() )
853 throw formatting_error(
"FString::sprintf buffer overflow or encoding error");
855 return setString(buf.data());
859 inline auto FString::data()
const noexcept ->
const wchar_t*
860 {
return string.data(); }
863 inline auto FString::data() noexcept ->
wchar_t*
864 {
return const_cast<wchar_t*
>(
string.data()); }
867 template <
typename NumT>
868 inline auto FString::setNumber (NumT value,
int precision) ->
FString&
870 if ( std::is_floating_point<NumT>::value )
871 return setNumber (lDouble(value), precision);
873 if ( isNegative(value) )
874 return setNumber (sInt64(value));
876 return setNumber (uInt64(value));
880 template <
typename NumT>
881 inline auto FString::setFormatedNumber (NumT value,
FString&& separator) ->
FString&
883 if ( isNegative(value) )
884 return setFormatedNumber (sInt64(value), std::move(separator));
886 return setFormatedNumber (uInt64(value), std::move(separator));
890 inline void FString::swap (
FString& s) noexcept
892 s.string.swap(
string);
896 inline void FString::internal_assign (std::wstring s) noexcept
914 return std::hash<std::wstring>{}(str.string);
Definition: fstring.h:906
Definition: class_template.cpp:25