FINAL CUT
ftypes.h
1 /***********************************************************************
2 * ftypes.h - Implements global data types *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2017-2024 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 #ifndef FTYPES_H
24 #define FTYPES_H
25 
26 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
27  #error "Only <final/final.h> can be included directly."
28 #endif
29 
30 #include <sys/types.h>
31 #include <cassert>
32 #include <cstddef>
33 #include <cstdint>
34 #include <cstring>
35 #include <cwctype>
36 
37 #include <array>
38 #include <chrono>
39 #include <functional>
40 #include <limits>
41 #include <memory>
42 #include <string>
43 #include <utility>
44 
45 #include "final/eventloop/pipedata.h"
46 
47 #if (defined(__APPLE__) && defined(__MACH__)) || defined(__OpenBSD__)
48  #define USE_KQUEUE_TIMER
49 #endif
50 
51 #if !(defined(__APPLE__) && defined(__MACH__)) && !(defined(__OpenBSD__))
52  #define USE_POSIX_TIMER
53 #endif
54 
55 #define null nullptr
56 
57 #ifdef __has_builtin
58  #define HAVE_BUILTIN(x) __has_builtin(x)
59 #else
60  #define HAVE_BUILTIN(x) 0
61 #endif
62 
63 #define badAllocOutput(object_name) \
64  std::clog << FLog::LogLevel::Error \
65  << __FILE__ << ":" << __LINE__ \
66  << ": Not enough memory to alloc " \
67  << (object_name) \
68  << " in " \
69  << __func__ << std::endl // ;
70 
71 using uChar = unsigned char;
72 using uShort = unsigned short;
73 using uInt = unsigned int;
74 using uLong = unsigned long;
75 using uInt8 = std::uint8_t;
76 using uInt16 = std::uint16_t;
77 using uInt32 = std::uint32_t;
78 using uInt64 = std::uint64_t;
79 
80 using sInt = signed int;
81 using sLong = signed long;
82 using sInt8 = std::int8_t;
83 using sInt16 = std::int16_t;
84 using sInt32 = std::int32_t;
85 using sInt64 = std::int64_t;
86 
87 using lDouble = long double;
88 using TimeValue = std::chrono::time_point<std::chrono::system_clock>;
89 using FCall = std::function<void()>;
90 
91 namespace finalcut
92 {
93 
94 namespace internal
95 {
96 
97 template <typename T
98  , bool is_signed>
100 {
101  constexpr auto operator () (const T& x) const noexcept -> bool
102  {
103  return x < 0;
104  }
105 };
106 
107 template <typename T>
108 struct is_negative<T, false>
109 {
110  constexpr auto operator () (const T&) const noexcept -> bool
111  {
112  return false;
113  }
114 };
115 
116 } // namespace internal
117 
118 // Check for 7-bit ASCII
119 template<typename CharT>
120 constexpr auto is7bit (CharT ch) noexcept -> bool
121 {
122  using char_type = std::make_unsigned_t<CharT>;
123  return static_cast<char_type>(ch) < 128;
124 }
125 
126 // Printable character verification
127 inline auto isPrintable (char ch) noexcept -> bool
128 {
129  return std::isprint(static_cast<unsigned char>(ch));
130 }
131 
132 inline auto isPrintable (wchar_t ch) noexcept -> bool
133 {
134  return std::iswprint(std::wint_t(ch));
135 }
136 
137 // Typecast to c-string
138 template <typename StringT>
139 constexpr auto C_STR (StringT&& string) noexcept
140 {
141  return const_cast<char*>(std::forward<StringT>(string));
142 }
143 
144 template <typename T>
145 constexpr auto isNegative (const T& x) noexcept -> bool
146 {
148 }
149 
150 template <typename T>
152 {
153  constexpr explicit operator int () const noexcept
154  {
155  return std::numeric_limits<T>::digits10;
156  }
157 };
158 
159 template <typename T>
160 struct EnumHash
161 {
162  constexpr auto operator () (const T& mt) const noexcept -> std::size_t
163  {
164  using underlying_type = std::underlying_type_t<T>;
165  return std::hash<underlying_type>{}(underlying_type(mt));
166  }
167 };
168 
169 template <typename CharT>
170 constexpr auto stringLength (const CharT* s) noexcept -> std::size_t
171 {
172  return std::char_traits<CharT>::length(s);
173 }
174 
175 template <typename CharT>
176 using remove_ptr_t = std::remove_pointer_t<CharT>;
177 
178 template <typename CharT>
179 using remove_ptr_cv_t = std::remove_cv_t<remove_ptr_t<CharT>>;
180 
181 template <typename CharT>
182 using is_char_based_ptr = std::is_same<char, remove_ptr_cv_t<CharT>>;
183 
184 template <typename CharT>
185 using is_wchar_based_ptr = std::is_same<wchar_t, remove_ptr_cv_t<CharT>>;
186 
187 template <typename CharT>
188 using remove_ref_t = std::remove_reference_t<CharT>;
189 
190 template <typename CharT>
191 using remove_ref_extent_t = std::remove_extent_t<remove_ref_t<CharT>>;
192 
193 template <typename CharT>
194 using remove_ref_extent_cv_t = std::remove_cv_t<remove_ref_extent_t<CharT>>;
195 
196 template <typename CharT>
197 using is_char_based_array = typename std::is_same<char, remove_ref_extent_cv_t<CharT>>;
198 
199 template <typename CharT>
200 using is_wchar_based_array = typename std::is_same<wchar_t, remove_ref_extent_cv_t<CharT>>;
201 
202 template <typename CharT>
203 using enable_if_char_ptr_t =
204  std::enable_if_t<
205  std::is_pointer<CharT>::value && is_char_based_ptr<CharT>::value
206  , std::nullptr_t>;
207 
208 template <typename CharT>
209 using enable_if_char_array_t =
210  std::enable_if_t<
211  std::is_array<remove_ref_t<CharT>>::value && is_char_based_array<CharT>::value
212  , std::nullptr_t>;
213 
214 template <typename CharT>
215 using enable_if_CString_t =
216  std::enable_if_t<
217  (std::is_pointer<CharT>::value && is_char_based_ptr<CharT>::value)
218  || (std::is_array<remove_ref_t<CharT>>::value && is_char_based_array<CharT>::value)
219  , std::nullptr_t>;
220 
221 template <typename CharT>
222 struct isCString
223  : std::integral_constant<bool
224  , (std::is_pointer<CharT>::value && is_char_based_ptr<CharT>::value)
225  || (std::is_array<remove_ref_t<CharT>>::value && is_char_based_array<CharT>::value)>
226 { };
227 
228 template <typename CharT>
229 using enable_if_wchar_ptr_t =
230  std::enable_if_t<
231  std::is_pointer<CharT>::value && is_wchar_based_ptr<CharT>::value
232  , std::nullptr_t>;
233 
234 template <typename CharT>
235 using enable_if_wchar_array_t =
236  std::enable_if_t<
237  std::is_array<remove_ref_t<CharT>>::value && is_wchar_based_array<CharT>::value
238  , std::nullptr_t>;
239 
240 template <typename CharT>
241 using enable_if_WCString_t =
242  std::enable_if_t<
243  (std::is_pointer<CharT>::value && is_wchar_based_ptr<CharT>::value)
244  || (std::is_array<remove_ref_t<CharT>>::value && is_wchar_based_array<CharT>::value)
245  , std::nullptr_t>;
246 
247 template <typename CharT>
249  : std::integral_constant<bool
250  , (std::is_pointer<CharT>::value && is_wchar_based_ptr<CharT>::value)
251  || (std::is_array<remove_ref_t<CharT>>::value && is_wchar_based_array<CharT>::value)>
252 { };
253 
254 template <typename NumT>
255 using enable_if_arithmetic_without_char_t =
256  std::enable_if_t< std::is_arithmetic<NumT>::value
257  && ! std::is_same<char, NumT>::value
258  , std::nullptr_t>;
259 
261 {
262  uInt8 p1 : 1; // Standout
263  uInt8 p2 : 1; // Underline
264  uInt8 p3 : 1; // Reverse
265  uInt8 p4 : 1; // Blink
266  uInt8 p5 : 1; // Dim
267  uInt8 p6 : 1; // Bold
268  uInt8 p7 : 1; // Invisible
269  uInt8 p8 : 1; // Protected
270  uInt8 p9 : 1; // Alternate charset
271  uInt8 : 7; // padding bits
272 };
273 
275 {
276  // Attribute byte #0
277  uInt8 bold : 1; // bold
278  uInt8 dim : 1; // dim
279  uInt8 italic : 1; // italic
280  uInt8 underline : 1; // underline
281  uInt8 blink : 1; // blink
282  uInt8 reverse : 1; // reverse
283  uInt8 standout : 1; // standout
284  uInt8 invisible : 1; // invisible
285  // Attribute byte #1
286  uInt8 protect : 1; // protect mode
287  uInt8 crossed_out : 1; // crossed out
288  uInt8 dbl_underline : 1; // double underline
289  uInt8 alt_charset : 1; // alternate character set (vt100)
290  uInt8 pc_charset : 1; // pc character set (CP437)
291  uInt8 transparent : 1; // transparent
292  uInt8 color_overlay : 1; // color overlay
293  uInt8 inherit_background : 1; // inherit background
294  // Attribute byte #2
295  uInt8 no_changes : 1; // no changes required
296  uInt8 printed : 1; // is printed to VTerm
297  uInt8 fullwidth_padding : 1; // padding char (after a full-width char)
298  uInt8 char_width : 2; // number of character cells on screen
299  uInt8 : 3; // padding bits
300  // Attribute byte #3
301  uInt8 : 8; // padding byte
302 };
303 
304 #if HAVE_BUILTIN(__builtin_bit_cast)
305 constexpr auto getFAttributeByte ( const FCharAttribute& fchar_attr
306  , std::size_t index ) noexcept -> uInt8
307 {
308  return (__builtin_bit_cast(uInt32, fchar_attr) >> (index << 3)) & 0xff;
309 }
310 #else
311 inline auto getFAttributeByte ( const FCharAttribute& fchar_attr
312  , std::size_t index ) noexcept -> uInt8
313 {
314  uInt8 byte{};
315  std::memcpy (&byte, reinterpret_cast<const uInt8*>(&fchar_attr) + index, sizeof(uInt8));
316  return byte;
317 }
318 #endif
319 
320 #if HAVE_BUILTIN(__builtin_bit_cast)
321 constexpr auto setFAttributeByte ( FCharAttribute& fchar_attr
322  , const std::size_t index
323  , const uInt8 value ) noexcept
324 {
325  if ( index >= sizeof(FCharAttribute) )
326  return; // index out of bounds
327 
328  const auto clear_value = __builtin_bit_cast(uInt32, fchar_attr) & ~(uInt32(0xff) << (index << 3));
329  const auto ret = clear_value | (uInt32(value) << (index << 3));
330  fchar_attr = __builtin_bit_cast(FCharAttribute, ret);
331 }
332 #else
333 inline auto setFAttributeByte ( FCharAttribute& fchar_attr
334  , std::size_t index
335  , uInt8 value ) noexcept
336 {
337  assert ( index < sizeof(FCharAttribute) );
338  std::memcpy(reinterpret_cast<uInt8*>(&fchar_attr) + index, &value, sizeof(uInt8));
339 }
340 #endif
341 
342 #if HAVE_BUILTIN(__builtin_bit_cast)
343 constexpr auto getFAttributeWord (const FCharAttribute& fchar_attr) noexcept -> uInt32
344 {
345  return __builtin_bit_cast(uInt32, fchar_attr);
346 }
347 #else
348 inline auto getFAttributeWord (const FCharAttribute& fchar_attr) noexcept -> uInt32
349 {
350  uInt32 word{};
351  std::memcpy(&word, &fchar_attr, sizeof(word));
352  return word;
353 }
354 #endif
355 
356 #if HAVE_BUILTIN(__builtin_bit_cast)
357 constexpr auto WordToFAttribute (uInt32 word) noexcept -> FCharAttribute
358 {
359  return __builtin_bit_cast(FCharAttribute, word);
360 }
361 #else
362 inline auto WordToFAttribute (uInt32 word) noexcept -> FCharAttribute
363 {
364  FCharAttribute fchar_attr{};
365  std::memcpy(&fchar_attr, &word, sizeof(fchar_attr));
366  return fchar_attr;
367 }
368 #endif
369 
371 {
372  uInt8 byte[4];
373  uInt32 word;
374  FCharAttribute bit;
375 };
376 
377 static constexpr std::size_t UNICODE_MAX = 5;
378 
379 using FUnicode = std::array<wchar_t, UNICODE_MAX>;
380 
381 enum class FColor : uInt16; // forward declaration
382 
383 
384 // FChar operator functions
385 //----------------------------------------------------------------------
386 #if HAVE_BUILTIN(__builtin_bit_cast)
387 constexpr auto isFUnicodeEqual (const FUnicode& lhs, const FUnicode& rhs) noexcept -> bool
388 {
389  // Check sizes first for early exit if sizes don't match
390  if ( lhs.size() != rhs.size() )
391  return false;
392 
393  // Perform a byte-wise comparison
394  return std::memcmp(&lhs[0], &rhs[0], lhs.size() * sizeof(wchar_t)) == 0;
395 }
396 #else
397 inline auto isFUnicodeEqual (const FUnicode& lhs, const FUnicode& rhs) noexcept -> bool
398 {
399  static_assert ( sizeof(lhs) == sizeof(rhs) , "Both sides are different sizes.");
400  // Perform a byte-wise comparison
401  return std::wmemcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
402 }
403 #endif
404 
405 //----------------------------------------------------------------------
406 #if HAVE_BUILTIN(__builtin_bit_cast)
407 constexpr auto getCompareBitMask() noexcept -> uInt32
408 {
409  constexpr const FAttribute mask {{ 0xff, 0xff, 0x04, 0x00 }};
410  return __builtin_bit_cast(uInt32, mask.byte);
411 }
412 #else
413 inline auto getCompareBitMask() noexcept -> uInt32
414 {
415  const FAttribute mask {{ 0xff, 0xff, 0x04, 0x00 }};
416  uInt32 word{};
417  std::memcpy(&word, &mask, sizeof(word));
418  return word;
419 }
420 #endif
421 
422 //----------------------------------------------------------------------
423 struct FChar
424 {
425  FUnicode ch{}; // Character code
426  FUnicode encoded_char{}; // Encoded output character
427  FColor fg_color{}; // Foreground color
428  FColor bg_color{}; // Background color
429  FAttribute attr{}; // Attributes
430 
431 #if HAVE_BUILTIN(__builtin_bit_cast)
432  friend constexpr
433 #else
434  friend inline
435 #endif
436  auto operator == (const FChar& lhs, const FChar& rhs) noexcept -> bool
437  {
438  if ( ! isFUnicodeEqual(lhs.ch, rhs.ch)
439  || lhs.fg_color != rhs.fg_color
440  || lhs.bg_color != rhs.bg_color )
441  return false;
442 
443  const auto mask = getCompareBitMask();
444 
445  if ( (lhs.attr.word & mask) != (rhs.attr.word & mask) )
446  return false;
447 
448  return true;
449  }
450 
451 #if HAVE_BUILTIN(__builtin_bit_cast)
452  friend constexpr
453 #else
454  friend inline
455 #endif
456  auto operator != (const FChar& lhs, const FChar& rhs) noexcept -> bool
457  {
458  return ! ( lhs == rhs );
459  }
460 };
461 
462 } // namespace finalcut
463 
464 #endif // FTYPES_H
Definition: ftypes.h:248
Definition: class_template.cpp:25
Definition: ftypes.h:423
Definition: ftypes.h:222
Definition: ftypes.h:260
Definition: ftypes.h:370
Definition: ftypes.h:151
Definition: ftypes.h:274
Definition: ftypes.h:99
Definition: ftypes.h:160