Add vvalptridx_t for always-valid valptridx values

This commit is contained in:
Kp 2014-08-13 02:44:59 +00:00
parent 125d9257be
commit 915b78b5e1
4 changed files with 85 additions and 27 deletions

View file

@ -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<T, I, magic_constant>::index_type valptridx_t<T, I, magic_c
return DXX_VALPTRIDX_CHECK(static_cast<std::size_t>(s) < a.size(), "invalid index used in array subscript", s, index_range_exception);
}
template <typename T, typename I, template <I> class magic_constant>
class vvalptridx_t : public valptridx_t<T, I, magic_constant>
{
typedef valptridx_t<T, I, magic_constant> 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 <index_type v>
static constexpr const magic_constant<v> &check_constant_index(const magic_constant<v> &m)
{
return DXX_VALPTRIDX_CHECK(static_cast<std::size_t>(v) < get_array().size(), "invalid index used", m, index_range_exception);
}
vvalptridx_t() = delete;
template <typename A>
vvalptridx_t(A &a, pointer_type t, index_type s) :
base_t(a, t, s)
{
}
template <index_type v>
vvalptridx_t(const magic_constant<v> &m) :
base_t(check_constant_index(m))
{
}
vvalptridx_t(const vvalptridx_t<typename tt::remove_const<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 <typename A>
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 <index_type v>
bool operator==(const magic_constant<v> &m) const
{
return base_t::operator==(check_constant_index(m));
}
template <typename R>
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<P Pconst, I, P##_magic_constant_t> { \
name() = delete; \
DXX_INHERIT_CONSTRUCTORS(name, valptridx_t<P Pconst, I, P##_magic_constant_t>); \
}; \
\
static inline name N(name::pointer_type o, name::index_type i) { \
struct v##name : vvalptridx_t<P Pconst, I, P##_magic_constant_t> { \
v##name() = delete; \
DXX_INHERIT_CONSTRUCTORS(v##name, vvalptridx_t<P Pconst, I, P##_magic_constant_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<const P *>(o) - &(const_cast<const decltype(A) &>(O).front())); \
} \
@ -146,4 +212,8 @@ typename valptridx_t<T, I, magic_constant>::index_type valptridx_t<T, I, magic_c
#define DEFINE_VALPTRIDX_SUBTYPE(N,P,I,A) \
_DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N,P,I,A,N##_t,); \
_DEFINE_VALPTRIDX_SUBTYPE_USERTYPE(N,P,I,A,c##N##_t,const); \
\
static inline v##N##_t N(N##_t::index_type i) { \
return {A, i}; \
} \

View file

@ -653,17 +653,17 @@ int obj_get_new_seg(object *obj);
// 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);
// for getting out of messed up linking situations (i.e. caused by demo playback)
void obj_relink_all(void);
// links an object into a segment's list of objects.
// takes object number and segment number
void obj_link(objptridx_t objnum,segnum_t segnum);
void obj_link(vobjptridx_t objnum,segnum_t segnum);
// unlinks an object from a segment's list of objects
void obj_unlink(objptridx_t objnum);
void obj_unlink(vobjptridx_t objnum);
// initialize a new object. adds to the list for the given segment
// returns the object number
@ -675,7 +675,7 @@ objptridx_t obj_create(enum object_type_t type, ubyte id, segnum_t segnum, const
objptridx_t obj_create_copy(objnum_t objnum, vms_vector *new_pos, segnum_t newsegnum);
// remove object from the world
void obj_delete(objptridx_t objnum);
void obj_delete(vobjptridx_t objnum);
// called after load. Takes number of objects, and objects should be
// compressed

View file

@ -1023,7 +1023,7 @@ static int load_game_data(PHYSFS_file *LoadFile)
}
else {
Objects[i].segnum = segment_none; //avoid Assert()
obj_link(objptridx(&Objects[i],i),objsegnum);
obj_link(objptridx(i),objsegnum);
}
}
}

View file

@ -86,7 +86,7 @@ using std::min;
using std::max;
static void obj_detach_all(object *parent);
static void obj_detach_one(objptridx_t sub);
static void obj_detach_one(vobjptridx_t sub);
/*
* Global variables
@ -890,14 +890,10 @@ void special_reset_objects(void)
}
//link the object into the list for its segment
void obj_link(objptridx_t obj,segnum_t segnum)
void obj_link(vobjptridx_t obj,segnum_t segnum)
{
Assert(obj != object_none);
Assert(obj->segnum == 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);