ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
boxing.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !DOXYGEN
10# include "alib/boxing/boxing.hpp"
12# if ALIB_MONOMEM
14# endif
15# if ALIB_DEBUG
17# endif
18# if ALIB_ENUMS && ALIB_STRINGS
21# endif
22# if ALIB_STRINGS
26# endif
27# if ALIB_CAMP
29# endif
30# include <cmath>
31# include <functional>
32#endif // !DOXYGEN
33
34
35#if ALIB_STRINGS
36 ALIB_BOXING_VTABLE_DEFINE( std::reference_wrapper<alib::strings::TAString<nchar ALIB_COMMA lang::HeapAllocator>>, vt_alib_wrapped_tanstring )
37 ALIB_BOXING_VTABLE_DEFINE( std::reference_wrapper<alib::strings::TAString<wchar ALIB_COMMA lang::HeapAllocator>>, vt_alib_wrapped_tawstring )
38 ALIB_BOXING_VTABLE_DEFINE( std::reference_wrapper<alib::strings::TAString<xchar ALIB_COMMA lang::HeapAllocator>>, vt_alib_wrapped_taxstring )
39#endif
40
42namespace alib {
43
44//==================================================================================================
45/// This is the reference documentation of sub-namespace \b boxing of the \aliblink, which
46/// holds types of library module \alib_boxing.
47///
48/// Extensive documentation for this module is provided with
49/// \ref alib_mod_boxing "ALib Module Boxing - Programmer's Manual".
50//==================================================================================================
51namespace boxing {
52
53// #################################################################################################
54// #################################################################################################
55// class Box
56// #################################################################################################
57// #################################################################################################
58
59#if ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
60 bool Box::IsSignedIntegral() const
61 {
62 #if ALIB_SIZEOF_INTEGER == 8
63 return IsType< int64_t >()
65 #else
66 return IsType< int32_t >()
68 #endif
72 }
73
74 bool Box::IsUnsignedIntegral() const
75 {
76 #if ALIB_SIZEOF_INTEGER == 8
77 return IsType<uint64_t >()
79 #else
80 return IsType<uint32_t >()
82 #endif
86 }
87
89 {
90 #if ALIB_SIZEOF_INTEGER == 8
91 return IsType< int64_t >() ? ( Unbox< int64_t >() )
92 : IsType< int32_t >() ? static_cast< integer>( Unbox< int32_t >() )
93 #else
94 return IsType< int32_t >() ? ( Unbox< int32_t >() )
95 : IsType< int64_t >() ? static_cast< integer>( Unbox< int64_t >() )
96 #endif
97 : IsType< int8_t >() ? static_cast< integer>( Unbox< int8_t >() )
98 : IsType< int16_t >() ? static_cast< integer>( Unbox< int16_t >() )
99 : static_cast< integer>( Unbox< intGap_t>() );
100 }
101
102
104 {
105 #if ALIB_SIZEOF_INTEGER == 8
106 return IsType<uint64_t >() ? ( Unbox<uint64_t >() )
107 : IsType<uint32_t >() ? static_cast<uinteger>( Unbox<uint32_t >() )
108 #else
109 return IsType<uint32_t >() ? ( Unbox<uint32_t >() )
110 : IsType<uint64_t >() ? static_cast<uinteger>( Unbox<uint64_t >() )
111 #endif
112 : IsType<uint8_t >() ? static_cast<uinteger>( Unbox<uint8_t >() )
113 : IsType<uint16_t >() ? static_cast<uinteger>( Unbox<uint16_t >() )
114 : static_cast<uinteger>( Unbox<uintGap_t>() );
115 }
116#endif
117
118#if ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
119bool Box::IsCharacter() const
120{
121 return IsType<char >()
124 || IsType<char32_t>();
125}
126
128{
129 return IsType<char >() ? static_cast<wchar>( Unbox<char >() )
130 : IsType<wchar_t >() ? static_cast<wchar>( Unbox<wchar_t >() )
131 : IsType<char16_t>() ? static_cast<wchar>( Unbox<char16_t>() )
132 : static_cast<wchar>( Unbox<char32_t>() );
133}
134#endif
135
137{
138 return IsType< double>()
139 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
140 || IsType< float >()
141 #endif
142 #if ALIB_SIZEOF_LONGDOUBLE_REPORTED <= 2 * ALIB_SIZEOF_INTEGER
144 #endif
145 ;
146}
147
149{
150 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
151 if( IsType< float >() ) return static_cast<double>( Unbox<float >() );
152 #endif
153
154 #if ALIB_SIZEOF_LONGDOUBLE_REPORTED <= 2 * ALIB_SIZEOF_INTEGER
155 if( IsType<long double>() ) return static_cast<double>( Unbox<long double>() );
156 #endif
157
158 return Unbox<double>();
159}
160
161 Box::operator bool() const { return Call<FIsTrue >(); }
162bool Box::IsNotNull () const { return Call<FIsNotNull >(); }
163size_t Box::Hashcode () const { return Call<FHashcode >(); }
165void Box::Clone( MonoAllocator& memory) { Call<FClone >( memory ); } )
166
167
168}} // namespace [alib::boxing]
169
170using namespace alib::boxing;
171bool Box::operator==(const Box& rhs) const { return Call<FEquals>( rhs ); }
172bool Box::operator< (const Box& rhs) const { return Call<FIsLess>( rhs ); }
173bool Box::operator<=(const Box& rhs) const { return Call<FIsLess>( rhs ) || Call<FEquals>( rhs ); }
174bool Box::operator> (const Box& rhs) const { return !Call<FIsLess>( rhs ) && !Call<FEquals>( rhs ); }
175namespace alib { namespace boxing {
176
177
178// #################################################################################################
179// #################################################################################################
180// class Boxes
181// #################################################################################################
182// #################################################################################################
183
184#if !DOXYGEN
185
186namespace {
187
188// #################################################################################################
189// #################################################################################################
190// Functions
191// #################################################################################################
192// #################################################################################################
193
194
195// #################################################################################################
196// FIsNotNull
197// #################################################################################################
198bool FIsNotNull_Default( const Box& box )
199{
200 return !( (box.IsArray() && box.UnboxLength() == 0 )
201 || (box.IsPointer() && box.Data().Pointers.CVoid == nullptr )
202 );
203}
204
205
206// #################################################################################################
207// FHashcode
208// #################################################################################################
209std::size_t FHashcode_Default( const Box& self )
210{
211 if( self.IsPointer() )
212 {
213 return size_t(0xa814e72cUL)
214 + size_t( self.TypeID().hash_code() )
215 + self.Data().Integrals.UInt * 89047023;
216 }
217
218 if( self.IsEnum() )
219 {
220 return size_t(0x49a024efUL)
221 + size_t( self.TypeID().hash_code() )
222 + self.Data().Integrals.UInt * 79204799;
223 }
224
225 if( self.IsArray() )
226 {
227 std::size_t result= 0xa925eb91L
228 + std::size_t( self.ElementTypeID().hash_code() );
229
230 // do different loops depending on array element size
231 auto size = self.ArrayElementSize();
232 auto length= self.UnboxLength();
233 if( size == 2 || size == 6 )
234 {
235 if (size == 6)
236 length*= 3;
237
238 uint16_t* array= self.Data().Pointer<uint16_t>();
239 for( integer i= 0 ; i < length ; ++i )
240 result = 67 * result + array[i];
241
242 return size_t( result );
243 }
244
245 if( size == 4 )
246 {
247 uint32_t* array= self.Data().Pointer<uint32_t>();
248 for( integer i= 0 ; i < length ; ++i )
249 result = 67*result + array[i];
250
251 return size_t( result );
252 }
253
254 if( size == 8 )
255 {
256 uint64_t* array= self.Data().Pointer<uint64_t>();
257 for( integer i= 0 ; i < length ; ++i )
258 result = std::size_t( 67 * result + array[i] );
259
260 return std::size_t( result );
261 }
262
263 // any other size
264 {
265 length*= size;
266 unsigned char* array= self.Data().Pointer<unsigned char>();
267 for( int i= 0 ; i < length ; ++i )
268 result = 67*result + array[i];
269
270 return size_t( result );
271 }
272 }
273
274 //--- default (value types) ---
275 size_t result= size_t(0xcf670957UL)
276 + size_t( self.TypeID().hash_code() );
277
278 unsigned int usedLen= self.GetPlaceholderUsageLength();
279
280 constexpr uinteger Bit1= static_cast<uinteger>( 1 );
281
282 // smaller than first "word"
283 if( usedLen < sizeof( uinteger ) )
284 return size_t( ( self.Data().GetUInteger(0)
285 & ((Bit1 << (usedLen * 8) )- 1) ) * 32194735 )
286 + result;
287
288 // add first word
289 result+= self.Data().GetUInteger(0) * 32194735;
290
291 if( usedLen == sizeof(uinteger) )
292 return result;
293
294 // tests if smaller than second "word"
295 if( usedLen - sizeof( uinteger ) < sizeof( uinteger ) )
296 {
297 return size_t( ( self.Data().GetUInteger(1)
298 & ((Bit1 << ((usedLen - sizeof(uinteger)) * 8) )- 1) ) * 321947 )
299 + result;
300 }
301
302 return result + self.Data().GetUInteger(1) * 321947;
303
304
305}
306
307// #################################################################################################
308// FEquals
309// #################################################################################################
310bool FEquals_Default( const Box& self, const Box& rhs )
311{
312 if( !self.IsSameType( rhs ) )
313 return false;
314
315 // array types?
316 if( self.IsArray() )
317 {
318 // different in type, length or nulled?
319 if( self.UnboxLength() != rhs.UnboxLength()
320 || ( ( self.Data().Pointer<char>() == nullptr)
321 != ( rhs .Data().Pointer<char>() == nullptr ) ) )
322 return false;
323
324 return self.Data().Pointer<char>() == nullptr
325 || self.UnboxLength() == 0
326 || self.Data().Pointer<char>() == rhs.Data().Pointer<char>()
327 || memcmp( self.Data().Pointer<char>(),
328 rhs .Data().Pointer<char>(),
329 static_cast <size_t>( self.UnboxLength() ) * self.ArrayElementSize()
330 ) == 0;
331 }
332
333 // non-array types
334 unsigned int usedLen= self.GetPlaceholderUsageLength();
335
336 constexpr uinteger Bit1= static_cast<uinteger>( 1 );
337 // tests if smaller than first "word"
338 if( usedLen < sizeof( uinteger ) )
339 {
340 uinteger mask= (Bit1 << (usedLen * 8) )- 1;
341 return ( self.Data().GetUInteger(0) & mask )
342 == ( rhs .Data().GetUInteger(0) & mask );
343 }
344
345 // test first word
346 if( self.Data().GetUInteger(0) != rhs.Data().GetUInteger(0) )
347 return false;
348
349 if( usedLen == sizeof( uinteger ) )
350 return true;
351
352 // tests if smaller than second "word"
353 if( usedLen - sizeof( uinteger ) < sizeof( uinteger ) )
354 {
355 uinteger mask= (Bit1 << (usedLen - sizeof(uinteger)) * 8 )- 1;
356 return ( self.Data().GetUInteger(1) & mask )
357 == ( rhs .Data().GetUInteger(1) & mask );
358 }
359
360 return self.Data().GetUInteger(1) == rhs.Data().GetUInteger(1);
361}
362
363
364bool FEquals_double( const Box& self, const Box& rhsBox )
365{
366 double lhs= self.UnboxFloatingPoint();
367 double rhs;
368 if( rhsBox.IsFloatingPoint () ) rhs= rhsBox.UnboxFloatingPoint () ;
369 else if( rhsBox.IsSignedIntegral () ) rhs= static_cast<double>( rhsBox.UnboxSignedIntegral () );
370 else if( rhsBox.IsUnsignedIntegral() ) rhs= static_cast<double>( rhsBox.UnboxUnsignedIntegral() );
371 else return false;
372
373 // we can ignore this warning, because we fixed it with the second test
374 #if defined(__clang__)
375 #pragma clang diagnostic push
376 #pragma clang diagnostic ignored "-Wfloat-equal"
377 #endif
378
379 return lhs == rhs
380 // take rounding errors into account.
381 // We use the "float-epsilon" and double it to be even a little weaker!
382 || std::fabs( lhs - rhs ) <= static_cast<double>( 2.0f * std::numeric_limits<float>::epsilon() );
383
384 #if defined(__clang__)
385 #pragma clang diagnostic pop
386 #endif
387}
388
389bool FEquals_integer( const Box& self, const Box& rhsBox )
390{
391 if( rhsBox.IsFloatingPoint() )
392 return FEquals_double( rhsBox, self );
393
394 integer rhs;
395 if( rhsBox.IsSignedIntegral () ) rhs= rhsBox.UnboxSignedIntegral () ;
396 else if( rhsBox.IsUnsignedIntegral() ) rhs= static_cast< integer>( rhsBox.UnboxUnsignedIntegral() );
397 else return false;
398
399 return self.UnboxSignedIntegral() == rhs;
400}
401
402bool FEquals_uinteger( const Box& self, const Box& rhsBox )
403{
404 if( rhsBox.IsFloatingPoint() )
405 return FEquals_double( rhsBox, self );
406
407 uinteger rhs;
408 if( rhsBox.IsSignedIntegral () ) rhs= static_cast<uinteger>( rhsBox.UnboxSignedIntegral () );
409 else if( rhsBox.IsUnsignedIntegral() ) rhs= rhsBox.UnboxUnsignedIntegral() ;
410 else return false;
411
412 return self.UnboxUnsignedIntegral() == rhs;
413}
414
415bool FEquals_char( const Box& self, const Box& rhs )
416{
417 if( !rhs.IsCharacter() )
418 return false;
419 return self.UnboxCharacter() == rhs.UnboxCharacter();
420}
421
422
423template<typename TChar>
424bool FEquals_TChar_Arr( const Box& lhs, const Box& rhs )
425{
426 if ( !rhs.IsArrayOf<TChar>() )
427 return false;
428
429 const TChar* compBuf= rhs.Data().Pointer<TChar>();
430 const TChar* boxBuf= lhs.Data().Pointer<TChar>();
431 if ( (boxBuf == nullptr) != (compBuf == nullptr) )
432 return false;
433
434 integer compLen= rhs.UnboxLength();
435 integer boxLen= lhs.UnboxLength();
436 if ( boxLen != compLen )
437 return false;
438
439 return 0 == characters::Compare <TChar>( boxBuf, compBuf, boxLen );
440}
441
442// #################################################################################################
443// FIsLess
444// #################################################################################################
445bool FIsLess_Default( const Box& box, const Box& comp )
446{
447 return std::type_index( box.TypeID() ) < std::type_index(comp.TypeID() )
448 || ( box.TypeID() == comp.TypeID()
449 &&box.Data().GetUInteger(0) < comp.Data().GetUInteger(0) );
450
451}
452
453#if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
454bool FIsLess_integer( const Box& self, const Box& rhs )
455{
456 auto lhs= self.Data().GetInteger(0);
457 if( rhs.IsSameType( self ) ) return lhs < rhs.Unbox<integer > () ;
458 if( rhs.IsType<uinteger>() ) return lhs < static_cast<integer> ( rhs.Unbox<uinteger> () );
459 if( rhs.IsFloatingPoint() ) return static_cast<double> ( lhs ) < rhs.UnboxFloatingPoint();
460
461 return std::type_index( self.TypeID() ) < std::type_index( rhs.TypeID() );
462}
463
464bool FIsLess_uinteger( const Box& self, const Box& rhs )
465{
466 auto lhs= self.Data().GetUInteger(0);
467 if( rhs.IsSameType( self ) ) return lhs < rhs.Data().GetUInteger(0) ;
468 if( rhs.IsType<integer> () ) return static_cast<integer> ( lhs ) < rhs.Unbox<integer>();
469 if( rhs.IsFloatingPoint() ) return static_cast<double > ( lhs ) < rhs.UnboxFloatingPoint();
470
471 return std::type_index( self.TypeID() ) < std::type_index( rhs.TypeID() );
472}
473
474#else
475
476bool helperBijectiveLessS( integer selfVal, const Box& selfType, const Box& rhs )
477{
478 if( rhs.IsSignedIntegral () ) return selfVal < rhs.UnboxSignedIntegral () ;
479 if( rhs.IsUnsignedIntegral() ) return selfVal < static_cast< integer>( rhs.UnboxUnsignedIntegral() );
480 if( rhs.IsFloatingPoint () ) return static_cast<double>( selfVal ) < rhs.UnboxFloatingPoint () ;
481
482 // no number?
483 return std::type_index( selfType.TypeID() ) < std::type_index( rhs.TypeID() );
484}
485
486bool helperBijectiveLessU( uinteger selfVal, const Box& selfType, const Box& rhs )
487{
488 if( rhs.IsSignedIntegral () ) return selfVal < static_cast<uinteger>( rhs.UnboxSignedIntegral () );
489 if( rhs.IsUnsignedIntegral() ) return selfVal < rhs.UnboxUnsignedIntegral() ;
490 if( rhs.IsFloatingPoint () ) return static_cast<double>( selfVal ) < rhs.UnboxFloatingPoint () ;
491
492 // no number?
493 return std::type_index( selfType.TypeID() ) < std::type_index( rhs.TypeID() );
494}
495
496bool FIsLess_int8_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessS( static_cast< integer>( self.Unbox< int8_t >() ), self, rhs ); }
497bool FIsLess_int16_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessS( static_cast< integer>( self.Unbox< int16_t >() ), self, rhs ); }
498bool FIsLess_int32_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessS( static_cast< integer>( self.Unbox< int32_t >() ), self, rhs ); }
499bool FIsLess_int64_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessS( static_cast< integer>( self.Unbox< int64_t >() ), self, rhs ); }
500bool FIsLess_intGap_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessS( static_cast< integer>( self.Unbox< intGap_t>() ), self, rhs ); }
501
502bool FIsLess_uint8_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessU( static_cast<uinteger>( self.Unbox<uint8_t >() ), self, rhs ); }
503bool FIsLess_uint16_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessU( static_cast<uinteger>( self.Unbox<uint16_t >() ), self, rhs ); }
504bool FIsLess_uint32_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessU( static_cast<uinteger>( self.Unbox<uint32_t >() ), self, rhs ); }
505bool FIsLess_uint64_t ( const Box& self, const Box& rhs ) { return helperBijectiveLessU( static_cast<uinteger>( self.Unbox<uint64_t >() ), self, rhs ); }
506bool FIsLess_uintGap_t( const Box& self, const Box& rhs ) { return helperBijectiveLessU( static_cast<uinteger>( self.Unbox<uintGap_t>() ), self, rhs ); }
507
508#endif
509
510bool FIsLess_char( const Box& self, const Box& rhs )
511{
512 if( rhs.IsCharacter () )
513 return self.UnboxCharacter() < rhs.UnboxCharacter () ;
514
515 return std::type_index( self.TypeID() ) < std::type_index( rhs.TypeID() );
516}
517
518
519
520bool FIsLess_double( const Box& self, const Box& rhs )
521{
522 double lhs= self.Unbox<double>();
523 if( rhs.IsFloatingPoint () ) return lhs < rhs.UnboxFloatingPoint () ;
524 if( rhs.IsSignedIntegral () ) return lhs < static_cast<double> ( rhs.UnboxSignedIntegral () );
525 if( rhs.IsUnsignedIntegral() ) return lhs < static_cast<double> ( rhs.UnboxUnsignedIntegral() );
526
527 return std::type_index( self.TypeID() ) < std::type_index( rhs.TypeID() );
528}
529
530#if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
531 bool FIsLess_float( const Box& self, const Box& rhs )
532 {
533 float lhs= self.Unbox<float>();
534 if( rhs.IsType<float >() ) return lhs < rhs.Unbox<float >() ;
535 if( rhs.IsType<double >() ) return lhs < static_cast<float> ( rhs.Unbox<double>() );
536 if( rhs.IsSignedIntegral () ) return lhs < static_cast<float> ( rhs.UnboxSignedIntegral () );
537 if( rhs.IsUnsignedIntegral() ) return lhs < static_cast<float> ( rhs.UnboxUnsignedIntegral() );
538
539 return std::type_index( self.TypeID() ) < std::type_index( rhs.TypeID() );
540 }
541#endif
542
543
544
545// #################################################################################################
546// FClone
547// #################################################################################################
548#if ALIB_MONOMEM
549
550void FClone_Default( Box& self, MonoAllocator& memory)
551{
552 if ( !self.IsArray() || self.UnboxLength() == 0)
553 return;
554
555 Placeholder& placeHolder= self.Data();
556 auto* src= placeHolder.Pointer<char>();
557 if( src== nullptr || placeHolder.GetInteger(1) < 0 )
558 return;
559
560 size_t alignment= self.ArrayElementSize();
561 if( alignment > sizeof(std::ptrdiff_t) )
562 alignment= sizeof(std::ptrdiff_t);
563
564
565 placeHolder.VoidPointer( memory().Alloc( self.ArrayElementSize() * placeHolder.GetUInteger(1),
566 alignment ) );
567 memcpy( placeHolder.Pointer<char>(), src, self.ArrayElementSize() * placeHolder.GetUInteger(1) );
568}
569
570#endif
571
572// #################################################################################################
573// FIsTrue
574// #################################################################################################
575bool FIsTrue_Default( const Box& self )
576{
577 if( self.IsArray() )
578 return self.UnboxLength() != 0;
579
580 // non-array types
581 unsigned int usedLen= self.GetPlaceholderUsageLength();
582
583 constexpr uinteger Bit1= static_cast<uinteger>( 1 );
584 // tests if smaller than first "word"
585 if( usedLen < sizeof( uinteger ) )
586 return ( self.Data().GetUInteger(0)
587 & ((Bit1 << (usedLen * 8) )- 1) ) != 0;
588
589 // test first word
590 if( self.Data().GetUInteger(0) != 0 )
591 return true;
592
593 if( usedLen == sizeof( uinteger ) )
594 return false;
595
596 // tests if smaller than second "word"
597 if( usedLen - sizeof( uinteger ) < sizeof( uinteger ) )
598 {
599 return ( self.Data().GetUInteger(1)
600 & ((Bit1 << (usedLen - sizeof(uinteger)) * 8 )- 1) ) != 0;
601 }
602
603 return self.Data().GetUInteger(1) != 0;
604}
605
606
607// #################################################################################################
608// ############################ Strings And Boxing #####################################
609// #################################################################################################
610#if ALIB_STRINGS
611
612template<typename TChar>
613bool FIsLess_TChar_arr( const Box& lhs, const Box& rhs )
614{
615 if( rhs.IsArrayOf<TChar>() )
617
618 return std::type_index( lhs.TypeID() ) < std::type_index(rhs.TypeID() );
619}
620
621
622template<typename TChar, typename TAllocator>
623void FAppend_Default( const Box& self, strings::TAString<TChar,TAllocator>& target)
624{
625 if( self.IsPointer() )
626 {
627 target << ALIB_REL_DBG( "PointerType", self.TypeID() )
629 << typename strings::TFormat<TChar>::Hex( self.Data().Integrals.UInt )
630 << ')';
631 return;
632 }
633
634 if( self.IsEnum() )
635 {
636 target << ALIB_REL_DBG( "EnumType", self.TypeID() ) << '(' << self.Data().Integrals.Int << ')';
637 return;
638 }
639
640 if( self.IsArray() )
641 {
642 target << ALIB_REL_DBG( "ArrayType", self.ElementTypeID() ) << '[' << self.UnboxLength() << ']';
643 return;
644 }
645
646 // value type
647 target << ALIB_REL_DBG( "ValueType", self.TypeID() ) << "(Size: " << self.GetPlaceholderUsageLength() << " bytes)";
648}
649
650
651template<typename TCharSrc, typename TChar, typename TAllocator>
652void FAppend_TcharArr( const Box& box, strings::TAString<TChar,TAllocator>& target )
653{
654 target.template Append<NC>( box.UnboxArray<TCharSrc>(), box.UnboxLength() );
655}
656
657#endif
658
659
660} // anonymous namespace
661
662#endif // !DOXYGEN
663
664
665// #################################################################################################
666// Non-anonymous functions
667// #################################################################################################
668
670{
671 return false;
672}
673
674
675// static member definition
676
677// #################################################################################################
678// Bootstrap()
679// #################################################################################################
681
682#if ALIB_DEBUG && !DOXYGEN
683namespace{ unsigned int initFlag= 0; }
684#endif // !DOXYGEN
685
686#if ALIB_DEBUG && !DOXYGEN
687 // This is used by boxing::Bootstrap to do runtime-check for compatibility of boxing
688 // and long double values.
689 // It was moved to file boxes.cpp to prevent the compiler to optimize and remove the code.
690 extern long double dbgLongDoubleWriteTestMem[2];
691 extern void dbgLongDoubleTrueLengthSet();
692 extern bool dbgLongDoubleTrueLengthTest();
693#endif
694
695#if ALIB_MONOMEM
696 namespace detail {
697 extern void bootStrapCFM(); ///< Bootstrap helper method.
698 }
699#endif
700
702{
703 ALIB_ASSERT_ERROR( initFlag == 0x92A3EF61, "BOXING", "Not initialized when calling shutdown." )
704 ALIB_DBG(initFlag= 1);
706}
707
709{
710 ALIB_ASSERT_ERROR( initFlag == 0, "BOXING", "This method must not be invoked twice." )
711 ALIB_DBG(initFlag= 0x92A3EF61);
712
713 //############### Debug-compilation checks ################
714 #if ALIB_DEBUG
715 // check size of long double
716 {
717 dbgLongDoubleTrueLengthSet();
718 dbgLongDoubleWriteTestMem[0]= 0.0L;
719 ALIB_ASSERT_ERROR( dbgLongDoubleTrueLengthTest(), "BOXING",
720 "Platform not supported. Template specialization T_SizeInPlaceholder<long double> contains wrong size" )
721 }
722 #endif
723
724 //############################# BootstrapRegister Static VTables #################################
729
730DOX_MARKER([DOX_BOXING_OPTIMIZE_REGISTER_1])
732DOX_MARKER([DOX_BOXING_OPTIMIZE_REGISTER_1])
733
734 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
737 #else
746 #if ALIB_SIZEOF_INTEGER == 8
749 #endif
750 #endif // !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
751
752
754 #if ALIB_SIZEOF_LONGDOUBLE_REPORTED <= 2 * ALIB_SIZEOF_INTEGER
756 #endif
757 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
759 #endif
760
761
762 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
764 #else
769 #endif
770
771DOX_MARKER([DOX_BOXING_OPTIMIZE_REGISTER_2])
773DOX_MARKER([DOX_BOXING_OPTIMIZE_REGISTER_2])
774
778
779 // Static VTables for standard types
781
782 // CodeMarker_CommonEnums
783 // Static VTables for low-level ALib types
788 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_ContainerOp )
789 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_CreateDefaults )
790 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_CreateIfNotExists )
791 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_CurrentData )
793 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_Initialization )
795 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_Propagation )
797 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_Responsibility )
805 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_ValueReference )
806 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_Whitespaces )
807
809
810 #if ALIB_STRINGS
811 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_wrapped_tanstring )
812 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_wrapped_tawstring )
813 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_wrapped_taxstring )
814 ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER( vt_alib_strings_token )
815 #endif
816
817 //######################## Register default implementations #######################
818 BootstrapRegisterDefault<FIsTrue >( FIsTrue_Default );
819 BootstrapRegisterDefault<FIsNotNull >( FIsNotNull_Default );
820 BootstrapRegisterDefault<FIsLess >( FIsLess_Default );
821 BootstrapRegisterDefault<FHashcode >( FHashcode_Default );
822 BootstrapRegisterDefault<FEquals >( FEquals_Default );
824 BootstrapRegisterDefault<FClone >( FClone_Default ); )
825
826 // ################################ IsNotNull ##########################################
828 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
831 #else
842 #endif
843
844 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
846 #else
851 #endif
852
853
854 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
856 #endif
858
859 // ################################ Hashcode ##########################################
861 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
864 #else
875 #endif
876
877 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
879 #else
884 #endif
885
886
887 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
889 #endif
893
894
895 // ################################ Equals ###########################################
897
898 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
901 #else
912 #endif
913
914 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
916 #endif
919
920
921 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
923 #else
928 #endif
929
930 BootstrapRegister<FEquals , TMappedToArrayOf<nchar>>( FEquals_TChar_Arr<nchar>);
931 BootstrapRegister<FEquals , TMappedToArrayOf<wchar>>( FEquals_TChar_Arr<wchar>);
932 BootstrapRegister<FEquals , TMappedToArrayOf<xchar>>( FEquals_TChar_Arr<xchar>);
933
934 // ################################ IsLess ###########################################
935 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
938 #else
949 #endif
950
951 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
953 #endif
956
957 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
959 #else
964 #endif
965
966
967 // #############################################################################################
968 // ########################## Strings And Boxing ###################################
969 // #############################################################################################
970#if ALIB_STRINGS
971 // register functions interface implementations
972 BootstrapRegister<FIsLess, TMappedToArrayOf<nchar>>( FIsLess_TChar_arr<nchar> );
973 BootstrapRegister<FIsLess, TMappedToArrayOf<wchar>>( FIsLess_TChar_arr<wchar> );
974 BootstrapRegister<FIsLess, TMappedToArrayOf<xchar>>( FIsLess_TChar_arr<xchar> );
975
976 // register functions of type FAppend
977 BootstrapRegisterDefault<FAppend<character , lang::HeapAllocator>>( FAppend_Default<character , lang::HeapAllocator> );
978 BootstrapRegisterDefault<FAppend<complementChar, lang::HeapAllocator>>( FAppend_Default<complementChar, lang::HeapAllocator> );
979 BootstrapRegisterDefault<FAppend<strangeChar , lang::HeapAllocator>>( FAppend_Default<strangeChar , lang::HeapAllocator> );
980
983
984 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS
987 #else
994 #endif
995
996 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS
1001 #else
1022 #endif
1023
1026 #if ALIB_FEAT_BOXING_BIJECTIVE_FLOATS
1029 #endif
1030 if constexpr (sizeof(long double) <= sizeof(Placeholder) )
1031 {
1034 }
1035 BootstrapRegister<FAppend<nchar, lang::HeapAllocator>, TMappedToArrayOf<nchar >>(FAppend_TcharArr<nchar, nchar, lang::HeapAllocator>);
1036 BootstrapRegister<FAppend<nchar, lang::HeapAllocator>, TMappedToArrayOf<wchar >>(FAppend_TcharArr<wchar, nchar, lang::HeapAllocator>);
1037 BootstrapRegister<FAppend<nchar, lang::HeapAllocator>, TMappedToArrayOf<xchar >>(FAppend_TcharArr<xchar, nchar, lang::HeapAllocator>);
1038 BootstrapRegister<FAppend<wchar, lang::HeapAllocator>, TMappedToArrayOf<nchar >>(FAppend_TcharArr<nchar, wchar, lang::HeapAllocator>);
1039 BootstrapRegister<FAppend<wchar, lang::HeapAllocator>, TMappedToArrayOf<wchar >>(FAppend_TcharArr<wchar, wchar, lang::HeapAllocator>);
1040 BootstrapRegister<FAppend<wchar, lang::HeapAllocator>, TMappedToArrayOf<xchar >>(FAppend_TcharArr<xchar, wchar, lang::HeapAllocator>);
1041 BootstrapRegister<FAppend<xchar, lang::HeapAllocator>, TMappedToArrayOf<nchar >>(FAppend_TcharArr<nchar, xchar, lang::HeapAllocator>);
1042 BootstrapRegister<FAppend<xchar, lang::HeapAllocator>, TMappedToArrayOf<wchar >>(FAppend_TcharArr<wchar, xchar, lang::HeapAllocator>);
1043 BootstrapRegister<FAppend<xchar, lang::HeapAllocator>, TMappedToArrayOf<xchar >>(FAppend_TcharArr<xchar, xchar, lang::HeapAllocator>);
1044
1054
1055 // CodeMarker_CommonEnums
1056 #if ALIB_CAMP
1081 #endif
1082
1084
1085 #if ALIB_DEBUG
1087 #if ALIB_EXT_LIB_THREADS_AVAILABLE
1089 #endif
1091 #endif
1092
1093
1094#endif // ALIB_STRINGS
1095
1096}
1097
1098// Box::dbgCheckRegistration
1099// Note: this method has to go here, to be able to check if boxing was bootstrapped already.
1100// If not, no check is performed.
1101#if ALIB_DEBUG_BOXING
1102
1104{
1105 // ERROR: A global or static instance of class Box is created and initialized to a
1106 // mapped type that uses a dynamic vtable. This is forbidden.
1107 // See chapter "12.4 Global And Static Box Instances" of the Programmer's Manual
1108 // of module ALib Boxing, for more information.
1109 assert( initFlag == 0x92A3EF61 ); // magic number
1110}
1111
1112void detail::DbgCheckRegistration( detail::VTable* vtable, bool increaseUsageCounter )
1113{
1114 if( vtable==nullptr)
1115 return;
1116
1117 if( increaseUsageCounter )
1118 ++vtable->DbgCntUsage;
1119
1120 if( initFlag== 0 || vtable->DbgProduction != detail::VTable::DbgFactoryType::Unregistered )
1121 return;
1122
1123 if( !vtable->IsArray() )
1124 {
1125 NString2K typeName;
1126 lang::DbgTypeDemangler( vtable->Type ).GetShort(typeName);
1127 ALIB_STRINGS_TO_NARROW( typeName, typeNameNarrow, 2048)
1128 ALIB_ERROR( "BOXING", "Static VTable of mapped type <", typeNameNarrow,
1129 "> not registered. Use Macro ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER with bootstrapping." )
1130 }
1131 else
1132 {
1133 NString2K typeName;
1134 lang::DbgTypeDemangler( vtable->ElementType ).GetShort(typeName);
1135 ALIB_STRINGS_TO_NARROW( typeName, typeNameNarrow, 2048)
1136 ALIB_ERROR( "BOXING", "Static VTable of mapped type <", typeNameNarrow,
1137 "[]> not registered. Use Macro ALIB_BOXING_REGISTER_MAPPED_ARRAY_TYPE with bootstrapping." )
1138 }
1139}
1140#endif
1141
1142}} // namespace [alib::boxing]
1144
1146
uinteger UnboxUnsignedIntegral() const
Definition box.inl:627
ALIB_API bool operator<(Box const &rhs) const
Definition boxing.cpp:172
size_t ArrayElementSize() const
Definition box.inl:968
TElementType * UnboxArray() const
Definition box.inl:987
ALIB_API bool IsNotNull() const
Definition boxing.cpp:162
bool IsPointer() const
Definition box.inl:737
wchar UnboxCharacter() const
Definition box.inl:669
integer UnboxLength() const
Definition box.inl:1018
bool IsFloatingPoint() const
Definition boxing.cpp:136
bool IsSameType(const Box &other) const
Definition box.inl:762
bool IsUnsignedIntegral() const
Definition box.inl:593
ALIB_API size_t Hashcode() const
Definition boxing.cpp:163
bool IsSignedIntegral() const
Definition box.inl:575
bool IsType() const
unsigned int GetPlaceholderUsageLength() const
Definition box.inl:879
ALIB_API bool operator<=(Box const &rhs) const
Definition boxing.cpp:173
bool IsEnum() const
Definition box.inl:749
ALIB_API double UnboxFloatingPoint() const
Definition boxing.cpp:148
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
Definition box.inl:1175
const std::type_info & TypeID() const
Definition box.inl:941
const std::type_info & ElementTypeID() const
Definition box.inl:956
bool IsArrayOf() const
Definition box.inl:725
const Placeholder & Data() const
Definition box.inl:844
integer UnboxSignedIntegral() const
Definition box.inl:610
ALIB_API bool operator>(Box const &rhs) const
Definition boxing.cpp:174
ALIB_API bool operator==(Box const &rhs) const
Definition boxing.cpp:171
ALIB_API void Clone(MonoAllocator &memory)
const TUnboxable Unbox() const
bool IsArray() const
Definition box.inl:712
bool IsCharacter() const
Definition box.inl:652
ALIB_API NAString & GetShort(NAString &target)
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
Definition vtable.inl:473
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define ALIB_STRINGS_TO_NARROW( src, dest, bufSize)
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_BOXING_BOOTSTRAP_REGISTER_FAPPEND_FOR_APPENDABLE_TYPE(TAppendable)
#define ALIB_BOXING_BOOTSTRAP_VTABLE_DBG_REGISTER(Identifier)
Definition vtable.inl:489
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
#define ALIB_DBG(...)
Definition alib.hpp:390
#define IF_ALIB_MONOMEM(...)
Definition alib.hpp:312
#define ALIB_REL_DBG(releaseCode,...)
Definition alib.hpp:392
void bootStrapCFM()
Bootstrap helper method.
ALIB_API void DbgCheckRegistration(detail::VTable *vtable, bool increaseUsageCounter)
Definition boxing.cpp:1112
ALIB_API void DbgCheckIsInitialized()
Definition boxing.cpp:1103
void Bootstrap()
Definition boxing.cpp:708
void BootstrapRegister(typename TFDecl::Signature function)
Definition boxing.hpp:112
void BootstrapRegisterDefault(typename TFDecl::Signature function)
Definition boxing.hpp:148
void Shutdown()
Definition boxing.cpp:701
int Compare(const TChar *lhs, const TChar *rhs, integer cmpLength)
Recursive
Denotes whether recursion is performed/allowed or not.
Inclusion
Denotes how members of a set something should be taken into account.
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
Whitespaces
Denotes whether a string is trimmed or not.
CreateDefaults
Denotes whether default entities should be created or not.
Caching
Denotes if a cache mechanism is enabled or disabled.
Side
Denotes if something is left or right.
Propagation
Denotes whether a e.g a setting should be propagated.
Switch
Denotes if sth. is switched on or off.
Initialization
Used for example with constructors that allow to suppress initialization of members.
Safeness
Denotes whether something should be performed in a safe or unsafe fashion.
SortOrder
Denotes sort order.
Reach
Denotes the reach of something.
SourceData
Denotes if the source data should be moved or copied.
Timezone
Denotes whether a time value represents local time or UTC.
Case
Denotes upper and lower case character treatment.
Alignment
Denotes Alignments.
Timing
Denotes if asynchronous tasks become synchronized.
CreateIfNotExists
Denotes whether something should be created if it does not exist.
Phase
Denotes a phase, e.g.,of a transaction.
ContainerOp
Denotes standard container operations.
Definition alib.cpp:69
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:276
characters::wchar wchar
Type alias in namespace alib.
characters::xchar xchar
Type alias in namespace alib.
lang::intGap_t intGap_t
Type alias in namespace alib.
Definition integers.hpp:279
lang::uintGap_t uintGap_t
Type alias in namespace alib.
Definition integers.hpp:282
characters::nchar nchar
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
static bool ComparableTypes(const Box &self, const Box &rhs)
static size_t UsePlaceholderBytes(const Box &self)
static ALIB_API bool ConstantTrue(const Box &)
Definition boxing.cpp:669
static ALIB_API void Shutdown()
Needs to be called only in debug versions to shut down internal hashtables cleanly.
Definition vtable.cpp:115
DbgFactoryType DbgProduction
Debug information.
Definition vtable.inl:226
const std::type_info & Type
Definition vtable.inl:193
const std::type_info & ElementType
Definition vtable.inl:197
TCString< TChar > HexLiteralPrefix
constexpr TReturn * Pointer() const
ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE constexpr integer GetInteger(int idx) const
detail::UnionIntegrals Integrals
Collection of integrals of different sizes.
constexpr uinteger GetUInteger(int idx) const
detail::UnionPointers Pointers
Collection of void, char and character pointers.
constexpr void * VoidPointer() const
integer Int
Signed integral of platform-dependent size.
uinteger UInt
Unsigned integral of platform-dependent size.
const void * CVoid
A constant void pointer.