26 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT) 27 #error "Only <final/final.h> can be included directly." 30 #include <sys/types.h> 44 #include <type_traits> 48 #include "final/eventloop/pipedata.h" 50 #if (defined(__APPLE__) && defined(__MACH__)) || defined(__OpenBSD__) 51 #define USE_KQUEUE_TIMER 54 #if !(defined(__APPLE__) && defined(__MACH__)) && !(defined(__OpenBSD__)) 55 #define USE_POSIX_TIMER 59 #define HAVE_BUILTIN(x) __has_builtin(x) 61 #define HAVE_BUILTIN(x) 0 64 #define badAllocOutput(object_name) \ 65 std::clog << FLog::LogLevel::Error \ 66 << __FILE__ << ":" << __LINE__ \ 67 << ": Not enough memory to alloc " \ 70 << __func__ << std::endl // ; 72 using uChar =
unsigned char;
73 using uShort =
unsigned short;
74 using uInt =
unsigned int;
75 using uLong =
unsigned long;
76 using uInt8 = std::uint8_t;
77 using uInt16 = std::uint16_t;
78 using uInt32 = std::uint32_t;
79 using uInt64 = std::uint64_t;
81 using sInt =
signed int;
82 using sLong =
signed long;
83 using sInt8 = std::int8_t;
84 using sInt16 = std::int16_t;
85 using sInt32 = std::int32_t;
86 using sInt64 = std::int64_t;
88 using lDouble =
long double;
89 using TimeValue = std::chrono::time_point<std::chrono::system_clock>;
90 using FCall = std::function<void()>;
102 constexpr
auto operator () (
const T& x)
const noexcept ->
bool 108 template <
typename T>
111 constexpr
auto operator () (
const T&)
const noexcept ->
bool 120 template<
typename CharT>
121 constexpr
auto is7bit (CharT ch) noexcept ->
bool 123 using char_type = std::make_unsigned_t<CharT>;
124 return static_cast<char_type
>(ch) < 128;
128 inline auto isPrintable (
char ch) noexcept ->
bool 130 return std::isprint(static_cast<unsigned char>(ch));
133 inline auto isPrintable (
wchar_t ch) noexcept ->
bool 135 return std::iswprint(std::wint_t(ch));
139 template <
typename StringT>
140 constexpr
auto C_STR (StringT&&
string) noexcept
142 return const_cast<char*
>(std::forward<StringT>(string));
145 template <
typename T>
146 constexpr
auto isNegative (
const T& x) noexcept ->
bool 151 template <
typename T>
154 constexpr
explicit operator int ()
const noexcept
156 return std::numeric_limits<T>::digits10;
160 template <
typename T>
163 constexpr
auto operator () (
const T& mt)
const noexcept -> std::size_t
165 using underlying_type = std::underlying_type_t<T>;
166 return std::hash<underlying_type>{}(underlying_type(mt));
170 template <
typename CharT>
171 constexpr
auto stringLength (
const CharT* s) noexcept -> std::size_t
173 return std::char_traits<CharT>::length(s);
176 template <
typename CharT>
177 using remove_ptr_t = std::remove_pointer_t<CharT>;
179 template <
typename CharT>
180 using remove_ptr_cv_t = std::remove_cv_t<remove_ptr_t<CharT>>;
182 template <
typename CharT>
183 using is_char_based_ptr = std::is_same<char, remove_ptr_cv_t<CharT>>;
185 template <
typename CharT>
186 using is_wchar_based_ptr = std::is_same<wchar_t, remove_ptr_cv_t<CharT>>;
188 template <
typename CharT>
189 using remove_ref_t = std::remove_reference_t<CharT>;
191 template <
typename CharT>
192 using remove_ref_extent_t = std::remove_extent_t<remove_ref_t<CharT>>;
194 template <
typename CharT>
195 using remove_ref_extent_cv_t = std::remove_cv_t<remove_ref_extent_t<CharT>>;
197 template <
typename CharT>
198 using is_char_based_array =
typename std::is_same<char, remove_ref_extent_cv_t<CharT>>;
200 template <
typename CharT>
201 using is_wchar_based_array =
typename std::is_same<wchar_t, remove_ref_extent_cv_t<CharT>>;
203 template <
typename CharT>
204 using enable_if_char_ptr_t =
206 std::is_pointer<CharT>::value && is_char_based_ptr<CharT>::value
209 template <
typename CharT>
210 using enable_if_char_array_t =
212 std::is_array<remove_ref_t<CharT>>::value && is_char_based_array<CharT>::value
215 template <
typename CharT>
216 using enable_if_CString_t =
218 (std::is_pointer<CharT>::value && is_char_based_ptr<CharT>::value)
219 || (std::is_array<remove_ref_t<CharT>>::value && is_char_based_array<CharT>::value)
222 template <
typename CharT>
224 : std::integral_constant<bool
225 , (std::is_pointer<CharT>::value && is_char_based_ptr<CharT>::value)
226 || (std::is_array<remove_ref_t<CharT>>::value && is_char_based_array<CharT>::value)>
229 template <
typename CharT>
230 using enable_if_wchar_ptr_t =
232 std::is_pointer<CharT>::value && is_wchar_based_ptr<CharT>::value
235 template <
typename CharT>
236 using enable_if_wchar_array_t =
238 std::is_array<remove_ref_t<CharT>>::value && is_wchar_based_array<CharT>::value
241 template <
typename CharT>
242 using enable_if_WCString_t =
244 (std::is_pointer<CharT>::value && is_wchar_based_ptr<CharT>::value)
245 || (std::is_array<remove_ref_t<CharT>>::value && is_wchar_based_array<CharT>::value)
248 template <
typename CharT>
250 : std::integral_constant<bool
251 , (std::is_pointer<CharT>::value && is_wchar_based_ptr<CharT>::value)
252 || (std::is_array<remove_ref_t<CharT>>::value && is_wchar_based_array<CharT>::value)>
255 template <
typename NumT>
256 using enable_if_arithmetic_without_char_t =
257 std::enable_if_t< std::is_arithmetic<NumT>::value
258 && ! std::is_same<char, NumT>::value
265 inline void expand (std::vector<char>& buffer, std::size_t addend)
267 buffer.resize(buffer.size() + addend);
270 inline void expand (std::array<char, 4>&, std::size_t)
275 template <
typename T>
276 using DecayedT =
typename std::decay_t<T>;
278 template <
typename CharBufferT>
279 using uInt32_if_vector_or_array = std::enable_if_t<
280 std::is_same<DecayedT<CharBufferT>, std::vector<char>>::value
281 || std::is_same<DecayedT<CharBufferT>, std::array<char, 4>>::value
284 #if defined(__CYGWIN__) 286 template <
typename CharBufferT>
287 inline auto encode (
wchar_t ucs, CharBufferT& buffer) -> uInt32_if_vector_or_array<CharBufferT>
290 const auto index = std::is_same<CharBufferT, std::vector<char>>::value
298 const auto dest = &buffer[index];
307 const auto dest = &buffer[index];
308 dest[0] = char(0xc0 | uChar(ucs >> 6u));
309 dest[1] = char(0x80 | uChar(ucs & 0x3f));
315 const auto dest = &buffer[index];
316 dest[0] = char(0xe0 | uChar(ucs >> 12u));
317 dest[1] = char(0x80 | uChar((ucs >> 6u) & 0x3f));
318 dest[2] = char(0x80 | uChar(ucs & 0x3f));
324 template <
typename CharBufferT>
325 inline auto encode (
wchar_t ucs, CharBufferT& buffer) -> uInt32_if_vector_or_array<CharBufferT>
328 const auto index = std::is_same<CharBufferT, std::vector<char>>::value
336 const auto dest = &buffer[index];
345 const auto dest = &buffer[index];
346 dest[0] = char(0xc0 | uChar(ucs >> 6u));
347 dest[1] = char(0x80 | uChar(ucs & 0x3f));
355 const auto dest = &buffer[index];
356 dest[0] = char(0xe0 | uChar(ucs >> 12u));
357 dest[1] = char(0x80 | uChar((ucs >> 6u) & 0x3f));
358 dest[2] = char(0x80 | uChar(ucs & 0x3f));
363 if ( ucs < 0x200000 )
366 const auto dest = &buffer[index];
367 dest[0] = char(0xf0 | uChar(ucs >> 18u));
368 dest[1] = char(0x80 | uChar((ucs >> 12u) & 0x3f));
369 dest[2] = char(0x80 | uChar((ucs >> 6u) & 0x3f));
370 dest[3] = char(0x80 | uChar(ucs & 0x3f));
374 return encode(L
'\uFFFD', buffer);
397 uInt8 crossed_out : 1;
398 uInt8 dbl_underline : 1;
399 uInt8 alt_charset : 1;
400 uInt8 pc_charset : 1;
401 uInt8 transparent : 1;
402 uInt8 color_overlay : 1;
403 uInt8 inherit_background : 1;
405 uInt8 no_changes : 1;
407 uInt8 fullwidth_padding : 1;
408 uInt8 char_width : 2;
416 return uInt32(fchar_attr.bold) << 0U
417 | uInt32(fchar_attr.dim) << 1U
418 | uInt32(fchar_attr.italic) << 2U
419 | uInt32(fchar_attr.underline) << 3U
420 | uInt32(fchar_attr.blink) << 4U
421 | uInt32(fchar_attr.reverse) << 5U
422 | uInt32(fchar_attr.standout) << 6U
423 | uInt32(fchar_attr.invisible) << 7U
424 | uInt32(fchar_attr.protect) << 8U
425 | uInt32(fchar_attr.crossed_out) << 9U
426 | uInt32(fchar_attr.dbl_underline) << 10U
427 | uInt32(fchar_attr.alt_charset) << 11U
428 | uInt32(fchar_attr.pc_charset) << 12U
429 | uInt32(fchar_attr.transparent) << 13U
430 | uInt32(fchar_attr.color_overlay) << 14U
431 | uInt32(fchar_attr.inherit_background) << 15U
432 | uInt32(fchar_attr.no_changes) << 16U
433 | uInt32(fchar_attr.printed) << 17U
434 | uInt32(fchar_attr.fullwidth_padding) << 18U
435 | uInt32(fchar_attr.char_width) << 19U;
442 constexpr
auto createMask (T setter) noexcept -> uInt32
446 return FCharAttribute_to_uInt32(mask);
466 attr.underline =
true;
481 attr.standout =
true;
486 attr.invisible =
true;
496 attr.crossed_out =
true;
499 constexpr
void setDblUnderlineMask (
FCharAttribute& attr) noexcept
501 attr.dbl_underline =
true;
506 attr.alt_charset =
true;
511 attr.pc_charset =
true;
516 attr.transparent =
true;
521 attr.color_overlay =
true;
524 constexpr
void setInheritBackground (
FCharAttribute& attr) noexcept
526 attr.inherit_background =
true;
531 attr.no_changes =
true;
539 constexpr
void setFullwidthPadding (
FCharAttribute& attr) noexcept
541 attr.fullwidth_padding =
true;
546 attr.char_width = 0x03;
551 constexpr
auto getFAttributeByte (
const FCharAttribute& fchar_attr
552 , std::size_t index ) noexcept -> uInt8
554 return (FCharAttribute_to_uInt32(fchar_attr) >> (index << 3)) & 0xff;
557 #if HAVE_BUILTIN(__builtin_bit_cast) 559 ,
const std::size_t index
560 ,
const uInt8 value ) noexcept
565 const auto clear_value = __builtin_bit_cast(uInt32, fchar_attr) & ~(uInt32(0xff) << (index << 3));
566 const auto ret = clear_value | (uInt32(value) << (index << 3));
572 , uInt8 value ) noexcept
575 std::memcpy(reinterpret_cast<uInt8*>(&fchar_attr) + index, &value,
sizeof(uInt8));
579 #if HAVE_BUILTIN(__builtin_bit_cast) 580 constexpr
auto getFAttributeData (
const FCharAttribute& fchar_attr) noexcept -> uInt32
582 return FCharAttribute_to_uInt32(fchar_attr);
585 inline auto getFAttributeData (
const FCharAttribute& fchar_attr) noexcept -> uInt32
588 std::memcpy(&data, &fchar_attr,
sizeof(data));
593 #if HAVE_BUILTIN(__builtin_bit_cast) 594 constexpr
auto WordToFAttribute (uInt32 data) noexcept ->
FCharAttribute 599 inline auto DataToFAttribute (uInt32 data) noexcept ->
FCharAttribute 602 std::memcpy(&fchar_attr, &data,
sizeof(fchar_attr));
611 static constexpr
auto bold = internal::createMask(internal::setBoldMask);
612 static constexpr
auto dim = internal::createMask(internal::setDimMask);
613 static constexpr
auto italic = internal::createMask(internal::setItalicMask);
614 static constexpr
auto underline = internal::createMask(internal::setUnderlineMask);
615 static constexpr
auto blink = internal::createMask(internal::setBlinkMask);
616 static constexpr
auto reverse = internal::createMask(internal::setReverseMask);
617 static constexpr
auto standout = internal::createMask(internal::setStandoutMask);
618 static constexpr
auto invisible = internal::createMask(internal::setInvisibleMask);
619 static constexpr
auto protect = internal::createMask(internal::setProtectMask);
620 static constexpr
auto crossed_out = internal::createMask(internal::setCrossedOutMask);
621 static constexpr
auto dbl_underline = internal::createMask(internal::setDblUnderlineMask);
622 static constexpr
auto alt_charset = internal::createMask(internal::setAltCharsetMask);
623 static constexpr
auto pc_charset = internal::createMask(internal::setPcCharsetMask);
624 static constexpr
auto transparent = internal::createMask(internal::setTransparent);
625 static constexpr
auto color_overlay = internal::createMask(internal::setColorOverlay);
626 static constexpr
auto inherit_background = internal::createMask(internal::setInheritBackground);
627 static constexpr
auto no_changes = internal::createMask(internal::setNoChanges);
628 static constexpr
auto printed = internal::createMask(internal::setPrinted);
629 static constexpr
auto fullwidth_padding = internal::createMask(internal::setFullwidthPadding);
630 static constexpr
auto char_width = internal::createMask(internal::setCharWidth);
635 static constexpr
auto bold = ~
set::bold;
636 static constexpr
auto dim = ~
set::dim;
637 static constexpr
auto italic = ~
set::italic;
638 static constexpr
auto underline = ~
set::underline;
639 static constexpr
auto blink = ~
set::blink;
640 static constexpr
auto reverse = ~
set::reverse;
641 static constexpr
auto standout = ~
set::standout;
642 static constexpr
auto invisible = ~
set::invisible;
643 static constexpr
auto protect = ~
set::protect;
644 static constexpr
auto crossed_out = ~
set::crossed_out;
645 static constexpr
auto dbl_underline = ~
set::dbl_underline;
646 static constexpr
auto alt_charset = ~
set::alt_charset;
647 static constexpr
auto pc_charset = ~
set::pc_charset;
648 static constexpr
auto transparent = ~
set::transparent;
649 static constexpr
auto color_overlay = ~
set::color_overlay;
650 static constexpr
auto inherit_background = ~
set::inherit_background;
651 static constexpr
auto no_changes = ~
set::no_changes;
652 static constexpr
auto printed = ~
set::printed;
653 static constexpr
auto fullwidth_padding = ~
set::fullwidth_padding;
654 static constexpr
auto char_width = ~
set::char_width;
657 constexpr
auto hasBit (uInt32 mask)
const noexcept ->
bool 659 return (data & mask) != 0;
662 constexpr
void setBit (uInt32 mask) noexcept
667 constexpr
void clearBit (uInt32 mask) noexcept
672 constexpr
void toggleBit (uInt32 mask) noexcept
680 #if HAVE_BUILTIN(__builtin_bit_cast) 683 std::memcpy(&bit, &data,
sizeof(uInt32));
690 #if HAVE_BUILTIN(__builtin_bit_cast) 691 data = __builtin_bit_cast(uInt32, bit);
693 std::memcpy(&data, &bit,
sizeof(uInt32));
697 #if defined(UNIT_TEST) 707 std::memcpy(&bits, &parent.data,
sizeof(uInt32));
713 std::memcpy(&parent.data, &bits,
sizeof(uInt32));
730 std::memcpy(&bits, &p.data,
sizeof(uInt32));
739 auto bit() -> BitProxy
744 auto bit()
const -> ConstBitProxy
752 std::array<uInt8, 4> byte;
758 std::memcpy(&byte, &parent.data,
sizeof(uInt32));
764 std::memcpy(&parent.data, &byte,
sizeof(uInt32));
767 auto operator -> () -> std::array<uInt8, 4>*
774 struct ConstByteProxy
776 std::array<uInt8, 4> byte;
780 std::memcpy(&byte, &p.data,
sizeof(uInt32));
783 auto operator -> ()
const ->
const std::array<uInt8, 4>*
789 auto byte() -> ByteProxy
794 auto byte()
const -> ConstByteProxy
798 #endif // defined(UNIT_TEST) 806 static constexpr std::size_t UNICODE_MAX = 5;
811 using iterator =
wchar_t*;
812 using const_iterator =
const wchar_t*;
813 using pointer =
wchar_t*;
814 using const_pointer =
const wchar_t*;
815 using reference =
wchar_t&;
816 using const_reference =
const wchar_t&;
817 using value_type = wchar_t;
820 constexpr
auto operator [] (std::size_t index) noexcept -> reference
822 #if defined(__clang__) 823 #pragma clang diagnostic push 824 #if __has_warning("-Wunsafe-buffer-usage") 825 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 828 return unicode_data[index];
829 #if defined(__clang__) 830 #pragma clang diagnostic pop 834 constexpr
auto operator [] (std::size_t index)
const noexcept -> const_reference
836 #if defined(__clang__) 837 #pragma clang diagnostic push 838 #if __has_warning("-Wunsafe-buffer-usage") 839 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 842 return unicode_data[index];
843 #if defined(__clang__) 844 #pragma clang diagnostic pop 849 constexpr
auto begin() noexcept -> iterator
851 return &unicode_data[0];
854 constexpr
auto end() noexcept -> iterator
856 #if defined(__clang__) 857 #pragma clang diagnostic push 858 #if __has_warning("-Wunsafe-buffer-usage") 859 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 862 return &unicode_data[UNICODE_MAX];
863 #if defined(__clang__) 864 #pragma clang diagnostic pop 868 constexpr
auto begin()
const noexcept -> const_iterator
870 return &unicode_data[0];
873 constexpr
auto end()
const noexcept -> const_iterator
875 #if defined(__clang__) 876 #pragma clang diagnostic push 877 #if __has_warning("-Wunsafe-buffer-usage") 878 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 881 return &unicode_data[UNICODE_MAX];
882 #if defined(__clang__) 883 #pragma clang diagnostic pop 887 constexpr
auto cbegin()
const noexcept -> const_iterator
889 return &unicode_data[0];
892 constexpr
auto cend()
const noexcept -> const_iterator
894 #if defined(__clang__) 895 #pragma clang diagnostic push 896 #if __has_warning("-Wunsafe-buffer-usage") 897 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 900 return &unicode_data[UNICODE_MAX];
901 #if defined(__clang__) 902 #pragma clang diagnostic pop 906 constexpr
auto data() noexcept -> pointer
908 return &unicode_data[0];
911 constexpr
auto data()
const noexcept -> const_pointer
913 return &unicode_data[0];
917 wchar_t unicode_data[UNICODE_MAX]{L
'\0', L
'\0', L
'\0', L
'\0', L
'\0'};
920 friend constexpr
auto operator == (
const FUnicode& lhs,
const FUnicode& rhs) noexcept ->
bool 922 #if defined(__clang__) 923 #pragma clang diagnostic push 924 #if __has_warning("-Wunsafe-buffer-usage") 925 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 928 return lhs.unicode_data[0] == rhs.unicode_data[0]
929 && lhs.unicode_data[1] == rhs.unicode_data[1]
930 && lhs.unicode_data[2] == rhs.unicode_data[2]
931 && lhs.unicode_data[3] == rhs.unicode_data[3]
932 && lhs.unicode_data[4] == rhs.unicode_data[4];
933 #if defined(__clang__) 934 #pragma clang diagnostic pop 938 friend constexpr
auto operator != (
const FUnicode& lhs,
const FUnicode& rhs) noexcept ->
bool 940 return ! ( lhs == rhs );
947 enum class FColor : uInt16;
961 explicit constexpr
FCellColor (uInt32 value) noexcept
965 constexpr
FCellColor (FColor fg, FColor bg) noexcept
966 : data{(uInt32(bg) << 16) | uInt32(fg)}
970 : data{(uInt32(color.bg) << 16) | uInt32(color.fg)}
974 constexpr
auto getPair()
const noexcept ->
FColors 977 #if HAVE_BUILTIN(__builtin_bit_cast) 978 pair = __builtin_bit_cast(
FColors, data);
980 std::memcpy( static_cast<void*>(&pair)
981 , static_cast<const void*>(&data)
987 constexpr
auto getFgColor()
const noexcept -> FColor
989 return FColor(data & 0x0000ffffU);
992 constexpr
auto getBgColor()
const noexcept -> FColor
994 return FColor(data >> 16);
998 constexpr
void setPair (
const FColors& pair) noexcept
1000 #if HAVE_BUILTIN(__builtin_bit_cast) 1001 data = __builtin_bit_cast(uInt32, pair);
1003 std::memcpy(&data, &pair,
sizeof(uInt32));
1007 constexpr
void setFgColor (
const FColor& fg) noexcept
1009 data = (data & 0xffff0000U) | uInt32(fg);
1012 constexpr
void setBgColor (
const FColor& bg) noexcept
1014 data = (data & 0x0000ffffU) | (uInt32(bg) << 16);
1018 constexpr
auto operator = (std::initializer_list<FColor> list) noexcept ->
FCellColor&
1020 if ( list.size() == 2 )
1022 auto iter = list.begin();
1023 data = uInt32(*iter);
1024 data |= (uInt32(*std::next(iter)) << 16);
1034 friend constexpr
auto operator == (
const FCellColor& lhs,
const FCellColor& rhs) noexcept ->
bool 1036 return lhs.data == rhs.data;
1039 friend constexpr
auto operator != (
const FCellColor& lhs,
const FCellColor& rhs) noexcept ->
bool 1041 return ! ( lhs == rhs );
1046 to.data = (to.data & 0x0000ffffU) | (from.data & 0xffff0000U);
1051 to.data = (to.data & 0xffff0000U) | (from.data & 0x0000ffffU);
1058 constexpr
auto getCompareBitMask() noexcept -> uInt32
1064 mask.underline =
true;
1066 mask.reverse =
true;
1067 mask.standout =
true;
1068 mask.invisible =
true;
1069 mask.protect =
true;
1070 mask.crossed_out =
true;
1071 mask.dbl_underline =
true;
1072 mask.alt_charset =
true;
1073 mask.pc_charset =
true;
1074 mask.transparent =
true;
1075 mask.color_overlay =
true;
1076 mask.inherit_background =
true;
1077 mask.fullwidth_padding =
true;
1078 return FCharAttribute_to_uInt32(mask);
1084 constexpr
auto getCharWidth()
const noexcept -> uInt32
1086 return (attr.data & FAttribute::set::char_width) >> 19U;
1090 constexpr
void setCharWidth (uInt32 width) noexcept
1092 attr.data = (attr.data & FAttribute::unset::char_width) \
1093 | ((width << 19U) & FAttribute::set::char_width);
1096 constexpr
void setBit (uInt32 mask,
bool enable) noexcept
1104 constexpr
void setBit (uInt32 mask) noexcept
1109 constexpr
void unsetBit (uInt32 mask) noexcept
1115 constexpr
auto isBitSet (uInt32 mask)
const noexcept ->
bool 1117 return attr.data & mask;
1127 #if HAVE_BUILTIN(__builtin_bit_cast) 1132 auto operator == (
const FChar& lhs,
const FChar& rhs) noexcept ->
bool 1134 if ( lhs.color.data != rhs.color.data )
1137 constexpr
auto mask = getCompareBitMask();
1139 if ( (lhs.attr.data & mask) != (rhs.attr.data & mask) )
1142 #if defined(__clang__) 1143 #pragma clang diagnostic push 1144 #if __has_warning("-Wunsafe-buffer-usage") 1145 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 1148 return lhs.ch.unicode_data[0] == rhs.ch.unicode_data[0]
1149 && lhs.ch.unicode_data[1] == rhs.ch.unicode_data[1]
1150 && lhs.ch.unicode_data[2] == rhs.ch.unicode_data[2]
1151 && lhs.ch.unicode_data[3] == rhs.ch.unicode_data[3]
1152 && lhs.ch.unicode_data[4] == rhs.ch.unicode_data[4];
1153 #if defined(__clang__) 1154 #pragma clang diagnostic pop 1158 #if HAVE_BUILTIN(__builtin_bit_cast) 1163 auto operator != (
const FChar& lhs,
const FChar& rhs) noexcept ->
bool 1165 return ! ( lhs == rhs );
Definition: class_template.cpp:25
Definition: ftypes.h:1081