diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index 77b159205..2396e03fd 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -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) { @@ -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; +} diff --git a/library/TileTypes.cpp b/library/TileTypes.cpp index 660114d3f..fa5d99555 100644 --- a/library/TileTypes.cpp +++ b/library/TileTypes.cpp @@ -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. diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 78c59f51d..b4623f791 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -125,13 +125,6 @@ namespace DFHack template T *ifnull(T *a, T *b) { return a ? a : b; } - // Enums - template - inline T next_enum_item_(T v) { - v = T(int(v) + 1); - return isvalid(v) ? v : start; - } - template struct enum_list_attr { size_t size; @@ -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 - inline int findBitfieldField(const T &val, const std::string &name) { - return findBitfieldField(name, sizeof(val.whole), val.get_items()); - } - - template - inline std::string bitfieldToString(const T &val) { - return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items()); - } } template @@ -183,6 +163,12 @@ namespace df using DFHack::BitArray; using DFHack::DfArray; + template + struct enum_traits {}; + + template + struct bitfield_traits {}; + template class class_virtual_identity : public virtual_identity { public: @@ -227,14 +213,70 @@ namespace df namespace enums {} } -#define ENUM_ATTR(enum,attr,val) (df::enums::enum::get_##attr(val)) +namespace DFHack { + // Enums + template + inline typename df::enum_traits::enum_type next_enum_item(T v) { + typedef df::enum_traits 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 + inline bool is_valid_enum_item(T v) { + return df::enum_traits::is_valid(v); + } + + template + inline const char *enum_item_raw_key(T val) { + typedef df::enum_traits traits; + return traits::is_valid(val) ? traits::key_table[val - traits::first_item_value] : NULL; + } + + template + 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 + inline bool find_enum_item(T *var, const std::string &name) { + typedef df::enum_traits 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 + inline int findBitfieldField(const std::string &name) { + typedef df::bitfield_traits 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 + inline std::string bitfieldToString(const T &val) { + typedef df::bitfield_traits traits; + return bitfieldToString(&val.whole, traits::bit_count, traits::bits); + } +} + + +#define ENUM_ATTR(enum,attr,val) (df::enum_traits::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(val)) +#define ENUM_FIRST_ITEM(enum) (df::enum_traits::first_item) +#define ENUM_LAST_ITEM(enum) (df::enum_traits::last_item) #define ENUM_NEXT_ITEM(enum,val) \ - (DFHack::next_enum_item_(val)) + (DFHack::next_enum_item(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))) diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index be83c3c49..7a2f5c71f 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -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) diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 433b0b405..68aadc3d6 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -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(items[i]); if (id < 0) 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++) { - int id = findBitfieldField(*cat, items[i]); + int id = findBitfieldField(items[i]); if (id < 0) return false; diff --git a/library/xml b/library/xml index 136181f06..78e998e3d 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 136181f067a0a5ed19a19c9f98eece41003fe372 +Subproject commit 78e998e3daa4a78b11b50c347beac2a9543b16dc diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 4d89aaae7..179fe666f 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -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(layer->vein_type[j])) sums[layer->vein_type[j]] += layer->vein_unk_38[j]; for (unsigned j = 0; j < layer->vein_mat.size(); j++) diff --git a/plugins/tiletypes.cpp b/plugins/tiletypes.cpp index 8825d8114..d704f030a 100644 --- a/plugins/tiletypes.cpp +++ b/plugins/tiletypes.cpp @@ -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; @@ -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; @@ -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; @@ -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;