Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
  3.  * It is copyright by its individual contributors, as recorded in the
  4.  * project's Git history.  See COPYING.txt at the top level for license
  5.  * terms and a link to the Git history.
  6.  */
  7. #pragma once
  8.  
  9. #include <functional>
  10. #include <cstddef>
  11. #include "dxxsconf.h"
  12. #include "cpp-valptridx.h"
  13.  
  14. #if defined(DXX_HAVE_CXX_BUILTIN_FILE_LINE)
  15. #define DXX_VALPTRIDX_ENABLE_REPORT_FILENAME
  16. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DECL_VARS  const char *filename = __builtin_FILE(), const unsigned lineno = __builtin_LINE()
  17. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_DECL_VARS  , DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DECL_VARS
  18. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS  const char *const filename, const unsigned lineno
  19. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS  DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS,
  20. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_ filename, lineno
  21. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_VOID_VARS()        static_cast<void>(filename), static_cast<void>(lineno)
  22. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_PASS_VARS  , DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_
  23. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS  DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_,
  24. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VA(...)       DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_, ## __VA_ARGS__
  25. #define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS     "rm" (filename), "rm" (lineno)
  26. #define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS     DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS,
  27. #else
  28. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DECL_VARS
  29. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_DECL_VARS
  30. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS
  31. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS
  32. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_VOID_VARS()        static_cast<void>(0)
  33. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_PASS_VARS
  34. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS
  35. #define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VA(...)       __VA_ARGS__
  36. #define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS
  37. #define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS
  38. #endif
  39.  
  40. template <typename managed_type>
  41. class valptridx :
  42.         protected valptridx_specialized_types<managed_type>::type
  43. {
  44.         using specialized_types = typename valptridx_specialized_types<managed_type>::type;
  45.         using specialized_types::array_size;
  46.         class partial_policy
  47.         {
  48.         public:
  49.                 class require_valid;
  50.                 class allow_invalid;
  51.                 template <template <typename> class policy>
  52.                         class apply_cv_policy;
  53.         };
  54.         class vc;       /* require_valid + const_policy */
  55.         class ic;       /* allow_invalid + const_policy */
  56.         class vm;       /* require_valid + mutable_policy */
  57.         class im;       /* allow_invalid + mutable_policy */
  58.         template <typename>
  59.                 class guarded;
  60.         class array_base_count_type;
  61.         using array_base_storage_type = std::array<managed_type, array_size>;
  62. protected:
  63.         using const_pointer_type = const managed_type *;
  64.         using const_reference_type = const managed_type &;
  65.         using mutable_pointer_type = managed_type *;
  66.         /* integral_type must be a primitive integer type capable of holding
  67.          * all legal values used with managed_type.  Legal values are valid
  68.          * indexes in array_managed_type and any magic out-of-range values.
  69.          */
  70.         using typename specialized_types::integral_type;
  71.         using index_type = integral_type;       // deprecated; should be dedicated UDT
  72.  
  73. public:
  74.         class array_managed_type;
  75.         using typename specialized_types::report_error_uses_exception;
  76.         /* ptridx<policy> publicly inherits from idx<policy> and
  77.          * ptr<policy>, but should not be implicitly sliced to one of the
  78.          * base types.  To prevent slicing, define
  79.          * DXX_VALPTRIDX_ENFORCE_STRICT_PI_SEPARATION to a non-zero value.
  80.          * When enabled, slicing prevention makes *ptr and *idx derive from
  81.          * ptr<policy> / idx<policy>.  When disabled, *ptr and *idx are
  82.          * typedef aliases for ptr<policy> / idx<policy>.
  83.          */
  84.         template <typename policy>
  85.                 class idx;
  86.         template <typename policy>
  87.                 class ptr;
  88.         template <typename policy>
  89.                 class ptridx;
  90. protected:
  91.         template <typename Pc, typename Pm>
  92.                 class basic_ival_member_factory;
  93.         template <typename Pc, typename Pm>
  94.                 class basic_vval_member_factory;
  95.         using typename specialized_types::allow_end_construction;
  96.         using typename specialized_types::assume_nothrow_index;
  97.  
  98.         template <typename handle_index_mismatch>
  99.         static inline void check_index_match(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, index_type, const array_managed_type &);
  100.         template <
  101.                 typename handle_index_range_error,
  102.                 template <typename> class Compare = std::less
  103.                 >
  104.         static inline index_type check_index_range(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS index_type, const array_managed_type *);
  105.         template <typename handle_index_mismatch, typename handle_index_range_error>
  106.         static inline void check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, std::size_t, const array_managed_type &);
  107.         template <typename handle_index_mismatch, typename handle_index_range_error>
  108.         static inline void check_implicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, const array_managed_type &);
  109.         template <typename handle_null_pointer>
  110.         static inline void check_null_pointer_conversion(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type);
  111.         template <typename handle_null_pointer>
  112.         static inline void check_null_pointer(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type, const array_managed_type &);
  113.  
  114. #define DXX_VALPTRIDX_FOR_EACH_VC_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX)    \
  115.         VERB(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, m);        \
  116.         VERB(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, c)
  117.  
  118. #define DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX)      \
  119.         DXX_VALPTRIDX_FOR_EACH_VC_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, i);  \
  120.         DXX_VALPTRIDX_FOR_EACH_VC_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, v)
  121.  
  122. #define DXX_VALPTRIDX_FOR_EACH_IDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)       \
  123.         DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, idx)
  124.  
  125. #define DXX_VALPTRIDX_FOR_EACH_PTR_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)       \
  126.         DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, ptr)
  127.  
  128. #define DXX_VALPTRIDX_FOR_EACH_PTRIDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)    \
  129.         DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, ptridx)
  130.  
  131. #define DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)       \
  132.         DXX_VALPTRIDX_FOR_EACH_PTR_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT);      \
  133.         DXX_VALPTRIDX_FOR_EACH_PTRIDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)
  134.  
  135. #define DXX_VALPTRIDX_FOR_EACH_IPPI_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)      \
  136.         DXX_VALPTRIDX_FOR_EACH_IDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT);      \
  137.         DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)
  138.  
  139.         class index_mismatch_exception;
  140.         class index_range_exception;
  141.         class null_pointer_exception;
  142. public:
  143.         /* This is a special placeholder that allows segiter to bypass the
  144.          * normal rules.  The calling code is responsible for providing the
  145.          * safety that is bypassed.  Use this bypass only if you understand
  146.          * exactly what you are skipping and why your use is safe despite
  147.          * the lack of checking.
  148.          */
  149.         using typename specialized_types::allow_none_construction;
  150.         using typename specialized_types::rebind_policy;
  151.         typedef ptridx<ic>      icptridx;
  152.         typedef ptridx<im>      imptridx;
  153.         typedef ptridx<vc>      vcptridx;
  154.         typedef ptridx<vm>      vmptridx;
  155.  
  156. #define DXX_VALPTRIDX_DECLARE_PI_TYPE(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX) \
  157.         using IVPREFIX ## MCPREFIX ## PISUFFIX = typename specialized_types::template wrapper< PISUFFIX < IVPREFIX ## MCPREFIX > >
  158.         DXX_VALPTRIDX_FOR_EACH_IDX_TYPE(DXX_VALPTRIDX_DECLARE_PI_TYPE,,,);
  159.         DXX_VALPTRIDX_FOR_EACH_PTR_TYPE(DXX_VALPTRIDX_DECLARE_PI_TYPE,,,);
  160. #undef DXX_VALPTRIDX_DEFINE_PI_TYPE
  161.  
  162. #define DXX_VALPTRIDX_MC_qualifier_m
  163. #define DXX_VALPTRIDX_MC_qualifier_c    const
  164. #define DXX_VALPTRIDX_DECLARE_MEMBER_FACTORIES(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX)        \
  165.         using f ## IVPREFIX ## MCPREFIX ## PISUFFIX =   \
  166.         DXX_VALPTRIDX_MC_qualifier_ ## MCPREFIX \
  167.         basic_ ## IVPREFIX ## val_member_factory<       \
  168.                 IVPREFIX ## c ## PISUFFIX,      \
  169.                 IVPREFIX ## m ## PISUFFIX       \
  170.         >
  171.         DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(DXX_VALPTRIDX_DECLARE_MEMBER_FACTORIES,,,);
  172. #undef DXX_VALPTRIDX_DECLARE_MEMBER_FACTORIES
  173. #undef DXX_VALPTRIDX_MC_qualifier_c
  174. #undef DXX_VALPTRIDX_MC_qualifier_m
  175.  
  176.         /* Commit a DRY violation here so that tools can easily find these
  177.          * types.  Strict DRY compliance would mean using a macro to
  178.          * generate the `using` line, since the typedef, the dispatcher type
  179.          * it references, and an argument to that type are all dependent on
  180.          * the same string.
  181.          */
  182.         template <typename T>
  183.                 using index_mismatch_error_type = typename specialized_types::template dispatch_index_mismatch_error<T, index_mismatch_exception>;
  184.         template <typename T>
  185.                 using index_range_error_type = typename specialized_types::template dispatch_index_range_error<T, index_range_exception>;
  186.         template <typename T>
  187.                 using null_pointer_error_type = typename specialized_types::template dispatch_null_pointer_error<T, null_pointer_exception>;
  188.  
  189.         template <integral_type constant>
  190.                 class magic_constant
  191.                 {
  192.                 public:
  193.                         constexpr operator integral_type() const { return constant; }   // integral_type conversion deprecated
  194.                 };
  195. };
  196.  
  197. #define DXX_VALPTRIDX_DEFINE_FACTORY_TYPEDEF(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX)  \
  198.         using f ## IVPREFIX ## MCPREFIX ## DERIVED_TYPE_PREFIX ## PISUFFIX = valptridx<MANAGED_TYPE>::f ## IVPREFIX ## MCPREFIX ## PISUFFIX
  199.  
  200. #define DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEF(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX)  \
  201.         using IVPREFIX ## MCPREFIX ## DERIVED_TYPE_PREFIX ## PISUFFIX ## _t = valptridx<MANAGED_TYPE>::IVPREFIX ## MCPREFIX ## PISUFFIX
  202.  
  203. #define DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEFS(MANAGED_TYPE, DERIVED_TYPE_PREFIX)        \
  204.         using MANAGED_TYPE ## _array = valptridx<MANAGED_TYPE>::array_managed_type;     \
  205.         DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(DXX_VALPTRIDX_DEFINE_FACTORY_TYPEDEF, MANAGED_TYPE, DERIVED_TYPE_PREFIX,);      \
  206.         DXX_VALPTRIDX_FOR_EACH_IPPI_TYPE(DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEF, MANAGED_TYPE, DERIVED_TYPE_PREFIX,)
  207.