Author: persia Date: Tue Jul 15 14:14:23 2014 New Revision: 25578 URL: http://svn.gna.org/viewcvs/freeciv?rev=25578&view=rev Log: Rewrite universal_fulfills_requirement
Performance considerations inspired by Marko Lindqvist <cazfi> See patch #4940 Modified: trunk/common/game.c trunk/common/requirements.c trunk/common/requirements.h Modified: trunk/common/game.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/game.c?rev=25578&r1=25577&r2=25578&view=diff ============================================================================== --- trunk/common/game.c (original) +++ trunk/common/game.c Tue Jul 15 14:14:23 2014 @@ -441,6 +441,7 @@ idex_init(); cm_init(); researches_init(); + universal_found_functions_init(); } /**************************************************************************** Modified: trunk/common/requirements.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/requirements.c?rev=25578&r1=25577&r2=25578&view=diff ============================================================================== --- trunk/common/requirements.c (original) +++ trunk/common/requirements.c Tue Jul 15 14:14:23 2014 @@ -38,6 +38,13 @@ /* The item contradicts, fulfills or is irrelevant to the requirement */ enum item_found {ITF_NO, ITF_YES, ITF_NOT_APPLICABLE}; + +/************************************************************************ + Container for item_found functions +************************************************************************/ +typedef enum item_found (*universal_found)(const struct requirement *, + const struct universal *); +static universal_found universal_found_function[VUT_COUNT] = {NULL}; /************************************************************************** Parse requirement type (kind) and value strings into a universal @@ -2811,19 +2818,13 @@ Not being mentioned counts as fulfillment. **************************************************************************/ -static bool -universal_fulfills_requirement(universals_u *univ, - enum item_found (*fulfills)( - const struct requirement *, - universals_u *), - const struct requirement_vector *reqs) -{ - fc_assert(univ); - fc_assert(fulfills); - fc_assert(reqs); +bool universal_fulfills_requirement(const struct requirement_vector *reqs, + const struct universal *source) +{ + fc_assert(universal_found_function[source->kind]); requirement_vector_iterate(reqs, preq) { - switch (fulfills(preq, univ)) { + switch ((*universal_found_function[source->kind])(preq, source)) { case ITF_NOT_APPLICABLE: continue; case ITF_NO: @@ -2846,16 +2847,16 @@ Find if a unit class fulfills a requirement **************************************************************************/ static enum item_found unit_class_found(const struct requirement *preq, - universals_u *uclass) -{ - fc_assert(uclass); - fc_assert(preq); + const struct universal *source) +{ + fc_assert(source->value.uclass); switch (preq->source.kind) { case VUT_UCLASS: - return uclass->uclass == preq->source.value.uclass ? ITF_YES : ITF_NO; + return source->value.uclass == preq->source.value.uclass ? ITF_YES + : ITF_NO; case VUT_UCFLAG: - return uclass_has_flag(uclass->uclass, + return uclass_has_flag(source->value.uclass, preq->source.value.unitclassflag) ? ITF_YES : ITF_NO; @@ -2869,22 +2870,21 @@ Find if a unit type fulfills a requirement **************************************************************************/ static enum item_found unit_type_found(const struct requirement *preq, - universals_u *utype) -{ - fc_assert(utype); - fc_assert(preq); + const struct universal *source) +{ + fc_assert(source->value.utype); switch (preq->source.kind) { case VUT_UTYPE: - return utype->utype == preq->source.value.utype ? ITF_YES : ITF_NO; + return source->value.utype == preq->source.value.utype ? ITF_YES : ITF_NO; case VUT_UCLASS: - return utype_class(utype->utype) == preq->source.value.uclass ? ITF_YES - : ITF_NO; + return utype_class(source->value.utype) == preq->source.value.uclass + ? ITF_YES : ITF_NO; case VUT_UTFLAG: - return utype_has_flag(utype->utype, + return utype_has_flag(source->value.utype, preq->source.value.unitflag) ? ITF_YES : ITF_NO; case VUT_UCFLAG: - return uclass_has_flag(utype_class(utype->utype), + return uclass_has_flag(utype_class(source->value.utype), preq->source.value.unitclassflag) ? ITF_YES : ITF_NO; default: @@ -2893,46 +2893,11 @@ }; } -/************************************************************************* - Will the specified unit class fulfill the requirements in the list? -**************************************************************************/ -bool requirement_fulfilled_by_unit_class(struct unit_class *uclass, - const struct requirement_vector *reqs) -{ - universals_u *univ; - bool result; - - fc_assert(uclass); - fc_assert(reqs); - - univ = fc_malloc(sizeof(*univ)); - univ->uclass = uclass; - - result = universal_fulfills_requirement(univ, unit_class_found, reqs); - - free(univ); - - return result; -} - -/************************************************************************* - Will the specified unit type fulfill the requirements in the list? -**************************************************************************/ -bool requirement_fulfilled_by_unit_type(struct unit_type *utype, - const struct requirement_vector *reqs) -{ - universals_u *univ; - bool result; - - fc_assert(utype); - fc_assert(reqs); - - univ = fc_malloc(sizeof(*univ)); - univ->utype = utype; - - result = universal_fulfills_requirement(univ, unit_type_found, reqs); - - free(univ); - - return result; -} +/************************************************************************ + Initialise universal_found_callbacks array. +*************************************************************************/ +void universal_found_functions_init(void) +{ + universal_found_function[VUT_UCLASS] = &unit_class_found; + universal_found_function[VUT_UTYPE] = &unit_type_found; +} Modified: trunk/common/requirements.h URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/requirements.h?rev=25578&r1=25577&r2=25578&view=diff ============================================================================== --- trunk/common/requirements.h (original) +++ trunk/common/requirements.h Tue Jul 15 14:14:23 2014 @@ -140,10 +140,19 @@ int universal_build_shield_cost(const struct universal *target); -bool requirement_fulfilled_by_unit_class(struct unit_class *uclass, - const struct requirement_vector *reqs); -bool requirement_fulfilled_by_unit_type(struct unit_type *utype, - const struct requirement_vector *reqs); +void universal_found_functions_init(void); +bool universal_fulfills_requirement(const struct requirement_vector *reqs, + const struct universal *source); + +/* Accessors to determine if a universal fulfills a requirement vector. + * When adding an additional accessor, be sure to add the appropriate + * item_found function in universal_found_callbacks_init(). */ +#define requirement_fulfilled_by_unit_class(_uc_, _rqs_) \ + universal_fulfills_requirement((_rqs_), \ + &(struct universal){.kind = VUT_UCLASS, .value = {.uclass = (_uc_)}}) +#define requirement_fulfilled_by_unit_type(_ut_, _rqs_) \ + universal_fulfills_requirement((_rqs_), \ + &(struct universal){.kind = VUT_UTYPE, .value = {.utype = (_ut_)}}) #ifdef __cplusplus } _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits