Pārlūkot izejas kodu

* itemdb.c/h using a static array of 32k struct item_data* entries (faster itemdb loockup and a first step to remove map_session_data->inventory_data).
* Fixed a typo in the configure script that replaced CFLAGS with CPPFLAGS when -Wno-pointer-sign is supported by the compiler. [FlavioJS]

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11259 54d463be-8e91-2dee-dedb-b68131a5f0ec

FlavioJS 17 gadi atpakaļ
vecāks
revīzija
cd8f2ef514
4 mainītis faili ar 169 papildinājumiem un 86 dzēšanām
  1. 4 0
      Changelog-Trunk.txt
  2. 2 2
      configure
  3. 1 1
      configure.in
  4. 162 83
      src/map/itemdb.c

+ 4 - 0
Changelog-Trunk.txt

@@ -4,6 +4,10 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2007/09/21
+	* itemdb.c/h using a static array of 32k struct item_data* entries (faster 
+	  itemdb loockup and a first step to remove map_session_data->inventory_data).
+	* Fixed a typo in the configure script that replaced CFLAGS with CPPFLAGS 
+	  when -Wno-pointer-sign is supported by the compiler. [FlavioJS]
 	* Corrected skill Charge Attack as described in bugreport:67 [ultramage]
 	- cast time is between 100% and 300% (+ infinite waiting fixed)
 	- damage is also between 100% and 300% (doesn't increase past range 9)

+ 2 - 2
configure

@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 11252 .
+# From configure.in Revision: 11259 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61.
 #
@@ -3748,7 +3748,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 { echo "$as_me:$LINENO: checking whether $CC supports -Wno-pointer-sign" >&5
 echo $ECHO_N "checking whether $CC supports -Wno-pointer-sign... $ECHO_C" >&6; }
 OLD_CFLAGS="$CFLAGS"
-CFLAGS="$CPPFLAGS -Wno-pointer-sign"
+CFLAGS="$CFLAGS -Wno-pointer-sign"
 cat >conftest.$ac_ext <<_ACEOF
 int foo;
 _ACEOF

+ 1 - 1
configure.in

@@ -133,7 +133,7 @@ AC_COMPILE_IFELSE(
 
 AC_MSG_CHECKING([whether $CC supports -Wno-pointer-sign])
 OLD_CFLAGS="$CFLAGS"
-CFLAGS="$CPPFLAGS -Wno-pointer-sign"
+CFLAGS="$CFLAGS -Wno-pointer-sign"
 AC_COMPILE_IFELSE(
 	[int foo;],
 	[AC_MSG_RESULT([yes])],

+ 162 - 83
src/map/itemdb.c

@@ -15,18 +15,25 @@
 #include <stdlib.h>
 #include <string.h>
 
+// 32k array entries (the rest goes to the db)
+#define MAX_ITEMDB 0x8000
 
-static struct dbt* item_db;
+
+
+static struct item_data* itemdb_array[MAX_ITEMDB];
+static struct dbt*       itemdb_other;
 
 static struct item_group itemgroup_db[MAX_ITEMGROUP];
 
 struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex]
 
+
+
 /*==========================================
  * 名前で検索用
  *------------------------------------------*/
 // name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
-int itemdb_searchname_sub(DBKey key,void *data,va_list ap)
+static int itemdb_searchname_sub(DBKey key,void *data,va_list ap)
 {
 	struct item_data *item=(struct item_data *)data,**dst,**dst2;
 	char *str;
@@ -52,9 +59,27 @@ int itemdb_searchname_sub(DBKey key,void *data,va_list ap)
  *------------------------------------------*/
 struct item_data* itemdb_searchname(const char *str)
 {
-	struct item_data *item=NULL, *item2=NULL;
+	struct item_data* item;
+	struct item_data* item2=NULL;
+	int i;
+
+	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
+	{
+		item = itemdb_array[i];
+		if( item == NULL )
+			continue;
+
+		// Absolute priority to Aegis code name.
+		if( strcasecmp(item->name,str) == 0 )
+			return item;
+
+		//Second priority to Client displayed name.
+		if( strcasecmp(item->name,str) == 0 )
+			item2 = item;
+	}
 
-	item_db->foreach(item_db,itemdb_searchname_sub,str,&item,&item2);
+	item = NULL;
+	itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2);
 	return item?item:item2;
 }
 
@@ -77,7 +102,37 @@ static int itemdb_searchname_array_sub(DBKey key,void * data,va_list ap)
  *------------------------------------------*/
 int itemdb_searchname_array(struct item_data** data, int size, const char *str)
 {
-	return item_db->getall(item_db,(void**)data,size,itemdb_searchname_array_sub,str);
+	struct item_data* item;
+	int i;
+	int count=0;
+
+	// Search in the array
+	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
+	{
+		item = itemdb_array[i];
+		if( item == NULL )
+			continue;
+
+		if( stristr(item->jname,str) || stristr(item->name,str) )
+		{
+			if( count < size )
+				data[count] = item;
+			++count;
+		}
+	}
+
+	// search in the db
+	if( count >= size )
+	{
+		data = NULL;
+		size = 0;
+	}
+	else
+	{
+		data -= count;
+		size -= count;
+	}
+	return count + itemdb_other->getall(itemdb_other,(void**)data,size,itemdb_searchname_array_sub,str);
 }
 
 
@@ -119,18 +174,18 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid)
 	return bonus;
 }
 
-/*==========================================
- * DBの存在確認
- *------------------------------------------*/
+/// Searches for the item_data.
+/// Returns the item_data or NULL if it does not exist.
 struct item_data* itemdb_exists(int nameid)
 {
-	struct item_data* id;
-	if (!nameid) return NULL;
-	id = idb_get(item_db,nameid);
-	//Adjust nameid in case it's used outside. [Skotlex]
-	if (id == &dummy_item)
-		dummy_item.nameid = nameid;
-	return id;
+	struct item_data* item;
+
+	if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
+		return itemdb_array[nameid];
+	item = idb_get(itemdb_other,nameid);
+	if( item == &dummy_item )
+		return NULL;// dummy data, doesn't exist
+	return item;
 }
 
 /*==========================================
@@ -199,18 +254,18 @@ static void create_dummy_data(void)
 	memset(&dummy_item, 0, sizeof(struct item_data));
 	dummy_item.nameid=500;
 	dummy_item.weight=1;
-	dummy_item.value_sell = 1;
-	dummy_item.type=3; //Etc item
-	strncpy(dummy_item.name,"UNKNOWN_ITEM",ITEM_NAME_LENGTH-1);
-	strncpy(dummy_item.jname,"UNKNOWN_ITEM",ITEM_NAME_LENGTH-1);
-	dummy_item.view_id = UNKNOWN_ITEM_ID;
+	dummy_item.value_sell=1;
+	dummy_item.type=IT_ETC; //Etc item
+	safestrncpy(dummy_item.name,"UNKNOWN_ITEM",sizeof(dummy_item.name));
+	safestrncpy(dummy_item.jname,"UNKNOWN_ITEM",sizeof(dummy_item.jname));
+	dummy_item.view_id=UNKNOWN_ITEM_ID;
 }
 
 static void* create_item_data(DBKey key, va_list args)
 {
 	struct item_data *id;
-	id=(struct item_data *)aCalloc(1,sizeof(struct item_data));
-	id->nameid = key.i;
+	CREATE(id, struct item_data, 1);
+	id->nameid=key.i;
 	id->weight=1;
 	id->type=IT_ETC;
 	return id;
@@ -221,14 +276,26 @@ static void* create_item_data(DBKey key, va_list args)
  *------------------------------------------*/
 struct item_data* itemdb_load(int nameid)
 {
-	struct item_data *id = idb_ensure(item_db,nameid,create_item_data);
-	if (id == &dummy_item)
-  	{	//Remove dummy_item, replace by real data.
-		DBKey key;
+	struct item_data *id;
+	DBKey key;
+
+	if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
+	{
+		id = itemdb_array[nameid];
+		if( id == NULL )
+		{
+			key.i = nameid;
+			id = itemdb_array[nameid] = create_item_data(key, NULL);
+		}
+		return id;
+	}
+
+	id = idb_ensure(itemdb_other, nameid, create_item_data);
+	if( id == &dummy_item )
+	{// Remove dummy_item, replace by real data.
 		key.i = nameid;
-		idb_remove(item_db,nameid);
 		id = create_item_data(key, NULL);
-		idb_put(item_db,nameid,id);
+		idb_put(itemdb_other, nameid, id);
 	}
 	return id;
 }
@@ -246,7 +313,15 @@ static void* return_dummy_data(DBKey key, va_list args)
  *------------------------------------------*/
 struct item_data* itemdb_search(int nameid)
 {
-	return idb_ensure(item_db,nameid,return_dummy_data);
+	if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
+	{
+		DBKey key;
+		if( itemdb_array[nameid] )
+			return itemdb_array[nameid];
+		key.i = nameid;
+		return (struct item_data*)return_dummy_data(key, NULL);
+	}
+	return idb_ensure(itemdb_other,nameid,return_dummy_data);
 }
 
 /*==========================================
@@ -630,18 +705,21 @@ static bool itemdb_parse_dbrow(char** str, char* source, int line)
 		| id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script |
 		+----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
 	*/
-	unsigned short nameid;
+	int nameid;
 	struct item_data* id;
 	
 	nameid = atoi(str[0]);
-	if(nameid <= 0)
+	if( nameid <= 0 )
+	{
+		ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source);
 		return false;
-	
+	}
+
 	//ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View
 	id = itemdb_load(nameid);
-	safestrncpy(id->name, str[1], ITEM_NAME_LENGTH-1);
-	safestrncpy(id->jname, str[2], ITEM_NAME_LENGTH-1);
-	
+	safestrncpy(id->name, str[1], sizeof(id->name));
+	safestrncpy(id->jname, str[2], sizeof(id->jname));
+
 	id->type = atoi(str[3]);
 	if (id->type == IT_DELAYCONSUME)
 	{	//Items that are consumed only after target confirmation
@@ -655,13 +733,13 @@ static bool itemdb_parse_dbrow(char** str, char* source, int line)
 	if (id->value_buy < id->value_sell * 2) id->value_buy = id->value_sell * 2; // prevent exploit
 	if (id->value_buy == 0 && id->value_sell > 0) id->value_buy = id->value_sell * 2;
 	if (id->value_sell == 0 && id->value_buy > 0) id->value_sell = id->value_buy / 2;
-	
+
 	id->weight = atoi(str[6]);
 	id->atk = atoi(str[7]);
 	id->def = atoi(str[8]);
 	id->range = atoi(str[9]);
 	id->slot = atoi(str[10]);
-	
+
 	if (id->slot > MAX_SLOTS)
 	{
 		ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS);
@@ -672,18 +750,18 @@ static bool itemdb_parse_dbrow(char** str, char* source, int line)
 	id->class_upper = atoi(str[12]);
 	id->sex	= atoi(str[13]);
 	id->equip = atoi(str[14]);
-	
+
 	if (!id->equip && itemdb_isequip2(id))
 	{
 		ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname);
 		id->type = IT_ETC;
 	}
-	
+
 	id->wlv = atoi(str[15]);
 	id->elv = atoi(str[16]);
 	id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this
 	id->look = atoi(str[18]);
-	
+
 	id->flag.available = 1;
 	id->flag.value_notdc = 0;
 	id->flag.value_notoc = 0;
@@ -715,7 +793,7 @@ static int itemdb_readdb(void)
 	char* filename[] = { "item_db.txt", "item_db2.txt" };
 	int fi;
 
-	for(fi = 0; fi < 2; fi++)
+	for( fi = 0; fi < ARRAYLENGTH(filename); ++fi )
 	{
 		uint32 lines = 0, count = 0;
 		char line[1024];
@@ -725,10 +803,10 @@ static int itemdb_readdb(void)
 
 		sprintf(path, "%s/%s", db_path, filename[fi]);
 		fp = fopen(path, "r");
-		if(fp == NULL) {
-			if(fi > 0)
-				continue;
-			return -1;
+		if( fp == NULL )
+		{
+			ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path);
+			continue;
 		}
 
 		// process rows one by one
@@ -749,8 +827,9 @@ static int itemdb_readdb(void)
 				}
 			}
 
-			if (i < 19) {
-				ShowWarning("itemdb_readdb: Insufficient columns for item with id %d, skipping.\n", atoi(str[0]));
+			if( i < 19 )
+			{
+				ShowWarning("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
 				continue;
 			}
 
@@ -782,7 +861,7 @@ static int itemdb_readdb(void)
 				continue;
 			str[21] = p; //Unequip script, last column.
 
-			if (!itemdb_parse_dbrow(str, filename[fi], lines))
+			if (!itemdb_parse_dbrow(str, path, lines))
 				continue;
 			
 			count++;
@@ -879,30 +958,34 @@ static void itemdb_read(void)
 /*==========================================
  * Initialize / Finalize
  *------------------------------------------*/
-static int itemdb_final_sub (DBKey key,void *data,va_list ap)
+
+/// Destroys the item_data.
+static void destroy_item_data(struct item_data* self, int free_self)
+{
+	if( self == NULL )
+		return;
+	// free scripts
+	if( self->script )
+		script_free_code(self->script);
+	if( self->equip_script )
+		script_free_code(self->equip_script);
+	if( self->unequip_script )
+		script_free_code(self->unequip_script);
+#if defined(DEBUG)
+	// trash item
+	memset(self, 0xDD, sizeof(struct item_data));
+#endif
+	// free self
+	if( free_self )
+		aFree(self);
+}
+
+static int itemdb_final_sub(DBKey key,void *data,va_list ap)
 {
-	int flag;
 	struct item_data *id = (struct item_data *)data;
 
-	flag = va_arg(ap, int);
-	if (id->script)
-	{
-		script_free_code(id->script);
-		id->script = NULL;
-	}
-	if (id->equip_script)
-	{
-		script_free_code(id->equip_script);
-		id->equip_script = NULL;
-	}
-	if (id->unequip_script)
-	{
-		script_free_code(id->unequip_script);
-		id->unequip_script = NULL;
-	}
-	// Whether to clear the item data (exception: do not clear the dummy item data
-	if (flag && id != &dummy_item) 
-		aFree(id);
+	if( id != &dummy_item )
+		destroy_item_data(id, 1);
 
 	return 0;
 }
@@ -915,24 +998,20 @@ void itemdb_reload(void)
 
 void do_final_itemdb(void)
 {
-	item_db->destroy(item_db, itemdb_final_sub, 1);
-	if (dummy_item.script) {
-		script_free_code(dummy_item.script);
-		dummy_item.script = NULL;
-	}
-	if (dummy_item.equip_script) {
-		script_free_code(dummy_item.equip_script);
-		dummy_item.equip_script = NULL;
-	}
-	if (dummy_item.unequip_script) {
-		script_free_code(dummy_item.unequip_script);
-		dummy_item.unequip_script = NULL;
-	}
+	int i;
+
+	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
+		if( itemdb_array[i] )
+			destroy_item_data(itemdb_array[i], 1);
+
+	itemdb_other->destroy(itemdb_other, itemdb_final_sub);
+	destroy_item_data(&dummy_item, 0);
 }
 
 int do_init_itemdb(void)
 {
-	item_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); 
+	memset(itemdb_array, 0, sizeof(itemdb_array));
+	itemdb_other = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); 
 	create_dummy_data(); //Dummy data item.
 	itemdb_read();