Change to the traits representation of enum and bitfield properties.

develop
Alexander Gavrilov 2012-03-15 20:46:08 +04:00
parent e5efbc5895
commit f84b1539a8
8 changed files with 91 additions and 47 deletions

@ -169,7 +169,7 @@ std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_ite
std::string res; std::string res;
const char *data = (const char*)p; const char *data = (const char*)p;
for (int i = 0; i < size*8; i++) { for (int i = 0; i < size; i++) {
unsigned v; unsigned v;
if (items[i].size > 1) { if (items[i].size > 1) {
@ -199,12 +199,22 @@ std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_ite
return res; return res;
} }
int DFHack::findBitfieldField(const std::string &name, int size, const bitfield_item_info *items) int DFHack::findBitfieldField_(const std::string &name, int size, const bitfield_item_info *items)
{ {
for (int i = 0; i < size*8; i++) { for (int i = 0; i < size; i++) {
if (items[i].name && items[i].name == name) if (items[i].name && items[i].name == name)
return i; return i;
} }
return -1; return -1;
} }
int DFHack::findEnumItem_(const std::string &name, int size, const char *const *items)
{
for (int i = 0; i < size; i++) {
if (items[i] && items[i] == name)
return i;
}
return -1;
}

@ -45,7 +45,7 @@ namespace DFHack
return sourceTileType; return sourceTileType;
#ifdef assert #ifdef assert
assert(tiletype::is_valid(sourceTileType)); assert(is_valid_enum_item(sourceTileType));
#endif #endif
// Special case for smooth pillars. // Special case for smooth pillars.

@ -125,13 +125,6 @@ namespace DFHack
template<class T> template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; } T *ifnull(T *a, T *b) { return a ? a : b; }
// Enums
template<class T, T start, bool (*isvalid)(T)>
inline T next_enum_item_(T v) {
v = T(int(v) + 1);
return isvalid(v) ? v : start;
}
template<class T> template<class T>
struct enum_list_attr { struct enum_list_attr {
size_t size; size_t size;
@ -143,19 +136,6 @@ namespace DFHack
const char *name; const char *name;
int size; int size;
}; };
DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items);
DFHACK_EXPORT int findBitfieldField(const std::string &name, int size, const bitfield_item_info *items);
template<class T>
inline int findBitfieldField(const T &val, const std::string &name) {
return findBitfieldField(name, sizeof(val.whole), val.get_items());
}
template<class T>
inline std::string bitfieldToString(const T &val) {
return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items());
}
} }
template<class T> template<class T>
@ -183,6 +163,12 @@ namespace df
using DFHack::BitArray; using DFHack::BitArray;
using DFHack::DfArray; using DFHack::DfArray;
template<class T>
struct enum_traits {};
template<class T>
struct bitfield_traits {};
template<class T> template<class T>
class class_virtual_identity : public virtual_identity { class class_virtual_identity : public virtual_identity {
public: public:
@ -227,14 +213,70 @@ namespace df
namespace enums {} namespace enums {}
} }
#define ENUM_ATTR(enum,attr,val) (df::enums::enum::get_##attr(val)) namespace DFHack {
// Enums
template<class T>
inline typename df::enum_traits<T>::enum_type next_enum_item(T v) {
typedef df::enum_traits<T> traits;
typedef typename traits::base_type base_type;
base_type iv = base_type(v);
return (iv < traits::last_item_value) ? T(iv+1) : traits::first_item;
}
template<class T>
inline bool is_valid_enum_item(T v) {
return df::enum_traits<T>::is_valid(v);
}
template<class T>
inline const char *enum_item_raw_key(T val) {
typedef df::enum_traits<T> traits;
return traits::is_valid(val) ? traits::key_table[val - traits::first_item_value] : NULL;
}
template<class T>
inline const char *enum_item_key_str(T val) {
return ifnull(enum_item_raw_key(val), "?");
}
DFHACK_EXPORT int findEnumItem_(const std::string &name, int size, const char *const *items);
template<class T>
inline bool find_enum_item(T *var, const std::string &name) {
typedef df::enum_traits<T> traits;
int size = traits::last_item_value-traits::first_item_value+1;
int idx = findEnumItem_(name, size, traits::key_table);
if (idx < 0) return false;
*var = T(traits::first_item_value+idx);
return true;
}
DFHACK_EXPORT int findBitfieldField_(const std::string &name, int size, const bitfield_item_info *items);
template<class T>
inline int findBitfieldField(const std::string &name) {
typedef df::bitfield_traits<T> traits;
return findBitfieldField_(name, traits::bit_count, traits::bits);
}
DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items);
template<class T>
inline std::string bitfieldToString(const T &val) {
typedef df::bitfield_traits<T> traits;
return bitfieldToString(&val.whole, traits::bit_count, traits::bits);
}
}
#define ENUM_ATTR(enum,attr,val) (df::enum_traits<df::enum>::attrs(val).attr)
#define ENUM_ATTR_STR(enum,attr,val) DFHack::ifnull(ENUM_ATTR(enum,attr,val),"?") #define ENUM_ATTR_STR(enum,attr,val) DFHack::ifnull(ENUM_ATTR(enum,attr,val),"?")
#define ENUM_KEY_STR(enum,val) ENUM_ATTR_STR(enum,key,val) #define ENUM_KEY_STR(enum,val) (DFHack::enum_item_key_str<df::enum>(val))
#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum) #define ENUM_FIRST_ITEM(enum) (df::enum_traits<df::enum>::first_item)
#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum) #define ENUM_LAST_ITEM(enum) (df::enum_traits<df::enum>::last_item)
#define ENUM_NEXT_ITEM(enum,val) \ #define ENUM_NEXT_ITEM(enum,val) \
(DFHack::next_enum_item_<df::enum,ENUM_FIRST_ITEM(enum),df::enums::enum::is_valid>(val)) (DFHack::next_enum_item<df::enum>(val))
#define FOR_ENUM_ITEMS(enum,iter) \ #define FOR_ENUM_ITEMS(enum,iter) \
for(df::enum iter = ENUM_FIRST_ITEM(enum); iter <= ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter))) for(df::enum iter = ENUM_FIRST_ITEM(enum); iter <= ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter)))

@ -167,16 +167,8 @@ bool ItemTypeInfo::find(const std::string &token)
if (items[0] == "NONE") if (items[0] == "NONE")
return true; return true;
FOR_ENUM_ITEMS(item_type, i) if (!find_enum_item(&type, items[0]))
{ return false;
const char *key = ENUM_ATTR(item_type, key, i);
if (key && key == items[0])
{
type = i;
break;
}
}
if (type == NONE) if (type == NONE)
return false; return false;
if (items.size() == 1) if (items.size() == 1)

@ -505,7 +505,7 @@ bool DFHack::parseJobMaterialCategory(df::job_material_category *cat, const std:
for (size_t i = 0; i < items.size(); i++) for (size_t i = 0; i < items.size(); i++)
{ {
int id = findBitfieldField(*cat, items[i]); int id = findBitfieldField<df::job_material_category>(items[i]);
if (id < 0) if (id < 0)
return false; return false;
@ -524,7 +524,7 @@ bool DFHack::parseJobMaterialCategory(df::dfhack_material_category *cat, const s
for (size_t i = 0; i < items.size(); i++) for (size_t i = 0; i < items.size(); i++)
{ {
int id = findBitfieldField(*cat, items[i]); int id = findBitfieldField<df::dfhack_material_category>(items[i]);
if (id < 0) if (id < 0)
return false; return false;

@ -1 +1 @@
Subproject commit 136181f067a0a5ed19a19c9f98eece41003fe372 Subproject commit 78e998e3daa4a78b11b50c347beac2a9543b16dc

@ -297,7 +297,7 @@ static command_result embark_prospector(color_ostream &out, df::viewscreen_choos
int sums[ENUM_LAST_ITEM(inclusion_type)+1] = { 0 }; int sums[ENUM_LAST_ITEM(inclusion_type)+1] = { 0 };
for (unsigned j = 0; j < layer->vein_mat.size(); j++) for (unsigned j = 0; j < layer->vein_mat.size(); j++)
if (inclusion_type::is_valid(layer->vein_type[j])) if (is_valid_enum_item<df::inclusion_type>(layer->vein_type[j]))
sums[layer->vein_type[j]] += layer->vein_unk_38[j]; sums[layer->vein_type[j]] += layer->vein_unk_38[j];
for (unsigned j = 0; j < layer->vein_mat.size(); j++) for (unsigned j = 0; j < layer->vein_mat.size(); j++)

@ -233,7 +233,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
if (option == "shape" || option == "sh" || option == "s") if (option == "shape" || option == "sh" || option == "s")
{ {
if (tiletype_shape::is_valid((df::tiletype_shape)valInt)) if (is_valid_enum_item((df::tiletype_shape)valInt))
{ {
paint.shape = (df::tiletype_shape)valInt; paint.shape = (df::tiletype_shape)valInt;
found = true; found = true;
@ -258,7 +258,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
} }
else if (option == "material" || option == "mat" || option == "m") else if (option == "material" || option == "mat" || option == "m")
{ {
if (tiletype_material::is_valid((df::tiletype_material)valInt)) if (is_valid_enum_item((df::tiletype_material)valInt))
{ {
paint.material = (df::tiletype_material)valInt; paint.material = (df::tiletype_material)valInt;
found = true; found = true;
@ -283,7 +283,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
} }
else if (option == "special" || option == "sp") else if (option == "special" || option == "sp")
{ {
if (tiletype_special::is_valid((df::tiletype_special)valInt)) if (is_valid_enum_item((df::tiletype_special)valInt))
{ {
paint.special = (df::tiletype_special)valInt; paint.special = (df::tiletype_special)valInt;
found = true; found = true;
@ -308,7 +308,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
} }
else if (option == "variant" || option == "var" || option == "v") else if (option == "variant" || option == "var" || option == "v")
{ {
if (tiletype_variant::is_valid((df::tiletype_variant)valInt)) if (is_valid_enum_item((df::tiletype_variant)valInt))
{ {
paint.variant = (df::tiletype_variant)valInt; paint.variant = (df::tiletype_variant)valInt;
found = true; found = true;