From 915b78b5e1bf836834e3ef5adcd5e3be166fab0c Mon Sep 17 00:00:00 2001 From: Kp Date: Wed, 13 Aug 2014 02:44:59 +0000 Subject: [PATCH] Add vvalptridx_t for always-valid valptridx values --- common/include/valptridx.h | 78 ++++++++++++++++++++++++++++++++++++-- common/main/object.h | 8 ++-- similar/main/gamesave.cpp | 2 +- similar/main/object.cpp | 24 +++--------- 4 files changed, 85 insertions(+), 27 deletions(-) diff --git a/common/include/valptridx.h b/common/include/valptridx.h index 7a49b2d56..c36a0ec37 100644 --- a/common/include/valptridx.h +++ b/common/include/valptridx.h @@ -103,7 +103,7 @@ protected: static index_type check_index_range(const A &a, index_type s) __attribute_warn_unused_result; pointer_type p; index_type i; - static decltype(get_global_array(pointer_type())) get_array() + static constexpr decltype(get_global_array(pointer_type())) get_array() { return get_global_array(pointer_type()); } @@ -124,19 +124,85 @@ typename valptridx_t::index_type valptridx_t(s) < a.size(), "invalid index used in array subscript", s, index_range_exception); } +template class magic_constant> +class vvalptridx_t : public valptridx_t +{ + typedef valptridx_t base_t; +protected: + using base_t::get_array; + using base_t::check_index_range; + using base_t::index_range_exception; +public: + typedef typename base_t::pointer_type pointer_type; + typedef typename base_t::index_type index_type; + template + static constexpr const magic_constant &check_constant_index(const magic_constant &m) + { + return DXX_VALPTRIDX_CHECK(static_cast(v) < get_array().size(), "invalid index used", m, index_range_exception); + } + vvalptridx_t() = delete; + template + vvalptridx_t(A &a, pointer_type t, index_type s) : + base_t(a, t, s) + { + } + template + vvalptridx_t(const magic_constant &m) : + base_t(check_constant_index(m)) + { + } + vvalptridx_t(const vvalptridx_t::type, I, magic_constant> &t) : + base_t(t) + { + } + vvalptridx_t(pointer_type p) : + base_t(p) + { + } + vvalptridx_t(const base_t &t) : + base_t(get_array(), t, t) + { + } + template + vvalptridx_t(A &a, index_type s) : + base_t(check_index_range(a, s)) + { + } + vvalptridx_t(index_type s) : + base_t(check_index_range(get_array(), s)) + { + } + using base_t::operator==; + template + bool operator==(const magic_constant &m) const + { + return base_t::operator==(check_constant_index(m)); + } + template + bool operator!=(const R &rhs) const + { + return !(*this == rhs); + } +}; + #define _DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N,P,I,A,name,Pconst) \ - static inline decltype(A) Pconst &get_global_array(P Pconst*) { return A; } \ + static inline constexpr decltype(A) Pconst &get_global_array(P Pconst*) { return A; } \ \ struct name : valptridx_t

{ \ name() = delete; \ DXX_INHERIT_CONSTRUCTORS(name, valptridx_t

); \ }; \ \ - static inline name N(name::pointer_type o, name::index_type i) { \ + struct v##name : vvalptridx_t

{ \ + v##name() = delete; \ + DXX_INHERIT_CONSTRUCTORS(v##name, vvalptridx_t

); \ + }; \ + \ + static inline v##name N(name::pointer_type o, name::index_type i) { \ return {A, o, i}; \ } \ \ - static inline name operator-(P Pconst *o, decltype(A) &O) \ + static inline v##name operator-(P Pconst *o, decltype(A) &O) \ { \ return N(o, const_cast(o) - &(const_cast(O).front())); \ } \ @@ -146,4 +212,8 @@ typename valptridx_t::index_type valptridx_tsegnum == segment_none); - Assert(segnum>=0 && segnum<=Highest_segment_index); - obj->segnum = segnum; obj->next = Segments[segnum].objects; @@ -919,12 +915,9 @@ void obj_link(objptridx_t obj,segnum_t segnum) Objects[0].prev = object_none; } -void obj_unlink(objptridx_t obj) +void obj_unlink(vobjptridx_t obj) { segment *seg = &Segments[obj->segnum]; - - Assert(obj != object_none); - if (obj->prev == object_none) seg->objects = obj->next; else @@ -1242,9 +1235,8 @@ objptridx_t obj_create_copy(objnum_t objnum, vms_vector *new_pos, segnum_t newse #endif //remove object from the world -void obj_delete(objptridx_t obj) +void obj_delete(vobjptridx_t obj) { - Assert(obj != object_none); Assert(obj->type != OBJ_NONE); Assert(obj != ConsoleObject); @@ -1589,16 +1581,12 @@ void obj_delete_all_that_should_be_dead() //when an object has moved into a new segment, this function unlinks it //from its old segment, and links it into the new segment -void obj_relink(objptridx_t objnum,segnum_t newsegnum) +void obj_relink(vobjptridx_t objnum,segnum_t newsegnum) { - Assert((objnum >= 0) && (objnum <= Highest_object_index)); Assert((newsegnum <= Highest_segment_index) && (newsegnum >= 0)); - obj_unlink(objnum); - obj_link(objnum,newsegnum); - } // for getting out of messed up linking situations (i.e. caused by demo playback) @@ -2095,7 +2083,7 @@ void obj_attach(objptridx_t parent,objptridx_t sub) } //dettaches one object -void obj_detach_one(objptridx_t sub) +void obj_detach_one(vobjptridx_t sub) { Assert(sub->flags & OF_ATTACHED); Assert(sub->ctype.expl_info.attach_parent != object_none);