text: /*
   * Copyright 2014-2016, Intel Corporation
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   *     * Redistributions of source code must retain the above copyright
   *       notice, this list of conditions and the following disclaimer.
   *
   *     * Redistributions in binary form must reproduce the above copyright
   *       notice, this list of conditions and the following disclaimer in
   *       the documentation and/or other materials provided with the
   *       distribution.
   *
   *     * Neither the name of the copyright holder nor the names of its
   *       contributors may be used to endorse or promote products derived
   *       from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  /*
   * libpmemobj/types.h -- definitions of libpmemobj type-safe macros
   */
  
  #ifndef LIBPMEMOBJ_TYPES_H
  #define LIBPMEMOBJ_TYPES_H 1
  
  #include <libpmemobj/base.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #define TOID_NULL(t)	((TOID(t))OID_NULL)
  #define PMEMOBJ_MAX_LAYOUT ((size_t)1024)
  
  /*
   * similar to offsetof, except that it takes a structure pointer,
   * instead of a structure type name
   */
  #define offsetofp(s, m) ((size_t)&(((s)0)->m))
  
  /*
   * Type safety macros
   */
  #ifndef _MSC_VER
  
  #define TOID_ASSIGN(o, value)(\
  {\
  	(o).oid = value;\
  	(o); /* to avoid "error: statement with no effect" */\
  })
  
  #else /* _MSC_VER */
  
  #define TOID_ASSIGN(o, value) ((o).oid = value, (o))
  
  #endif /* _MSC_VER */
  
  #define TOID_EQUALS(lhs, rhs)\
  ((lhs).oid.off == (rhs).oid.off &&\
  	(lhs).oid.pool_uuid_lo == (rhs).oid.pool_uuid_lo)
  
  /* type number of root object */
  #define POBJ_ROOT_TYPE_NUM 0
  #define _toid_struct
  #define _toid_union
  #define _toid_enum
  #define _POBJ_LAYOUT_REF(name) (sizeof(_pobj_layout_##name##_ref))
  
  /*
   * Typed OID
   */
  #define TOID(t)\
  union _toid_##t##_toid
  
  #ifdef __cplusplus
  #define _TOID_CONSTR(t)\
  _toid_##t##_toid()\
  { }\
  _toid_##t##_toid(PMEMoid _oid) : oid(_oid)\
  { }
  #else
  #define _TOID_CONSTR(t)
  #endif
  
  /*
   * Declaration of typed OID
   */
  #define _TOID_DECLARE(t, i)\
  typedef uint8_t _toid_##t##_toid_type_num[(i) + 1];\
  TOID(t)\
  {\
  	_TOID_CONSTR(t)\
  	PMEMoid oid;\
  	t *_type;\
  	_toid_##t##_toid_type_num *_type_num;\
  }
  
  /*
   * Declaration of typed OID of an object
   */
  #define TOID_DECLARE(t, i) _TOID_DECLARE(t, i)
  
  /*
   * Declaration of typed OID of a root object
   */
  #define TOID_DECLARE_ROOT(t) _TOID_DECLARE(t, POBJ_ROOT_TYPE_NUM)
  
  /*
   * Type number of specified type
   */
  #define TOID_TYPE_NUM(t) (sizeof(_toid_##t##_toid_type_num) - 1)
  
  /*
   * Type number of object read from typed OID
   */
  #define TOID_TYPE_NUM_OF(o) (sizeof(*(o)._type_num) - 1)
  
  /*
   * NULL check
   */
  #define TOID_IS_NULL(o)	((o).oid.off == 0)
  
  /*
   * Validates whether type number stored in typed OID is the same
   * as type number stored in object's metadata
   */
  #define TOID_VALID(o) (TOID_TYPE_NUM_OF(o) == pmemobj_type_num((o).oid))
  
  /*
   * Checks whether the object is of a given type
   */
  #define OID_INSTANCEOF(o, t) (TOID_TYPE_NUM(t) == pmemobj_type_num(o))
  
  /*
   * Begin of layout declaration
   */
  #define POBJ_LAYOUT_BEGIN(name)\
  typedef uint8_t _pobj_layout_##name##_ref[__COUNTER__ + 1]
  
  /*
   * End of layout declaration
   */
  #define POBJ_LAYOUT_END(name)\
  typedef char _pobj_layout_##name##_cnt[__COUNTER__ + 1 -\
  _POBJ_LAYOUT_REF(name)];
  
  /*
   * Number of types declared inside layout without the root object
   */
  #define POBJ_LAYOUT_TYPES_NUM(name) (sizeof(_pobj_layout_##name##_cnt) - 1)
  
  /*
   * Declaration of typed OID inside layout declaration
   */
  #define POBJ_LAYOUT_TOID(name, t)\
  TOID_DECLARE(t, (__COUNTER__ + 1 - _POBJ_LAYOUT_REF(name)));
  
  /*
   * Declaration of typed OID of root inside layout declaration
   */
  #define POBJ_LAYOUT_ROOT(name, t)\
  TOID_DECLARE_ROOT(t);
  
  /*
   * Name of declared layout
   */
  #define POBJ_LAYOUT_NAME(name) #name
  
  #define TOID_TYPEOF(o) __typeof__(*(o)._type)
  
  #define TOID_OFFSETOF(o, field) offsetofp(__typeof__((o)._type), field)
  
  /*
   * XXX - DIRECT_RW and DIRECT_RO are not available when compiled using VC++
   *       as C code (/TC).  Use /TP option.
   */
  #ifndef _MSC_VER
  
  #define DIRECT_RW(o) (\
  {__typeof__(o) _o; _o._type = NULL; (void)_o;\
  (__typeof__(*(o)._type) *)pmemobj_direct((o).oid); })
  #define DIRECT_RO(o) ((const __typeof__(*(o)._type) *)pmemobj_direct((o).oid))
  
  #elif defined(__cplusplus)
  
  /*
   * XXX - On Windows, these macros do not behave exactly the same as on Linux.
   */
  #define DIRECT_RW(o) \
  	(reinterpret_cast < __typeof__((o)._type) > (pmemobj_direct((o).oid)))
  #define DIRECT_RO(o) \
  	(reinterpret_cast < const __typeof__((o)._type) > \
  	(pmemobj_direct((o).oid)))
  
  #endif /* (defined(_MSC_VER) || defined(__cplusplus)) */
  
  #define D_RW	DIRECT_RW
  #define D_RO	DIRECT_RO
  
  #ifdef __cplusplus
  }
  #endif
  #endif	/* libpmemobj/types.h */
  