summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2019-09-23 02:04:43 +0200
committerGitHub <noreply@github.com>2019-09-23 02:04:43 +0200
commit579064db1eb50e73558dc8e81e81dd7a24f3b246 (patch)
tree48d1bb149fee8d3e4a27303d50d41d432c24fe8b /src/map
parent7121899a562856863984ce90268e9af37769b346 (diff)
parent3be1dd0c728e31743c793c78ceab97b2391fb3ac (diff)
downloadhercules-579064db1eb50e73558dc8e81e81dd7a24f3b246.tar.gz
hercules-579064db1eb50e73558dc8e81e81dd7a24f3b246.tar.bz2
hercules-579064db1eb50e73558dc8e81e81dd7a24f3b246.tar.xz
hercules-579064db1eb50e73558dc8e81e81dd7a24f3b246.zip
Merge pull request #2535 from HerculesWS/itemdb_violation
Fixed several issues in itemdb_search_name function
Diffstat (limited to 'src/map')
-rw-r--r--src/map/atcommand.c6
-rw-r--r--src/map/clif.c2
-rw-r--r--src/map/itemdb.c136
-rw-r--r--src/map/itemdb.h12
-rw-r--r--src/map/script.c2
5 files changed, 100 insertions, 58 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 968a4282a..145a5c95d 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -3559,7 +3559,7 @@ ACMD(idsearch)
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,77), item_name); // Search results for '%s' (name: id):
clif->message(fd, atcmd_output);
- match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, 0);
+ match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, IT_SEARCH_NAME_PARTIAL);
if (match > MAX_SEARCH) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, match);
clif->message(fd, atcmd_output);
@@ -7453,7 +7453,7 @@ ACMD(iteminfo)
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
- count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
+ count = itemdb->search_name_array(item_array, MAX_SEARCH, message, IT_SEARCH_NAME_PARTIAL);
if (!count) {
clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
@@ -7504,7 +7504,7 @@ ACMD(whodrops)
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
- count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
+ count = itemdb->search_name_array(item_array, MAX_SEARCH, message, IT_SEARCH_NAME_PARTIAL);
if (!count) {
clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
diff --git a/src/map/clif.c b/src/map/clif.c
index 0748558fa..1ed5e1d9f 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -15323,7 +15323,7 @@ static void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
safestrncpy(item_monster_name, p->str, sizeof(item_monster_name));
- if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) {
+ if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, IT_SEARCH_NAME_EXACT)) > 0 ) {
for(i = 0; i < count; i++) {
if( !item_array[i] )
continue;
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 3aae2c90c..e5e7b9478 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -117,73 +117,105 @@ static struct item_data *itemdb_name2id(const char *str)
*/
static int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
{
- struct item_data *item = DB->data2ptr(&data);
- char *str;
- str=va_arg(ap,char *);
+ struct item_data *itd = DB->data2ptr(&data);
+ const char *str = va_arg(ap, const char *);
+ enum item_name_search_flag flag = va_arg(ap, enum item_name_search_flag);
+
nullpo_ret(str);
- if (item == &itemdb->dummy)
+
+ if (itd == &itemdb->dummy)
return 1; //Invalid item.
- if(stristr(item->jname,str))
- return 0;
- if(battle_config.case_sensitive_aegisnames && strstr(item->name,str))
- return 0;
- if(!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
+
+ if (
+ (flag == IT_SEARCH_NAME_PARTIAL
+ && (stristr(itd->jname, str) != NULL
+ || (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
+ ))
+ || (flag == IT_SEARCH_NAME_EXACT
+ && (strcmp(itd->jname, str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
+ ))
+ ) {
+
return 0;
- return strcmpi(item->jname,str);
+ } else {
+ return 1;
+ }
}
-/*==========================================
- * Founds up to N matches. Returns number of matches [Skotlex]
- * search flag :
- * 0 - approximate match
- * 1 - exact match
- *------------------------------------------*/
-static int itemdb_searchname_array(struct item_data **data, int size, const char *str, int flag)
+/**
+ * Finds up to passed size matches
+ * @param data array of struct item_data for returning the results in
+ * @param size size of the array
+ * @param str string used in this search
+ * @param flag search mode refer to enum item_name_search_flag for possible values
+ * @return returns all found matches in the database which could be bigger than size
+ **/
+static int itemdb_searchname_array(struct item_data **data, const int size, const char *str, enum item_name_search_flag flag)
{
- struct item_data* item;
- int i;
- int count=0;
-
nullpo_ret(data);
nullpo_ret(str);
- // Search in the array
- for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i )
- {
- item = itemdb->array[i];
- if( item == NULL )
+ Assert_ret(flag >= IT_SEARCH_NAME_PARTIAL && flag < IT_SEARCH_NAME_MAX);
+ Assert_ret(size > 0);
+
+ int
+ results_count = 0,
+ length = 0;
+
+ // Search in array
+ for (int i = 0; i < ARRAYLENGTH(itemdb->array); ++i) {
+ struct item_data *itd = itemdb->array[i];
+
+ if (itd == NULL)
continue;
- if(
- (!flag
- && (stristr(item->jname,str)
- || (battle_config.case_sensitive_aegisnames && strstr(item->name,str))
- || (!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
- ))
- || (flag
- && (strcmp(item->jname,str) == 0
- || (battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0)
- || (!battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0)
- ))
- ) {
- if( count < size )
- data[count] = item;
- ++count;
+ if (
+ (flag == IT_SEARCH_NAME_PARTIAL
+ && (stristr(itd->jname, str) != NULL
+ || (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
+ ))
+ || (flag == IT_SEARCH_NAME_EXACT
+ && (strcmp(itd->jname, str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
+ ))
+ ) {
+ if (length < size) {
+ data[length] = itd;
+ ++length;
+ }
+
+ ++results_count;
}
}
- // search in the db
- if( count < size )
- {
- struct DBData *db_data[MAX_SEARCH];
- int db_count = 0;
- size -= count;
- db_count = itemdb->other->getall(itemdb->other, (struct DBData**)&db_data, size, itemdb->searchname_array_sub, str);
- for (i = 0; i < db_count; i++)
- data[count++] = DB->data2ptr(db_data[i]);
- count += db_count;
+ // Search in dbmap
+ int dbmap_size = size - length;
+ if (dbmap_size > 0) {
+ struct DBData **dbmap_data = NULL;
+ int dbmap_count = 0;
+ CREATE(dbmap_data, struct DBData *, dbmap_size);
+
+ dbmap_count = itemdb->other->getall(itemdb->other, dbmap_data, dbmap_size, itemdb->searchname_array_sub, str, flag);
+ dbmap_size = min(dbmap_count, dbmap_size);
+
+ for (int i = 0; i < dbmap_size; ++i) {
+ data[length] = DB->data2ptr(dbmap_data[i]);
+ ++length;
+ }
+
+ results_count += dbmap_count;
+ aFree(dbmap_data);
+ } else { // We got all matches we can return, so we only need to count now.
+ results_count += itemdb->other->getall(itemdb->other, NULL, 0, itemdb->searchname_array_sub, str, flag);
}
- return count;
+
+ return results_count;
}
+
/* [Ind/Hercules] */
static int itemdb_chain_item(unsigned short chain_id, int *rate)
{
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 16a348797..e3264d7d8 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -412,6 +412,16 @@ enum ItemOptionTypes {
IT_OPT_MAX
};
+/**
+ * Item name search flags
+ **/
+
+enum item_name_search_flag {
+ IT_SEARCH_NAME_PARTIAL,
+ IT_SEARCH_NAME_EXACT,
+ IT_SEARCH_NAME_MAX,
+};
+
/** Convenience item list (entry) used in various functions */
struct itemlist_entry {
int id; ///< Item ID or (inventory) index
@@ -635,7 +645,7 @@ struct itemdb_interface {
/* */
struct item_data* (*name2id) (const char *str);
struct item_data* (*search_name) (const char *name);
- int (*search_name_array) (struct item_data** data, int size, const char *str, int flag);
+ int (*search_name_array) (struct item_data **data, const int size, const char *str, enum item_name_search_flag flag);
struct item_data* (*load)(int nameid);
struct item_data* (*search)(int nameid);
struct item_data* (*exists) (int nameid);
diff --git a/src/map/script.c b/src/map/script.c
index 604213982..c7ec3c26f 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -18804,7 +18804,7 @@ static BUILDIN(searchitem)
if ((items[0] = itemdb->exists(atoi(itemname)))) {
count = 1;
} else {
- count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, 0);
+ count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, IT_SEARCH_NAME_PARTIAL);
if (count > MAX_SEARCH) count = MAX_SEARCH;
}