From 2f81c3a6960f22c6c772a1795005d49dca595a78 Mon Sep 17 00:00:00 2001 From: myk002 Date: Mon, 31 Oct 2022 10:57:04 -0700 Subject: [PATCH] use preprocessor foreach to reduce boilerplate --- library/include/MiscUtils.h | 59 ++++++++++++ plugins/overlay.cpp | 183 +++++------------------------------- 2 files changed, 82 insertions(+), 160 deletions(-) diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 56506f7bd..768d23dd4 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -429,3 +429,62 @@ DFHACK_EXPORT std::string UTF2DF(const std::string &in); DFHACK_EXPORT std::string DF2UTF(const std::string &in); DFHACK_EXPORT std::string DF2CONSOLE(const std::string &in); DFHACK_EXPORT std::string DF2CONSOLE(DFHack::color_ostream &out, const std::string &in); + +// MAP macro for implementing preprocessor foreach +// from https://github.com/swansontec/map-macro/blob/master/map.h +// MAP_JOIN was added as a generalization of the existing MAP_LIST +/* + * Created by William Swanson in 2012. + * + * I, William Swanson, dedicate this work to the public domain. + * I waive all rights to the work worldwide under copyright law, + * including all related and neighboring rights, + * to the extent allowed by law. + * + * You can copy, modify, distribute and perform the work, + * even for commercial purposes, all without asking permission. + */ + +#define EVAL0(...) __VA_ARGS__ +#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__))) +#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) +#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) +#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) +#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) + +#define MAP_END(...) +#define MAP_OUT +#define MAP_COMMA , + +#define MAP_GET_END2() 0, MAP_END +#define MAP_GET_END1(...) MAP_GET_END2 +#define MAP_GET_END(...) MAP_GET_END1 +#define MAP_NEXT0(test, next, ...) next MAP_OUT +#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0) +#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next) + +#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__) +#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__) + +#define MAP_JOIN_NEXT1(sep, test, next) MAP_NEXT0(test, sep next, 0) +#define MAP_JOIN_NEXT(sep, test, next) MAP_JOIN_NEXT1(sep, MAP_GET_END test, next) + +#define MAP_JOIN0(f, sep, x, peek, ...) f(x) MAP_JOIN_NEXT(sep, peek, MAP_JOIN1)(f, sep, peek, __VA_ARGS__) +#define MAP_JOIN1(f, sep, x, peek, ...) f(x) MAP_JOIN_NEXT(sep, peek, MAP_JOIN0)(f, sep, peek, __VA_ARGS__) + +/** + * Applies the function macro `f` to each of the remaining parameters. + */ +#define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +/** + * Applies the function macro `f` to each of the remaining parameters and + * inserts the given separator between the results. + */ +#define MAP_JOIN(f, sep, ...) EVAL(MAP_JOIN1(f, sep, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +/** + * Applies the function macro `f` to each of the remaining parameters and + * inserts commas between the results. + */ +#define MAP_LIST(f, ...) MAP_JOIN(f, MAP_COMMA, __VA_ARGS__) diff --git a/plugins/overlay.cpp b/plugins/overlay.cpp index 3af3bf0b5..1da693b04 100644 --- a/plugins/overlay.cpp +++ b/plugins/overlay.cpp @@ -85,6 +85,7 @@ #include "Debug.h" #include "LuaTools.h" +#include "MiscUtils.h" #include "PluginManager.h" #include "VTableInterpose.h" @@ -98,6 +99,26 @@ namespace DFHack { DBG_DECLARE(overlay, event, DebugCategory::LINFO); } +#define SCREEN_LIST adopt_region, adventure_log, announcelist, \ + assign_display_item, barter, buildinglist, building, choose_start_site, \ + civlist, counterintelligence, createquota, customize_unit, dungeonmode, \ + dungeon_monsterstatus, dungeon_wrestle, dwarfmode, entity, \ + export_graphical_map, export_region, game_cleaner, image_creator, item, \ + joblist, jobmanagement, job, justice, kitchenpref, layer_arena_creature, \ + layer_assigntrade, layer_choose_language_name, layer_currency, \ + layer_export_play_map, layer_military, layer_musicsound, layer_noblelist, \ + layer_overall_health, layer_reaction, layer_squad_schedule, \ + layer_stockpile, layer_stone_restriction, layer_unit_action, \ + layer_unit_health, layer_unit_relationship, layer_world_gen_param_preset, \ + layer_world_gen_param, legends, loadgame, locations, meeting, movieplayer, \ + new_region, noble, option, overallstatus, petitions, pet, price, \ + reportlist, requestagreement, savegame, selectitem, setupadventure, \ + setupdwarfgame, stores, textviewer, title, \ + topicmeeting_fill_land_holder_positions, topicmeeting, \ + topicmeeting_takerequests, tradeagreement, tradegoods, tradelist, \ + treasurelist, unitlist, unit, update_region, wages, workquota_condition, \ + workquota_details, workshop_profile + template struct viewscreen_overlay : T { typedef T interpose_base; @@ -124,86 +145,7 @@ struct viewscreen_overlay : T { template<> IMPLEMENT_VMETHOD_INTERPOSE_PRIO(screen##_overlay, feed, 100); \ template<> IMPLEMENT_VMETHOD_INTERPOSE_PRIO(screen##_overlay, render, 100); -IMPLEMENT_HOOKS(adopt_region) -IMPLEMENT_HOOKS(adventure_log) -IMPLEMENT_HOOKS(announcelist) -IMPLEMENT_HOOKS(assign_display_item) -IMPLEMENT_HOOKS(barter) -IMPLEMENT_HOOKS(buildinglist) -IMPLEMENT_HOOKS(building) -IMPLEMENT_HOOKS(choose_start_site) -IMPLEMENT_HOOKS(civlist) -IMPLEMENT_HOOKS(counterintelligence) -IMPLEMENT_HOOKS(createquota) -IMPLEMENT_HOOKS(customize_unit) -IMPLEMENT_HOOKS(dungeonmode) -IMPLEMENT_HOOKS(dungeon_monsterstatus) -IMPLEMENT_HOOKS(dungeon_wrestle) -IMPLEMENT_HOOKS(dwarfmode) -IMPLEMENT_HOOKS(entity) -IMPLEMENT_HOOKS(export_graphical_map) -IMPLEMENT_HOOKS(export_region) -IMPLEMENT_HOOKS(game_cleaner) -IMPLEMENT_HOOKS(image_creator) -IMPLEMENT_HOOKS(item) -IMPLEMENT_HOOKS(joblist) -IMPLEMENT_HOOKS(jobmanagement) -IMPLEMENT_HOOKS(job) -IMPLEMENT_HOOKS(justice) -IMPLEMENT_HOOKS(kitchenpref) -IMPLEMENT_HOOKS(layer_arena_creature) -IMPLEMENT_HOOKS(layer_assigntrade) -IMPLEMENT_HOOKS(layer_choose_language_name) -IMPLEMENT_HOOKS(layer_currency) -IMPLEMENT_HOOKS(layer_export_play_map) -IMPLEMENT_HOOKS(layer_military) -IMPLEMENT_HOOKS(layer_musicsound) -IMPLEMENT_HOOKS(layer_noblelist) -IMPLEMENT_HOOKS(layer_overall_health) -IMPLEMENT_HOOKS(layer_reaction) -IMPLEMENT_HOOKS(layer_squad_schedule) -IMPLEMENT_HOOKS(layer_stockpile) -IMPLEMENT_HOOKS(layer_stone_restriction) -IMPLEMENT_HOOKS(layer_unit_action) -IMPLEMENT_HOOKS(layer_unit_health) -IMPLEMENT_HOOKS(layer_unit_relationship) -IMPLEMENT_HOOKS(layer_world_gen_param_preset) -IMPLEMENT_HOOKS(layer_world_gen_param) -IMPLEMENT_HOOKS(legends) -IMPLEMENT_HOOKS(loadgame) -IMPLEMENT_HOOKS(locations) -IMPLEMENT_HOOKS(meeting) -IMPLEMENT_HOOKS(movieplayer) -IMPLEMENT_HOOKS(new_region) -IMPLEMENT_HOOKS(noble) -IMPLEMENT_HOOKS(option) -IMPLEMENT_HOOKS(overallstatus) -IMPLEMENT_HOOKS(petitions) -IMPLEMENT_HOOKS(pet) -IMPLEMENT_HOOKS(price) -IMPLEMENT_HOOKS(reportlist) -IMPLEMENT_HOOKS(requestagreement) -IMPLEMENT_HOOKS(savegame) -IMPLEMENT_HOOKS(selectitem) -IMPLEMENT_HOOKS(setupadventure) -IMPLEMENT_HOOKS(setupdwarfgame) -IMPLEMENT_HOOKS(stores) -IMPLEMENT_HOOKS(textviewer) -IMPLEMENT_HOOKS(title) -IMPLEMENT_HOOKS(topicmeeting_fill_land_holder_positions) -IMPLEMENT_HOOKS(topicmeeting) -IMPLEMENT_HOOKS(topicmeeting_takerequests) -IMPLEMENT_HOOKS(tradeagreement) -IMPLEMENT_HOOKS(tradegoods) -IMPLEMENT_HOOKS(tradelist) -IMPLEMENT_HOOKS(treasurelist) -IMPLEMENT_HOOKS(unitlist) -IMPLEMENT_HOOKS(unit) -IMPLEMENT_HOOKS(update_region) -IMPLEMENT_HOOKS(wages) -IMPLEMENT_HOOKS(workquota_condition) -IMPLEMENT_HOOKS(workquota_details) -IMPLEMENT_HOOKS(workshop_profile) +MAP(IMPLEMENT_HOOKS, SCREEN_LIST) #undef IMPLEMENT_HOOKS @@ -218,86 +160,7 @@ DFhackCExport command_result plugin_enable(color_ostream &, bool enable) { DEBUG(control).print("%sing interpose hooks\n", enable ? "enabl" : "disabl"); - if (INTERPOSE_HOOKS_FAILED(adopt_region) || - INTERPOSE_HOOKS_FAILED(adventure_log) || - INTERPOSE_HOOKS_FAILED(announcelist) || - INTERPOSE_HOOKS_FAILED(assign_display_item) || - INTERPOSE_HOOKS_FAILED(barter) || - INTERPOSE_HOOKS_FAILED(buildinglist) || - INTERPOSE_HOOKS_FAILED(building) || - INTERPOSE_HOOKS_FAILED(choose_start_site) || - INTERPOSE_HOOKS_FAILED(civlist) || - INTERPOSE_HOOKS_FAILED(counterintelligence) || - INTERPOSE_HOOKS_FAILED(createquota) || - INTERPOSE_HOOKS_FAILED(customize_unit) || - INTERPOSE_HOOKS_FAILED(dungeonmode) || - INTERPOSE_HOOKS_FAILED(dungeon_monsterstatus) || - INTERPOSE_HOOKS_FAILED(dungeon_wrestle) || - INTERPOSE_HOOKS_FAILED(dwarfmode) || - INTERPOSE_HOOKS_FAILED(entity) || - INTERPOSE_HOOKS_FAILED(export_graphical_map) || - INTERPOSE_HOOKS_FAILED(export_region) || - INTERPOSE_HOOKS_FAILED(game_cleaner) || - INTERPOSE_HOOKS_FAILED(image_creator) || - INTERPOSE_HOOKS_FAILED(item) || - INTERPOSE_HOOKS_FAILED(joblist) || - INTERPOSE_HOOKS_FAILED(jobmanagement) || - INTERPOSE_HOOKS_FAILED(job) || - INTERPOSE_HOOKS_FAILED(justice) || - INTERPOSE_HOOKS_FAILED(kitchenpref) || - INTERPOSE_HOOKS_FAILED(layer_arena_creature) || - INTERPOSE_HOOKS_FAILED(layer_assigntrade) || - INTERPOSE_HOOKS_FAILED(layer_choose_language_name) || - INTERPOSE_HOOKS_FAILED(layer_currency) || - INTERPOSE_HOOKS_FAILED(layer_export_play_map) || - INTERPOSE_HOOKS_FAILED(layer_military) || - INTERPOSE_HOOKS_FAILED(layer_musicsound) || - INTERPOSE_HOOKS_FAILED(layer_noblelist) || - INTERPOSE_HOOKS_FAILED(layer_overall_health) || - INTERPOSE_HOOKS_FAILED(layer_reaction) || - INTERPOSE_HOOKS_FAILED(layer_squad_schedule) || - INTERPOSE_HOOKS_FAILED(layer_stockpile) || - INTERPOSE_HOOKS_FAILED(layer_stone_restriction) || - INTERPOSE_HOOKS_FAILED(layer_unit_action) || - INTERPOSE_HOOKS_FAILED(layer_unit_health) || - INTERPOSE_HOOKS_FAILED(layer_unit_relationship) || - INTERPOSE_HOOKS_FAILED(layer_world_gen_param_preset) || - INTERPOSE_HOOKS_FAILED(layer_world_gen_param) || - INTERPOSE_HOOKS_FAILED(legends) || - INTERPOSE_HOOKS_FAILED(loadgame) || - INTERPOSE_HOOKS_FAILED(locations) || - INTERPOSE_HOOKS_FAILED(meeting) || - INTERPOSE_HOOKS_FAILED(movieplayer) || - INTERPOSE_HOOKS_FAILED(new_region) || - INTERPOSE_HOOKS_FAILED(noble) || - INTERPOSE_HOOKS_FAILED(option) || - INTERPOSE_HOOKS_FAILED(overallstatus) || - INTERPOSE_HOOKS_FAILED(petitions) || - INTERPOSE_HOOKS_FAILED(pet) || - INTERPOSE_HOOKS_FAILED(price) || - INTERPOSE_HOOKS_FAILED(reportlist) || - INTERPOSE_HOOKS_FAILED(requestagreement) || - INTERPOSE_HOOKS_FAILED(savegame) || - INTERPOSE_HOOKS_FAILED(selectitem) || - INTERPOSE_HOOKS_FAILED(setupadventure) || - INTERPOSE_HOOKS_FAILED(setupdwarfgame) || - INTERPOSE_HOOKS_FAILED(stores) || - INTERPOSE_HOOKS_FAILED(textviewer) || - INTERPOSE_HOOKS_FAILED(title) || - INTERPOSE_HOOKS_FAILED(topicmeeting_fill_land_holder_positions) || - INTERPOSE_HOOKS_FAILED(topicmeeting) || - INTERPOSE_HOOKS_FAILED(topicmeeting_takerequests) || - INTERPOSE_HOOKS_FAILED(tradeagreement) || - INTERPOSE_HOOKS_FAILED(tradegoods) || - INTERPOSE_HOOKS_FAILED(tradelist) || - INTERPOSE_HOOKS_FAILED(treasurelist) || - INTERPOSE_HOOKS_FAILED(unitlist) || - INTERPOSE_HOOKS_FAILED(unit) || - INTERPOSE_HOOKS_FAILED(update_region) || - INTERPOSE_HOOKS_FAILED(wages) || - INTERPOSE_HOOKS_FAILED(workquota_condition) || - INTERPOSE_HOOKS_FAILED(workquota_details) || - INTERPOSE_HOOKS_FAILED(workshop_profile)) + if (MAP_JOIN(INTERPOSE_HOOKS_FAILED, ||, SCREEN_LIST)) return CR_FAILURE; is_enabled = enable;