remove order de-duplication for short and study orders.

This commit is contained in:
Enno Rehling 2017-10-08 15:34:40 +02:00
parent 828ca5f5f6
commit 97ff152f17
3 changed files with 43 additions and 106 deletions

View File

@ -31,21 +31,13 @@
#include <string.h> #include <string.h>
# define ORD_KEYWORD(ord) (keyword_t)((ord)->command & 0xFFFF) # define ORD_KEYWORD(ord) (keyword_t)((ord)->command & 0xFFFF)
# define OD_LOCALE(odata) locale_array[(odata)->_lindex]->lang # define OD_LOCALE(odata) ((odata) ? (odata)->lang : NULL)
# define OD_STRING(odata) (odata)->_str # define OD_STRING(odata) ((odata) ? (odata)->_str : NULL)
typedef struct locale_data {
struct order_data *short_orders;
struct order_data *study_orders[MAXSKILLS];
const struct locale *lang;
} locale_data;
static struct locale_data *locale_array[MAXLOCALES];
typedef struct order_data { typedef struct order_data {
const char *_str; const char *_str;
int _refcount; int _refcount;
int _lindex; const struct locale *lang;
} order_data; } order_data;
#include <selist.h> #include <selist.h>
@ -53,15 +45,21 @@ typedef struct order_data {
static selist * orders; static selist * orders;
order_data *load_data(int id) { order_data *load_data(int id) {
if (id > 0) {
order_data * od = (order_data *)selist_get(orders, id - 1); order_data * od = (order_data *)selist_get(orders, id - 1);
++od->_refcount; ++od->_refcount;
return od; return od;
}
return NULL;
} }
int add_data(order_data *od) { int add_data(order_data *od) {
if (od->_str) {
++od->_refcount; ++od->_refcount;
selist_push(&orders, od); selist_push(&orders, od);
return selist_length(orders); return selist_length(orders);
}
return 0;
} }
static void release_data(order_data * data) static void release_data(order_data * data)
@ -219,103 +217,42 @@ void free_orders(order ** olist)
} }
} }
static char *mkdata(order_data **pdata, size_t len, int lindex, const char *str) static char *mkdata(order_data **pdata, size_t len, const struct locale *lang, const char *str)
{ {
order_data *data; order_data *data;
char *result; char *result;
data = malloc(sizeof(order_data) + len + 1); data = malloc(sizeof(order_data) + len + 1);
result = (char *)(data + 1); result = (char *)(data + 1);
data->_lindex = lindex; data->lang = lang;
data->_refcount = 0; data->_refcount = 0;
data->_str = 0; data->_str = (len > 0) ? result : NULL;
data->_str = (len > 0) ? result : 0;
if (str) strcpy(result, str); if (str) strcpy(result, str);
if (pdata) *pdata = data; if (pdata) *pdata = data;
return result; return result;
} }
static order_data *create_data(keyword_t kwd, const char *sptr, int lindex) static order_data *create_data(keyword_t kwd, const char *sptr, const struct locale *lang)
{ {
const char *s = sptr; const char *s = sptr;
order_data *data; order_data *data;
const struct locale *lang = locale_array[lindex]->lang;
if (kwd != NOKEYWORD) if (kwd != NOKEYWORD)
s = (*sptr) ? sptr : NULL; s = (*sptr) ? sptr : NULL;
/* learning, only one order_data per skill required */
if (kwd == K_STUDY) {
skill_t sk = get_skill(parse_token_depr(&sptr), lang);
switch (sk) {
case NOSKILL: /* fehler */
break;
case SK_MAGIC: /* kann parameter haben */
if (*sptr != 0)
break;
default: /* nur skill als Parameter, keine extras */
data = locale_array[lindex]->study_orders[sk];
if (data == NULL) {
const char *skname = skillname(sk, lang);
const char *spc = strchr(skname, ' ');
size_t len = strlen(skname);
char *dst = mkdata(&data, len + (spc ? 3 : 0), lindex, spc ? 0 : skname);
locale_array[lindex]->study_orders[sk] = data;
if (spc) {
dst[0] = '\"';
memcpy(dst + 1, skname, len);
dst[len + 1] = '\"';
dst[len + 2] = '\0';
}
data->_refcount = 1;
}
++data->_refcount;
return data;
}
}
/* orders with no parameter, only one order_data per order required */ /* orders with no parameter, only one order_data per order required */
else if (kwd != NOKEYWORD && *sptr == 0) { if (kwd != NOKEYWORD && *sptr == 0) {
data = locale_array[lindex]->short_orders; mkdata(&data, 0, lang, NULL);
if (data == NULL) {
mkdata(&data, 0, lindex, 0);
data->_refcount = 1;
locale_array[lindex]->short_orders = data;
}
++data->_refcount;
return data;
}
mkdata(&data, s ? strlen(s) : 0, lindex, s);
data->_refcount = 1; data->_refcount = 1;
return data; return data;
}
static void clear_localedata(int lindex) {
int i;
release_data(locale_array[lindex]->short_orders);
locale_array[lindex]->short_orders = NULL;
for (i = 0; i != MAXSKILLS; ++i) {
release_data(locale_array[lindex]->study_orders[i]);
locale_array[lindex]->study_orders[i] = 0;
} }
locale_array[lindex]->lang = 0; mkdata(&data, s ? strlen(s) : 0, lang, s);
} data->_refcount = 1;
return data;
void close_orders(void) {
int i;
for (i = 0; i != MAXLOCALES; ++i) {
if (locale_array[i]){
clear_localedata(i);
free(locale_array[i]);
locale_array[i] = 0;
}
}
free_data();
} }
static order *create_order_i(order *ord, keyword_t kwd, const char *sptr, bool persistent, static order *create_order_i(order *ord, keyword_t kwd, const char *sptr, bool persistent,
bool noerror, const struct locale *lang) bool noerror, const struct locale *lang)
{ {
int lindex;
order_data *od; order_data *od;
assert(ord); assert(ord);
@ -335,16 +272,6 @@ static order *create_order_i(order *ord, keyword_t kwd, const char *sptr, bool p
} }
} }
lindex = locale_index(lang);
assert(lindex < MAXLOCALES);
if (!locale_array[lindex]) {
locale_array[lindex] = (locale_data *)calloc(1, sizeof(locale_data));
}
else if (locale_array[lindex]->lang != lang) {
clear_localedata(lindex);
}
locale_array[lindex]->lang = lang;
ord->command = (int)kwd; ord->command = (int)kwd;
if (persistent) ord->command |= CMD_PERSIST; if (persistent) ord->command |= CMD_PERSIST;
if (noerror) ord->command |= CMD_QUIET; if (noerror) ord->command |= CMD_QUIET;
@ -352,7 +279,7 @@ static order *create_order_i(order *ord, keyword_t kwd, const char *sptr, bool p
while (isspace(*(unsigned char *)sptr)) ++sptr; while (isspace(*(unsigned char *)sptr)) ++sptr;
od = create_data(kwd, sptr, lindex); od = create_data(kwd, sptr, lang);
ord->id = add_data(od); ord->id = add_data(od);
release_data(od); release_data(od);
@ -630,21 +557,30 @@ void push_order(order ** ordp, order * ord)
*ordp = ord; *ordp = ord;
} }
static order_data *parser_od;
keyword_t init_order(const struct order *ord) keyword_t init_order(const struct order *ord)
{ {
static order_data *od;
if (!ord) { if (!ord) {
release_data(od); release_data(parser_od);
parser_od = NULL;
return NOKEYWORD; return NOKEYWORD;
} }
else { else {
if (od) { if (parser_od) {
// TODO: warning // TODO: warning
release_data(od); release_data(parser_od);
} }
od = load_data(ord->id); parser_od = load_data(ord->id);
init_tokens_str(od->_str); init_tokens_str(OD_STRING(parser_od));
return ORD_KEYWORD(ord); return ORD_KEYWORD(ord);
} }
} }
void close_orders(void) {
if (parser_od) {
init_order(NULL);
}
free_data();
}

View File

@ -496,8 +496,8 @@ int sabotage_cmd(unit * u, struct order *ord)
init_order(ord); init_order(ord);
s = getstrtoken(); s = getstrtoken();
p = findparam(s, u->faction->locale); p = findparam(s, u->faction->locale);
init_order(NULL);
switch (p) { switch (p) {
case P_SHIP: case P_SHIP:

View File

@ -448,6 +448,7 @@ int teach_cmd(unit * teacher, struct order *ord)
if (academy_students > 0 && sk_academy!=NOSKILL) { if (academy_students > 0 && sk_academy!=NOSKILL) {
academy_teaching_bonus(teacher, sk_academy, academy_students); academy_teaching_bonus(teacher, sk_academy, academy_students);
} }
init_order(NULL);
return 0; return 0;
} }
@ -784,7 +785,7 @@ int study_cmd(unit * u, order * ord)
mage = create_mage(u, u->faction->magiegebiet); mage = create_mage(u, u->faction->magiegebiet);
} }
} }
init_order(NULL);
return 0; return 0;
} }