Skip to content

Commit

Permalink
Change to the traits representation of enum and bitfield properties.
Browse files Browse the repository at this point in the history
  • Loading branch information
angavrilov committed Mar 15, 2012
1 parent e5efbc5 commit f84b153
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 47 deletions.
16 changes: 13 additions & 3 deletions library/DataDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_ite
std::string res;
const char *data = (const char*)p;

for (int i = 0; i < size*8; i++) {
for (int i = 0; i < size; i++) {
unsigned v;

if (items[i].size > 1) {
Expand Down Expand Up @@ -199,12 +199,22 @@ std::string DFHack::bitfieldToString(const void *p, int size, const bitfield_ite
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)
return i;
}

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;
}
2 changes: 1 addition & 1 deletion library/TileTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace DFHack
return sourceTileType;

#ifdef assert
assert(tiletype::is_valid(sourceTileType));
assert(is_valid_enum_item(sourceTileType));
#endif

// Special case for smooth pillars.
Expand Down
92 changes: 67 additions & 25 deletions library/include/DataDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,6 @@ namespace DFHack
template<class T>
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>
struct enum_list_attr {
size_t size;
Expand All @@ -143,19 +136,6 @@ namespace DFHack
const char *name;
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>
Expand Down Expand Up @@ -183,6 +163,12 @@ namespace df
using DFHack::BitArray;
using DFHack::DfArray;

template<class T>
struct enum_traits {};

template<class T>
struct bitfield_traits {};

template<class T>
class class_virtual_identity : public virtual_identity {
public:
Expand Down Expand Up @@ -227,14 +213,70 @@ namespace df
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_KEY_STR(enum,val) ENUM_ATTR_STR(enum,key,val)
#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum)
#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum)
#define ENUM_KEY_STR(enum,val) (DFHack::enum_item_key_str<df::enum>(val))
#define ENUM_FIRST_ITEM(enum) (df::enum_traits<df::enum>::first_item)
#define ENUM_LAST_ITEM(enum) (df::enum_traits<df::enum>::last_item)

#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) \
for(df::enum iter = ENUM_FIRST_ITEM(enum); iter <= ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter)))

Expand Down
12 changes: 2 additions & 10 deletions library/modules/Items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,8 @@ bool ItemTypeInfo::find(const std::string &token)
if (items[0] == "NONE")
return true;

FOR_ENUM_ITEMS(item_type, i)
{
const char *key = ENUM_ATTR(item_type, key, i);
if (key && key == items[0])
{
type = i;
break;
}
}

if (!find_enum_item(&type, items[0]))
return false;
if (type == NONE)
return false;
if (items.size() == 1)
Expand Down
4 changes: 2 additions & 2 deletions library/modules/Materials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ bool DFHack::parseJobMaterialCategory(df::job_material_category *cat, const std:

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)
return false;

Expand All @@ -524,7 +524,7 @@ bool DFHack::parseJobMaterialCategory(df::dfhack_material_category *cat, const s

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)
return false;

Expand Down
2 changes: 1 addition & 1 deletion library/xml
Submodule xml updated from 136181 to 78e998
2 changes: 1 addition & 1 deletion plugins/prospector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ static command_result embark_prospector(color_ostream &out, df::viewscreen_choos
int sums[ENUM_LAST_ITEM(inclusion_type)+1] = { 0 };

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];

for (unsigned j = 0; j < layer->vein_mat.size(); j++)
Expand Down
8 changes: 4 additions & 4 deletions plugins/tiletypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri

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;
found = true;
Expand All @@ -258,7 +258,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
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;
found = true;
Expand All @@ -283,7 +283,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
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;
found = true;
Expand All @@ -308,7 +308,7 @@ bool processTileType(TileType &paint, const std::string &option, const std::stri
}
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;
found = true;
Expand Down

0 comments on commit f84b153

Please sign in to comment.