2#ifndef __ASE_CXXAUX_HH__ 
    3#define __ASE_CXXAUX_HH__ 
    5#include <ase/sysconfig.h> 
   19static_assert (
sizeof (
uint) == 4, 
"");
 
   32static_assert (
sizeof (
int8)  == 1 && 
sizeof (
int16)  == 2 && 
sizeof (
int32)  == 4 && 
sizeof (
int64)  == 8, 
"");
 
   33static_assert (
sizeof (
int) == 4 && 
sizeof (
uint) == 4 && 
sizeof (
unichar) == 4, 
"");
 
   41#define ASE_CPP_STRINGIFY(s)    ASE_CPP_STRINGIFY_ (s)                   
   42#define ASE_CPP_STRINGIFY_(s)   #s                                       
   43#define ASE_CPP_PASTE2_(a,b)    a ## b                                   
   44#define ASE_CPP_PASTE2(a,b)     ASE_CPP_PASTE2_ (a,b)                    
   45#define ASE_ISLIKELY(expr)      __builtin_expect (bool (expr), 1)        
   46#define ASE_UNLIKELY(expr)      __builtin_expect (bool (expr), 0)        
   47#define ASE_ABS(a)              ((a) < 0 ? -(a) : (a))                   
   48#define ASE_MIN(a,b)            ((a) <= (b) ? (a) : (b))                 
   49#define ASE_MAX(a,b)            ((a) >= (b) ? (a) : (b))                 
   50#define ASE_CLAMP(v,mi,ma)      ((v) < (mi) ? (mi) : ((v) > (ma) ? (ma) : (v)))  
   51#define ASE_ARRAY_SIZE(array)   (sizeof (array) / sizeof ((array)[0]))           
   52#define ASE_ALIGN(size, base)   ((base) * ((size_t (size) + (base) - 1) / (base)))  
   53#define ASE_ALIGNMENT16(pointer) (0xf & ptrdiff_t (pointer)) 
   54#define ASE_ALIGNED16(pointer)   (!ALIGNMENT16 (pointer)) 
   57#define ASE_ALWAYS_INLINE       __attribute__ ((always_inline)) 
   58#define ASE_COLD                __attribute__ ((__cold__)) 
   59#define ASE_CONST               __attribute__ ((__const__)) 
   60#define ASE_CONSTRUCTOR         __attribute__ ((constructor,used))       
   61#define ASE_DEPRECATED          __attribute__ ((__deprecated__)) 
   62#define ASE_FORMAT(fx)          __attribute__ ((__format_arg__ (fx))) 
   63#define ASE_HOT                 __attribute__ ((__hot__)) 
   64#define ASE_MALLOC              __attribute__ ((__malloc__)) 
   65#define ASE_MAY_ALIAS           __attribute__ ((may_alias)) 
   66#define ASE_NOINLINE            __attribute__ ((noinline)) 
   67#define ASE_NORETURN            __attribute__ ((__noreturn__)) 
   68#define ASE_NO_INSTRUMENT       __attribute__ ((__no_instrument_function__)) 
   69#define ASE_PRINTF(fx, ax)      __attribute__ ((__format__ (__printf__, fx, ax))) 
   70#define ASE_PURE                __attribute__ ((__pure__)) 
   71#define ASE_SCANF(fx, ax)       __attribute__ ((__format__ (__scanf__, fx, ax))) 
   72#define ASE_SENTINEL            __attribute__ ((__sentinel__)) 
   73#define ASE_UNUSED              __attribute__ ((__unused__)) 
   74#define ASE_USE_RESULT          __attribute__ ((warn_unused_result)) 
   75#define ASE_USED                __attribute__ ((__used__)) 
   76#define ASE_WEAK                __attribute__ ((__weak__)) 
   79#define ASE_RETURN_UNLESS(cond, ...)      do { if (ASE_UNLIKELY (!bool (cond))) return __VA_ARGS__; } while (0) 
   82#define ASE_ASSERT_RETURN(expr, ...)     do { if (expr) [[likely]] break; ::Ase::assertion_failed (#expr); return __VA_ARGS__; } while (0) 
   85#define ASE_ASSERT_RETURN_UNREACHED(...) do { ::Ase::assertion_failed (nullptr); return __VA_ARGS__; } while (0) 
   88#define ASE_ASSERT_UNREACHED(...)        do { ::Ase::assertion_fatal (nullptr); } while (0) 
   91#define ASE_ASSERT(expr)                 do { if (expr) [[likely]] break; ::Ase::assertion_fatal (#expr); } while (0) 
   94#define ASE_ASSERT_WARN(expr)            do { if (expr) [[likely]] break; ::Ase::assertion_failed (#expr); } while (0) 
   97#define ASE_ASSERT_PARANOID(expr)        do { if (expr) [[likely]] break; ::Ase::assertion_failed (#expr); } while (0) 
  100#define ASE_DIE(msg)                    do { errno = 0; ::Ase::perror_die (msg); } while (0) 
  103#define ASE_PERROR_DIE(msg)             do { ::Ase::perror_die (msg); } while (0) 
  106#define ASE_CLASS_NON_COPYABLE(ClassName)  \ 
  107   ClassName  (const ClassName&) = delete; \ 
  108  ClassName&    operator=  (const ClassName&) = delete 
 
  111#define ASE_STRUCT_DECLS(Klass)                                  \ 
  113  using ASE_CPP_PASTE2 (Klass, P) = ::std::shared_ptr<Klass>;   \ 
  114  using ASE_CPP_PASTE2 (Klass, S) = ::std::vector<Klass>; 
  117#define ASE_CLASS_DECLS(Klass)                                  \ 
  119  using ASE_CPP_PASTE2 (Klass, W) = ::std::weak_ptr<Klass>;     \ 
  120  using ASE_CPP_PASTE2 (Klass, P) = ::std::shared_ptr<Klass>;   \ 
  121  using ASE_CPP_PASTE2 (Klass, S) = ::std::vector<ASE_CPP_PASTE2 (Klass, P)>; 
  124#define ASE_DEFINE_ENUM_EQUALITY(Enum)         \ 
  125  constexpr bool    operator== (Enum v, int64_t n) { return int64_t (v) == n; } \ 
  126  constexpr bool    operator== (int64_t n, Enum v) { return n == int64_t (v); } \ 
  127  constexpr bool    operator!= (Enum v, int64_t n) { return int64_t (v) != n; } \ 
  128  constexpr bool    operator!= (int64_t n, Enum v) { return n != int64_t (v); } 
  129#define ASE_DEFINE_FLAGS_ARITHMETIC(Enum)      \ 
  130  constexpr int64_t operator>> (Enum v, int64_t n) { return int64_t (v) >> n; } \ 
  131  constexpr int64_t operator<< (Enum v, int64_t n) { return int64_t (v) << n; } \ 
  132  constexpr int64_t operator^  (Enum v, int64_t n) { return int64_t (v) ^ n; } \ 
  133  constexpr int64_t operator^  (int64_t n, Enum v) { return n ^ int64_t (v); } \ 
  134  constexpr Enum    operator^  (Enum v, Enum w)    { return Enum (int64_t (v) ^ w); } \ 
  135  constexpr int64_t operator|  (Enum v, int64_t n) { return int64_t (v) | n; } \ 
  136  constexpr int64_t operator|  (int64_t n, Enum v) { return n | int64_t (v); } \ 
  137  constexpr Enum    operator|  (Enum v, Enum w)    { return Enum (int64_t (v) | w); } \ 
  138  constexpr int64_t operator&  (Enum v, int64_t n) { return int64_t (v) & n; } \ 
  139  constexpr int64_t operator&  (int64_t n, Enum v) { return n & int64_t (v); } \ 
  140  constexpr Enum    operator&  (Enum v, Enum w)    { return Enum (int64_t (v) & w); } \ 
  141  constexpr int64_t operator~  (Enum v)            { return ~int64_t (v); } \ 
  142  constexpr int64_t operator+  (Enum v)            { return +int64_t (v); } \ 
  143  constexpr int64_t operator-  (Enum v)            { return -int64_t (v); } \ 
  144  constexpr int64_t operator+  (Enum v, int64_t n) { return int64_t (v) + n; } \ 
  145  constexpr int64_t operator+  (int64_t n, Enum v) { return n + int64_t (v); } \ 
  146  constexpr int64_t operator-  (Enum v, int64_t n) { return int64_t (v) - n; } \ 
  147  constexpr int64_t operator-  (int64_t n, Enum v) { return n - int64_t (v); } \ 
  148  constexpr int64_t operator*  (Enum v, int64_t n) { return int64_t (v) * n; } \ 
  149  constexpr int64_t operator*  (int64_t n, Enum v) { return n * int64_t (v); } \ 
  150  constexpr int64_t operator/  (Enum v, int64_t n) { return int64_t (v) / n; } \ 
  151  constexpr int64_t operator/  (int64_t n, Enum v) { return n / int64_t (v); } \ 
  152  constexpr int64_t operator%  (Enum v, int64_t n) { return int64_t (v) % n; } \ 
  153  constexpr int64_t operator%  (int64_t n, Enum v) { return n % int64_t (v); } \ 
  154  constexpr Enum&   operator^= (Enum &e, int64_t n) { e = Enum (e ^ n); return e; } \ 
  155  constexpr Enum&   operator|= (Enum &e, int64_t n) { e = Enum (e | n); return e; } \ 
  156  constexpr Enum&   operator&= (Enum &e, int64_t n) { e = Enum (e & n); return e; } \ 
  157  constexpr Enum&   operator+= (Enum &e, int64_t n) { e = Enum (e + n); return e; } \ 
  158  constexpr Enum&   operator-= (Enum &e, int64_t n) { e = Enum (e - n); return e; } \ 
  159  constexpr Enum&   operator*= (Enum &e, int64_t n) { e = Enum (e * n); return e; } \ 
  160  constexpr Enum&   operator/= (Enum &e, int64_t n) { e = Enum (e / n); return e; } \ 
  161  constexpr Enum&   operator%= (Enum &e, int64_t n) { e = Enum (e % n); return e; } \ 
  162  ASE_DEFINE_ENUM_EQUALITY (Enum) 
  165template<
typename UInt> 
static inline constexpr UInt
 
  166rotr (UInt bits, uint32_t offset)
 
  168  const uint32_t wrapped_bits = 
sizeof (bits) * 8 - offset;
 
  169  return (bits >> offset) | (bits << wrapped_bits);
 
  173template<
typename UInt> 
static inline constexpr UInt
 
  174rotl (UInt bits, uint32_t offset)
 
  176  const uint32_t wrapped_bits = 
sizeof (bits) * 8 - offset;
 
  177  return (bits << offset) | (bits >> wrapped_bits);
 
  181template<
typename T> 
static inline constexpr T
 
  182divmod (T dividend, T divisor, T *reminderp)
 
  184  *reminderp = dividend % divisor; 
 
  185  return dividend / divisor;       
 
  192template<
class T> ASE_PURE 
static inline const char*
 
  199template<
class T> ASE_PURE 
static inline const char*
 
  206template<
typename T> 
static T*
 
  209  asm (
"" : 
"+r" (ptr));        
 
  222void assertion_failed (
const char *msg = 
nullptr, 
const char *file = __builtin_FILE(),
 
  223                       int line = __builtin_LINE(), 
const char *func = __builtin_FUNCTION()) noexcept;
 
  224void assertion_fatal  (const 
char *msg = 
nullptr, const 
char *file = __builtin_FILE(),
 
  225                       int line = __builtin_LINE(), const 
char *func = __builtin_FUNCTION()) noexcept ASE_NORETURN;
 
  232extern inline constexpr 
bool 
  235  return n == 0 || (a[0] == b[0] && (a[0] == 0 || 
constexpr_equals (a + 1, b + 1, n - 1)));
 
 
  239template<
class Type, 
class ...Ts> __attribute__ ((always_inline)) 
inline void 
  240new_inplace (Type &typemem, Ts &&... args)
 
  246template<
class Type> __attribute__ ((always_inline)) 
inline void 
  247delete_inplace (Type &typemem)
 
  253template<
class T> 
void 
  260template<
bool value> 
using REQUIRES = typename ::std::enable_if<value, bool>::type;
 
  263template<
bool value> 
using REQUIRESv = typename ::std::enable_if<value, void>::type;
 
  269#define ASE_DEFINE_MAKE_SHARED(CLASS)                                   \ 
  270  struct MakeSharedAllocator_ : std::allocator<CLASS> {                 \ 
  271    template<typename ...Args>                                          \ 
  272    static void construct (CLASS *p, Args &&...args)                    \ 
  273    { ::new (p) CLASS (std::forward<Args> (args)...); }                 \ 
  274    static void destroy (CLASS *p)                                      \ 
  276    template<typename U> struct rebind {                                \ 
  278        std::conditional_t<std::is_same<U, CLASS>::value,               \ 
  279                           MakeSharedAllocator_, std::allocator<U>>;    \ 
  282  template<typename ...Args> static std::shared_ptr<CLASS>              \ 
  283  make_shared (Args &&...args)                                          \ 
  285    return std::allocate_shared<CLASS> (MakeSharedAllocator_(),         \ 
  286                                        std::forward<Args> (args)...);  \ 
 
  311  typedef decltype (
object->shared_from_this()) ObjectP;
 
  315      sptr = 
object->shared_from_this();
 
  320    sptr = 
object->shared_from_this();
 
 
  328  return shared_ptr_cast<Target> (
const_cast<Source*
> (
object));
 
 
  348  return shared_ptr_cast<Source> (
object);
 
 
  356  if (__builtin_expect (!!cptr, 
true))
 
 
  377  Class *ptr_ = 
nullptr;
 
  379  initialize() ASE_NOINLINE
 
  384      ptr_ = 
new (mem_) Class(); 
 
  390  explicit  operator bool () const ASE_PURE  { 
return ptr_ != 
nullptr; }
 
 
  410  operator    uint32_t   () 
const noexcept              { 
return id; }
 
  411  bool        operator== (
int64_t i) 
const noexcept     { 
return id == i; }
 
  412  bool        operator!= (
int64_t i) 
const noexcept     { 
return id != i; }
 
  413  friend bool operator== (
int64_t i, 
const Id32 &
id)    { 
return id.operator== (i); }
 
  414  friend bool operator!= (
int64_t i, 
const Id32 &
id)    { 
return id.operator!= (i); }
 
 
constexpr Persistent() noexcept
A constexpr constructor avoids the static initialization order fiasco.
 
Class * operator->() __attribute__((__pure__))
Retrieve pointer to Class instance, always returns the same pointer.
 
Class & operator*() __attribute__((__pure__))
Retrieve reference to Class instance, always returns the same reference.
 
#define ASE_UNLIKELY(expr)
Compiler hint to optimize for expr evaluating to false.
 
The Anklang C++ API namespace.
 
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
 
void call_delete(T *o)
Simple way to create a standalone callback to delete an object of type T.
 
void assertion_failed(const char *msg, const char *file, int line, const char *func) noexcept
Print instructive message, handle "breakpoint", "backtrace" and "fatal-warnings" in $ASE_DEBUG.
 
int32_t int32
A 32-bit signed integer.
 
int16_t int16
A 16-bit signed integer.
 
uint8_t uint8
An 8-bit unsigned integer.
 
int8_t int8
An 8-bit signed integer.
 
int64_t int64
A 64-bit unsigned integer, use PRI*64 in format strings.
 
std::shared_ptr< C > weak_ptr_fetch_or_create(std::weak_ptr< C > &wptr, const std::function< std::shared_ptr< C >()> &ctor)
Fetch shared_ptr from wptr and create C with ctor if needed.
 
typename ::std::enable_if< value, bool >::type REQUIRES
REQUIRES<value> - Simplified version of std::enable_if<cond,bool>::type to use SFINAE in function tem...
 
void assertion_fatal(const char *msg, const char *file, int line, const char *func) noexcept
Print a debug message via assertion_failed() and abort the program.
 
void perror_die(const std::string &msg) noexcept
Issue a warning about an assertion error.
 
typename ::std::enable_if< value, void >::type REQUIRESv
REQUIRESv<value> - Simplified version of std::enable_if<cond,void>::type to use SFINAE in struct temp...
 
constexpr bool constexpr_equals(const char *a, const char *b, size_t n)
Test string equality at compile time.
 
std::shared_ptr< typename std::remove_pointer< Source >::type > shared_ptr_from(Source *object)
Use shared_ptr_cast<>() to convert an object pointer into a shared_ptr<>.
 
uint32_t unichar
A 32-bit unsigned integer used for Unicode characters.
 
const char * string_demangle_cxx(const char *mangled_identifier) noexcept
Demangle identifier via libcc.
 
std::string backtrace_command()
Find GDB and construct command line.
 
bool assertion_failed_fatal
Global flag to force aborting on assertion warnings.
 
uint16_t uint16
A 16-bit unsigned integer.
 
uint32_t uint32
A 32-bit unsigned integer.
 
std::shared_ptr< typename std::remove_pointer< Target >::type > shared_ptr_cast(Source *object)
 
uint32_t uint
Provide 'uint' as convenience type.
 
Helper class for integer IDs up to 32 Bit, possibly of enum type.
 
Common base type to allow casting between polymorphic classes.