summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/HPMchar.c18
-rw-r--r--src/char/HPMchar.h2
-rw-r--r--src/char/char.c92
-rw-r--r--src/char/char.h3
-rw-r--r--src/char/loginif.c4
-rw-r--r--src/common/HPM.c696
-rw-r--r--src/common/HPM.h66
-rw-r--r--src/common/HPMDataCheck.h1
-rw-r--r--src/common/HPMi.h121
-rw-r--r--src/common/cbasetypes.h2
-rw-r--r--src/common/console.c286
-rw-r--r--src/common/console.h18
-rw-r--r--src/common/core.c35
-rw-r--r--src/common/core.h4
-rw-r--r--src/common/db.h1321
-rw-r--r--src/common/mmo.h7
-rw-r--r--src/common/socket.c133
-rw-r--r--src/common/socket.h26
-rw-r--r--src/common/timer.c34
-rw-r--r--src/login/HPMlogin.c18
-rw-r--r--src/login/HPMlogin.h2
-rw-r--r--src/login/login.c25
-rw-r--r--src/map/HPMmap.c52
-rw-r--r--src/map/HPMmap.h2
-rw-r--r--src/map/battleground.c14
-rw-r--r--src/map/battleground.h6
-rw-r--r--src/map/chrif.c22
-rw-r--r--src/map/clif.c12
-rw-r--r--src/map/guild.c23
-rw-r--r--src/map/instance.c14
-rw-r--r--src/map/instance.h7
-rw-r--r--src/map/itemdb.c12
-rw-r--r--src/map/itemdb.h6
-rw-r--r--src/map/map.c11
-rw-r--r--src/map/map.h6
-rw-r--r--src/map/mob.c11
-rw-r--r--src/map/mob.h13
-rw-r--r--src/map/npc.c11
-rw-r--r--src/map/npc.h6
-rw-r--r--src/map/party.c23
-rw-r--r--src/map/party.h7
-rw-r--r--src/map/path.c2
-rw-r--r--src/map/pc.c20
-rw-r--r--src/map/pc.h9
-rw-r--r--src/map/unit.c24
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.Hooks.inc12
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.Hooks.inc12
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc12
48 files changed, 1734 insertions, 1529 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c
index a67f017c1..d3150bc11 100644
--- a/src/char/HPMchar.c
+++ b/src/char/HPMchar.c
@@ -47,13 +47,19 @@
// HPMDataCheck comes after all the other includes
#include "common/HPMDataCheck.h"
-bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
- /* record address */
- switch( type ) {
+/**
+ * HPM plugin data store validator sub-handler (char-server)
+ *
+ * @see HPM_interface::data_store_validate
+ */
+bool HPM_char_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize)
+{
+ switch (type) {
+ // No supported types at the moment.
default:
- return false;
+ break;
}
- return true;
+ return false;
}
void HPM_char_plugin_load_sub(struct hplugin *plugin) {
@@ -61,6 +67,8 @@ void HPM_char_plugin_load_sub(struct hplugin *plugin) {
}
void HPM_char_do_init(void) {
+ HPM->load_sub = HPM_char_plugin_load_sub;
+ HPM->data_store_validate_sub = HPM_char_data_store_validate;
HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
HPM_shared_symbols(SERVER_TYPE_CHAR);
}
diff --git a/src/char/HPMchar.h b/src/char/HPMchar.h
index e3e000ef3..431017b7a 100644
--- a/src/char/HPMchar.h
+++ b/src/char/HPMchar.h
@@ -13,7 +13,7 @@
struct hplugin;
-bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+bool HPM_char_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize);
void HPM_char_plugin_load_sub(struct hplugin *plugin);
diff --git a/src/char/char.c b/src/char/char.c
index 3cc8853a4..1e0428a3d 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -2626,10 +2626,12 @@ int char_parse_fromlogin(int fd) {
while(RFIFOREST(fd) >= 2) {
uint16 command = RFIFOW(fd,0);
- if( HPM->packetsc[hpParse_FromLogin] ) {
- int success = HPM->parse_packets(fd,hpParse_FromLogin);
- if( success == 1 ) continue;
- else if( success == 2 ) return 0;
+ if (VECTOR_LENGTH(HPM->packets[hpParse_FromLogin]) > 0) {
+ int result = HPM->parse_packets(fd,hpParse_FromLogin);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
switch (command) {
@@ -2965,9 +2967,11 @@ void mapif_server_reset(int id)
WBUFL(buf,4) = htonl(chr->server[id].ip);
WBUFW(buf,8) = htons(chr->server[id].port);
j = 0;
- for(i = 0; i < chr->server[id].maps; i++)
- if (chr->server[id].map[i])
- WBUFW(buf,10+(j++)*4) = chr->server[id].map[i];
+ for (i = 0; i < VECTOR_LENGTH(chr->server[id].maps); i++) {
+ uint16 m = VECTOR_INDEX(chr->server[id].maps, i);
+ if (m != 0)
+ WBUFW(buf,10+(j++)*4) = m;
+ }
if (j > 0) {
WBUFW(buf,2) = j * 4 + 10;
mapif->sendallwos(fd, buf, WBUFW(buf,2));
@@ -3050,14 +3054,16 @@ void char_send_maps(int fd, int id, int j)
// Transmitting the maps of the other map-servers to the new map-server
for(k = 0; k < ARRAYLENGTH(chr->server); k++) {
if (chr->server[k].fd > 0 && k != id) {
- WFIFOHEAD(fd,10 +4*chr->server[k].maps);
+ WFIFOHEAD(fd,10 + 4 * VECTOR_LENGTH(chr->server[k].maps));
WFIFOW(fd,0) = 0x2b04;
WFIFOL(fd,4) = htonl(chr->server[k].ip);
WFIFOW(fd,8) = htons(chr->server[k].port);
j = 0;
- for(i = 0; i < chr->server[k].maps; i++)
- if (chr->server[k].map[i])
- WFIFOW(fd,10+(j++)*4) = chr->server[k].map[i];
+ for(i = 0; i < VECTOR_LENGTH(chr->server[k].maps); i++) {
+ uint16 m = VECTOR_INDEX(chr->server[k].maps, i);
+ if (m != 0)
+ WFIFOW(fd,10+(j++)*4) = m;
+ }
if (j > 0) {
WFIFOW(fd,2) = j * 4 + 10;
WFIFOSET(fd,WFIFOW(fd,2));
@@ -3068,27 +3074,22 @@ void char_send_maps(int fd, int id, int j)
void char_parse_frommap_map_names(int fd, int id)
{
- int i,j = 0;
-
- if( chr->server[id].map != NULL ) { aFree(chr->server[id].map); chr->server[id].map = NULL; }
-
- chr->server[id].maps = ( RFIFOW(fd, 2) - 4 ) / 4;
- CREATE(chr->server[id].map, unsigned short, chr->server[id].maps);
-
+ int i;
- for(i = 4; i < RFIFOW(fd,2); i += 4) {
- chr->server[id].map[j] = RFIFOW(fd,i);
- j++;
+ VECTOR_CLEAR(chr->server[id].maps);
+ VECTOR_ENSURE(chr->server[id].maps, (RFIFOW(fd, 2) - 4) / 4, 1);
+ for (i = 4; i < RFIFOW(fd,2); i += 4) {
+ VECTOR_PUSH(chr->server[id].maps, RFIFOW(fd,i));
}
ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
- id, j, CONVIP(chr->server[id].ip), chr->server[id].port);
+ id, (int)VECTOR_LENGTH(chr->server[id].maps), CONVIP(chr->server[id].ip), chr->server[id].port);
ShowStatus("Map-server %d loading complete.\n", id);
// send name for wisp to player
chr->map_received_ok(fd);
chr->send_fame_list(fd); //Send fame list.
- chr->send_maps(fd, id, j);
+ chr->send_maps(fd, id, (int)VECTOR_LENGTH(chr->server[id].maps));
RFIFOSKIP(fd,RFIFOW(fd,2));
}
@@ -3896,7 +3897,6 @@ void char_parse_frommap_scdata_delete(int fd)
int char_parse_frommap(int fd)
{
- int i;
int id;
ARR_FIND( 0, ARRAYLENGTH(chr->server), id, chr->server[id].fd == fd );
@@ -3913,11 +3913,12 @@ int char_parse_frommap(int fd)
}
while(RFIFOREST(fd) >= 2) {
- if( HPM->packetsc[hpParse_FromMap] ) {
- if( (i = HPM->parse_packets(fd,hpParse_FromMap)) ) {
- if( i == 1 ) continue;
- if( i == 2 ) return 0;
- }
+ if (VECTOR_LENGTH(HPM->packets[hpParse_FromMap]) > 0) {
+ int result = HPM->parse_packets(fd,hpParse_FromMap);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
switch(RFIFOW(fd,0)) {
@@ -4154,11 +4155,11 @@ int char_search_mapserver(unsigned short map, uint32 ip, uint16 port)
{
if (chr->server[i].fd > 0
&& (ip == (uint32)-1 || chr->server[i].ip == ip)
- && (port == (uint16)-1 || chr->server[i].port == port))
- {
- for (j = 0; chr->server[i].map[j]; j++)
- if (chr->server[i].map[j] == map)
- return i;
+ && (port == (uint16)-1 || chr->server[i].port == port)
+ ) {
+ ARR_FIND(0, VECTOR_LENGTH(chr->server[i].maps), j, VECTOR_INDEX(chr->server[i].maps, j) == map);
+ if (j != VECTOR_LENGTH(chr->server[i].maps))
+ return i;
}
}
@@ -4577,7 +4578,7 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl)
}
#endif
- ARR_FIND( 0, ARRAYLENGTH(chr->server), server_id, chr->server[server_id].fd > 0 && chr->server[server_id].map );
+ ARR_FIND(0, ARRAYLENGTH(chr->server), server_id, chr->server[server_id].fd > 0 && VECTOR_LENGTH(chr->server[server_id].maps) > 0);
/* not available, tell it to wait (client wont close; char select will respawn).
* magic response found by Ind thanks to Yommy <3 */
if( server_id == ARRAYLENGTH(chr->server) ) {
@@ -4638,7 +4639,7 @@ void char_parse_char_select(int fd, struct char_session_data* sd, uint32 ipl)
if (i < 0 || !cd->last_point.map) {
unsigned short j;
//First check that there's actually a map server online.
- ARR_FIND( 0, ARRAYLENGTH(chr->server), j, chr->server[j].fd >= 0 && chr->server[j].map );
+ ARR_FIND(0, ARRAYLENGTH(chr->server), j, chr->server[j].fd >= 0 && VECTOR_LENGTH(chr->server[j].maps) > 0);
if (j == ARRAYLENGTH(chr->server)) {
ShowInfo("Connection Closed. No map servers available.\n");
chr->authfail_fd(fd, 1); // 1 = Server closed
@@ -5095,10 +5096,12 @@ int char_parse_char(int fd)
//For use in packets that depend on an sd being present [Skotlex]
#define FIFOSD_CHECK(rest) do { if(RFIFOREST(fd) < (rest)) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,(rest)); return 0; } } while (0)
- if( HPM->packetsc[hpParse_Char] ) {
- int success = HPM->parse_packets(fd,hpParse_Char);
- if( success == 1 ) continue;
- else if( success == 2 ) return 0;
+ if (VECTOR_LENGTH(HPM->packets[hpParse_Char]) > 0) {
+ int result = HPM->parse_packets(fd,hpParse_Char);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
cmd = RFIFOW(fd,0);
@@ -5785,9 +5788,8 @@ int do_final(void) {
SQL->Free(inter->sql_handle);
mapindex->final();
- for(i = 0; i < MAX_MAP_SERVERS; i++ )
- if( chr->server[i].map )
- aFree(chr->server[i].map);
+ for (i = 0; i < MAX_MAP_SERVERS; i++)
+ VECTOR_CLEAR(chr->server[i].maps);
aFree(chr->CHAR_CONF_NAME);
aFree(chr->NET_CONF_NAME);
@@ -5886,8 +5888,8 @@ int do_init(int argc, char **argv) {
chr->SQL_CONF_NAME = aStrdup("conf/inter-server.conf");
chr->INTER_CONF_NAME = aStrdup("conf/inter-server.conf");
- for(i = 0; i < MAX_MAP_SERVERS; i++ )
- chr->server[i].map = NULL;
+ for (i = 0; i < MAX_MAP_SERVERS; i++)
+ VECTOR_INIT(chr->server[i].maps);
HPM_char_do_init();
cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT);
diff --git a/src/char/char.h b/src/char/char.h
index e79cc1898..fe6c0b9da 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -49,8 +49,7 @@ struct mmo_map_server {
uint32 ip;
uint16 port;
int users;
- unsigned short *map;
- unsigned short maps;
+ VECTOR_DECL(uint16) maps;
};
#define MAX_MAP_SERVERS 2
diff --git a/src/char/loginif.c b/src/char/loginif.c
index 422c7c589..e99e05237 100644
--- a/src/char/loginif.c
+++ b/src/char/loginif.c
@@ -63,8 +63,8 @@ void loginif_on_ready(void)
chr->send_accounts_tologin(INVALID_TIMER, timer->gettick(), 0, 0);
// if no map-server already connected, display a message...
- ARR_FIND( 0, ARRAYLENGTH(chr->server), i, chr->server[i].fd > 0 && chr->server[i].map );
- if( i == ARRAYLENGTH(chr->server) )
+ ARR_FIND(0, ARRAYLENGTH(chr->server), i, chr->server[i].fd > 0 && VECTOR_LENGTH(chr->server[i].maps));
+ if (i == ARRAYLENGTH(chr->server))
ShowStatus("Awaiting maps from map-server.\n");
}
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 0316f9494..578e90bbc 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -43,28 +43,52 @@ DBMap *datacheck_db;
int datacheck_version;
const struct s_HPMDataCheck *datacheck_data;
-void hplugin_trigger_event(enum hp_event_types type) {
- unsigned int i;
- for( i = 0; i < HPM->plugin_count; i++ ) {
- if( HPM->plugins[i]->hpi->event[type] != NULL )
- (HPM->plugins[i]->hpi->event[type])();
+/**
+ * Executes an event on all loaded plugins.
+ *
+ * @param type The event type to trigger.
+ */
+void hplugin_trigger_event(enum hp_event_types type)
+{
+ int i;
+ for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) {
+ struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i);
+ if (plugin->hpi->event[type] != NULL)
+ plugin->hpi->event[type]();
}
}
-void hplugin_export_symbol(void *var, char *name) {
- RECREATE(HPM->symbols, struct hpm_symbol *, ++HPM->symbol_count);
- CREATE(HPM->symbols[HPM->symbol_count - 1] ,struct hpm_symbol, 1);
- HPM->symbols[HPM->symbol_count - 1]->name = name;
- HPM->symbols[HPM->symbol_count - 1]->ptr = var;
+/**
+ * Exports a symbol to the shared symbols list.
+ *
+ * @param value The symbol value.
+ * @param name The symbol name.
+ */
+void hplugin_export_symbol(void *value, const char *name)
+{
+ struct hpm_symbol *symbol = NULL;
+ CREATE(symbol ,struct hpm_symbol, 1);
+ symbol->name = name;
+ symbol->ptr = value;
+ VECTOR_ENSURE(HPM->symbols, 1, 1);
+ VECTOR_PUSH(HPM->symbols, symbol);
}
-void *hplugin_import_symbol(char *name, unsigned int pID) {
- unsigned int i;
+/**
+ * Imports a shared symbol.
+ *
+ * @param name The symbol name.
+ * @param pID The requesting plugin ID.
+ * @return The symbol value.
+ * @retval NULL if the symbol wasn't found.
+ */
+void *hplugin_import_symbol(char *name, unsigned int pID)
+{
+ int i;
+ ARR_FIND(0, VECTOR_LENGTH(HPM->symbols), i, strcmp(VECTOR_INDEX(HPM->symbols, i)->name, name) == 0);
- for( i = 0; i < HPM->symbol_count; i++ ) {
- if( strcmp(HPM->symbols[i]->name,name) == 0 )
- return HPM->symbols[i]->ptr;
- }
+ if (i != VECTOR_LENGTH(HPM->symbols))
+ return VECTOR_INDEX(HPM->symbols, i)->ptr;
ShowError("HPM:get_symbol:%s: '"CL_WHITE"%s"CL_RESET"' not found!\n",HPM->pid2name(pID),name);
return NULL;
@@ -81,40 +105,60 @@ bool hplugin_iscompatible(char* version) {
return ( req_major == HPM->version[0] && req_minor <= HPM->version[1] ) ? true : false;
}
-bool hplugin_exists(const char *filename) {
- unsigned int i;
- for(i = 0; i < HPM->plugin_count; i++) {
- if( strcmpi(HPM->plugins[i]->filename,filename) == 0 )
+/**
+ * Checks whether a plugin is currently loaded
+ *
+ * @param filename The plugin filename.
+ * @retval true if the plugin exists and is currently loaded.
+ * @retval false otherwise.
+ */
+bool hplugin_exists(const char *filename)
+{
+ int i;
+ for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) {
+ if (strcmpi(VECTOR_INDEX(HPM->plugins, i)->filename,filename) == 0)
return true;
}
return false;
}
-struct hplugin *hplugin_create(void) {
- RECREATE(HPM->plugins, struct hplugin *, ++HPM->plugin_count);
- CREATE(HPM->plugins[HPM->plugin_count - 1], struct hplugin, 1);
- HPM->plugins[HPM->plugin_count - 1]->idx = HPM->plugin_count - 1;
- HPM->plugins[HPM->plugin_count - 1]->filename = NULL;
- return HPM->plugins[HPM->plugin_count - 1];
+
+/**
+ * Initializes the data structure for a new plugin and registers it.
+ *
+ * @return A (retained) pointer to the initialized data.
+ */
+struct hplugin *hplugin_create(void)
+{
+ struct hplugin *plugin = NULL;
+ CREATE(plugin, struct hplugin, 1);
+ plugin->idx = (int)VECTOR_LENGTH(HPM->plugins);
+ plugin->filename = NULL;
+ VECTOR_ENSURE(HPM->plugins, 1, 1);
+ VECTOR_PUSH(HPM->plugins, plugin);
+ return plugin;
}
-bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receive) (int fd), unsigned int point,unsigned int pluginID) {
+bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receive) (int fd), unsigned int point, unsigned int pluginID)
+{
struct HPluginPacket *packet;
- unsigned int i;
+ int i;
- if( point >= hpPHP_MAX ) {
+ if (point >= hpPHP_MAX) {
ShowError("HPM->addPacket:%s: unknown point '%u' specified for packet 0x%04x (len %d)\n",HPM->pid2name(pluginID),point,cmd,length);
return false;
}
- for(i = 0; i < HPM->packetsc[point]; i++) {
- if( HPM->packets[point][i].cmd == cmd ) {
- ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!",HPM->pid2name(pluginID),cmd,HPM->pid2name(HPM->packets[point][i].pluginID));
+ for (i = 0; i < VECTOR_LENGTH(HPM->packets[point]); i++) {
+ if (VECTOR_INDEX(HPM->packets[point], i).cmd == cmd ) {
+ ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!",
+ HPM->pid2name(pluginID), cmd, HPM->pid2name(VECTOR_INDEX(HPM->packets[point], i).pluginID));
return false;
}
}
- RECREATE(HPM->packets[point], struct HPluginPacket, ++HPM->packetsc[point]);
- packet = &HPM->packets[point][HPM->packetsc[point] - 1];
+ VECTOR_ENSURE(HPM->packets[point], 1, 1);
+ VECTOR_PUSHZEROED(HPM->packets[point]);
+ packet = &VECTOR_LAST(HPM->packets[point]);
packet->pluginID = pluginID;
packet->cmd = cmd;
@@ -124,136 +168,158 @@ bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receiv
return true;
}
-void hplugins_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr)
+/**
+ * Validates and if necessary initializes a plugin data store.
+ *
+ * @param type[in] The data store type.
+ * @param storeptr[in,out] A pointer to the store.
+ * @param initialize Whether the store should be initialized in case it isn't.
+ * @retval false if the store is an invalid or mismatching type.
+ * @retval true if the store is a valid type.
+ *
+ * @remark
+ * If \c storeptr is a pointer to a NULL pointer (\c storeptr itself can't
+ * be NULL), two things may happen, depending on the \c initialize value:
+ * if false, then \c storeptr isn't changed; if true, then \c storeptr is
+ * initialized through \c HPM->data_store_create() and ownership is passed
+ * to the caller.
+ */
+bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize)
{
- /* record address */
+ struct hplugin_data_store *store;
+ nullpo_retr(false, storeptr);
+ store = *storeptr;
+ if (!initialize && store == NULL)
+ return true;
+
switch (type) {
/* core-handled */
case HPDT_SESSION:
- ret->HPDataSRCPtr = (void**)(&((struct socket_data *)ptr)->hdata);
- ret->hdatac = &((struct socket_data *)ptr)->hdatac;
break;
- /* goes to sub */
default:
- if (HPM->grabHPDataSub) {
- if (HPM->grabHPDataSub(ret,type,ptr))
- return;
- ShowError("HPM:HPM:grabHPData failed, unknown type %d!\n",type);
- } else {
- ShowError("HPM:grabHPData failed, type %d needs sub-handler!\n",type);
+ if (HPM->data_store_validate_sub == NULL) {
+ ShowError("HPM:validateHPData failed, type %d needs sub-handler!\n",type);
+ return false;
+ }
+ if (!HPM->data_store_validate_sub(type, storeptr, initialize)) {
+ ShowError("HPM:HPM:validateHPData failed, unknown type %d!\n",type);
+ return false;
}
- ret->HPDataSRCPtr = NULL;
- ret->hdatac = NULL;
- return;
+ break;
+ }
+ if (initialize && (!store || store->type == HPDT_UNKNOWN)) {
+ HPM->data_store_create(storeptr, type);
+ store = *storeptr;
}
+ if (store->type != type) {
+ ShowError("HPM:HPM:validateHPData failed, store type mismatch %d != %d.\n",store->type, type);
+ return false;
+ }
+ return true;
}
-void hplugins_addToHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, void *data, unsigned int index, bool autofree)
+/**
+ * Adds an entry to a plugin data store.
+ *
+ * @param type[in] The store type.
+ * @param pluginID[in] The plugin identifier.
+ * @param storeptr[in,out] A pointer to the store. The store will be initialized if necessary.
+ * @param data[in] The data entry to add.
+ * @param classid[in] The entry class identifier.
+ * @param autofree[in] Whether the entry should be automatically freed when removed.
+ */
+void hplugins_addToHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store **storeptr, void *data, uint32 classid, bool autofree)
{
- struct HPluginData *HPData, **HPDataSRC;
- struct HPDataOperationStorage action;
- unsigned int i, max;
-
- HPM->grabHPData(&action,type,ptr);
+ struct hplugin_data_store *store;
+ struct hplugin_data_entry *entry;
+ int i;
+ nullpo_retv(storeptr);
- if (action.hdatac == NULL) { /* woo it failed! */
- ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index);
+ if (!HPM->data_store_validate(type, storeptr, true)) {
+ /* woo it failed! */
+ ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
return;
}
-
- /* flag */
- HPDataSRC = *(action.HPDataSRCPtr);
- max = *(action.hdatac);
+ store = *storeptr;
/* duplicate check */
- for (i = 0; i < max; i++) {
- if (HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index) {
- ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and index %u\n",HPM->pid2name(pluginID),pluginID,index);
- return;
- }
+ ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid);
+ if (i != VECTOR_LENGTH(store->entries)) {
+ ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and classid %u\n", HPM->pid2name(pluginID), pluginID, classid);
+ return;
}
- /* HPluginData is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */
- CREATE(HPData, struct HPluginData, 1);
+ /* hplugin_data_entry is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */
+ CREATE(entry, struct hplugin_data_entry, 1);
/* input */
- HPData->pluginID = pluginID;
- HPData->type = index;
- HPData->flag.free = autofree ? 1 : 0;
- HPData->data = data;
-
- /* resize */
- *(action.hdatac) += 1;
- RECREATE(*(action.HPDataSRCPtr),struct HPluginData *,*(action.hdatac));
+ entry->pluginID = pluginID;
+ entry->classid = classid;
+ entry->flag.free = autofree ? 1 : 0;
+ entry->data = data;
- /* RECREATE modified the address */
- HPDataSRC = *(action.HPDataSRCPtr);
- HPDataSRC[*(action.hdatac) - 1] = HPData;
+ VECTOR_ENSURE(store->entries, 1, 1);
+ VECTOR_PUSH(store->entries, entry);
}
-void *hplugins_getFromHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index)
+/**
+ * Retrieves an entry from a plugin data store.
+ *
+ * @param type[in] The store type.
+ * @param pluginID[in] The plugin identifier.
+ * @param store[in] The store.
+ * @param classid[in] The entry class identifier.
+ *
+ * @return The retrieved entry, or NULL.
+ */
+void *hplugins_getFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid)
{
- struct HPDataOperationStorage action;
- struct HPluginData **HPDataSRC;
- unsigned int i, max;
-
- HPM->grabHPData(&action,type,ptr);
+ int i;
- if (action.hdatac == NULL) { /* woo it failed! */
- ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index);
+ if (!HPM->data_store_validate(type, &store, false)) {
+ /* woo it failed! */
+ ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
return NULL;
}
+ if (!store)
+ return NULL;
- /* flag */
- HPDataSRC = *(action.HPDataSRCPtr);
- max = *(action.hdatac);
-
- for (i = 0; i < max; i++) {
- if (HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index)
- return HPDataSRC[i]->data;
- }
+ ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid);
+ if (i != VECTOR_LENGTH(store->entries))
+ return VECTOR_INDEX(store->entries, i)->data;
return NULL;
}
-void hplugins_removeFromHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index)
+/**
+ * Removes an entry from a plugin data store.
+ *
+ * @param type[in] The store type.
+ * @param pluginID[in] The plugin identifier.
+ * @param store[in] The store.
+ * @param classid[in] The entry class identifier.
+ */
+void hplugins_removeFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid)
{
- struct HPDataOperationStorage action;
- struct HPluginData **HPDataSRC;
- unsigned int i, max;
-
- HPM->grabHPData(&action,type,ptr);
+ struct hplugin_data_entry *entry;
+ int i;
- if (action.hdatac == NULL) { /* woo it failed! */
- ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index);
+ if (!HPM->data_store_validate(type, &store, false)) {
+ /* woo it failed! */
+ ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid);
return;
}
+ if (!store)
+ return;
- /* flag */
- HPDataSRC = *(action.HPDataSRCPtr);
- max = *(action.hdatac);
-
- for (i = 0; i < max; i++) {
- if (HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index)
- break;
- }
-
- if (i != max) {
- unsigned int cursor;
-
- aFree(HPDataSRC[i]->data);/* when its removed we delete it regardless of autofree */
- aFree(HPDataSRC[i]);
- HPDataSRC[i] = NULL;
+ ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid);
+ if (i == VECTOR_LENGTH(store->entries))
+ return;
- for (i = 0, cursor = 0; i < max; i++) {
- if (HPDataSRC[i] == NULL)
- continue;
- if (i != cursor)
- HPDataSRC[cursor] = HPDataSRC[i];
- cursor++;
- }
- *(action.hdatac) = cursor;
- }
+ entry = VECTOR_INDEX(store->entries, i);
+ VECTOR_ERASE(store->entries, i); // Erase and compact
+ aFree(entry->data); // when it's removed we delete it regardless of autofree
+ aFree(entry);
}
/* TODO: add ability for tracking using pID for the upcoming runtime load/unload support. */
@@ -303,9 +369,9 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF
return false;
}
- ARR_FIND(0, cmdline->args_data_count, i, strcmp(cmdline->args_data[i].name, name) == 0);
+ ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), i, strcmp(VECTOR_INDEX(cmdline->args_data, i).name, name) == 0);
- if (i < cmdline->args_data_count) {
+ if (i != VECTOR_LENGTH(cmdline->args_data)) {
ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID));
return false;
}
@@ -313,25 +379,36 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF
return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL);
}
+/**
+ * Adds a configuration listener for a plugin.
+ *
+ * @param pluginID The plugin identifier.
+ * @param type The configuration type to listen for.
+ * @param name The configuration entry name.
+ * @param func The callback function.
+ * @retval true if the listener was added successfully.
+ * @retval false in case of error.
+ */
bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val))
{
struct HPConfListenStorage *conf;
- unsigned int i;
+ int i;
if (type >= HPCT_MAX) {
ShowError("HPM->addConf:%s: unknown point '%u' specified for config '%s'\n",HPM->pid2name(pluginID),type,name);
return false;
}
- for (i = 0; i < HPM->confsc[type]; i++) {
- if (!strcmpi(name,HPM->confs[type][i].key)) {
- ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!",HPM->pid2name(pluginID),name,HPM->pid2name(HPM->confs[type][i].pluginID));
- return false;
- }
+ ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[type]), i, strcmpi(name, VECTOR_INDEX(HPM->config_listeners[type], i).key) == 0);
+ if (i != VECTOR_LENGTH(HPM->config_listeners[type])) {
+ ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!",
+ HPM->pid2name(pluginID), name, HPM->pid2name(VECTOR_INDEX(HPM->config_listeners[type], i).pluginID));
+ return false;
}
- RECREATE(HPM->confs[type], struct HPConfListenStorage, ++HPM->confsc[type]);
- conf = &HPM->confs[type][HPM->confsc[type] - 1];
+ VECTOR_ENSURE(HPM->config_listeners[type], 1, 1);
+ VECTOR_PUSHZEROED(HPM->config_listeners[type]);
+ conf = &VECTOR_LAST(HPM->config_listeners[type]);
conf->pluginID = pluginID;
safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH);
@@ -477,30 +554,23 @@ struct hplugin *hplugin_load(const char* filename) {
return plugin;
}
+/**
+ * Unloads and unregisters a plugin.
+ *
+ * @param plugin The plugin data.
+ */
void hplugin_unload(struct hplugin* plugin)
{
+ int i;
if (plugin->filename)
aFree(plugin->filename);
if (plugin->dll)
plugin_close(plugin->dll);
/* TODO: for manual packet unload */
/* - Go through known packets and unlink any belonging to the plugin being removed */
- if (!HPM->off) {
- unsigned int i, cursor;
- for (cursor = 0; cursor < HPM->plugin_count; cursor++) {
- if (HPM->plugins[cursor]->idx != plugin->idx)
- continue;
- HPM->plugins[cursor] = NULL;
- break;
- }
- for(i = cursor + 1; i < HPM->plugin_count; i++) {
- HPM->plugins[cursor] = HPM->plugins[i];
- cursor++;
- }
- if (!(HPM->plugin_count = cursor)) {
- aFree(HPM->plugins);
- HPM->plugins = NULL;
- }
+ ARR_FIND(0, VECTOR_LENGTH(HPM->plugins), i, VECTOR_INDEX(HPM->plugins, i)->idx == plugin->idx);
+ if (i != VECTOR_LENGTH(HPM->plugins)) {
+ VECTOR_ERASE(HPM->plugins, i);
}
aFree(plugin);
}
@@ -510,8 +580,8 @@ void hplugin_unload(struct hplugin* plugin)
*/
CMDLINEARG(loadplugin)
{
- RECREATE(HPM->cmdline_plugins, char *, ++HPM->cmdline_plugins_count);
- HPM->cmdline_plugins[HPM->cmdline_plugins_count-1] = aStrdup(params);
+ VECTOR_ENSURE(HPM->cmdline_load_plugins, 1, 1);
+ VECTOR_PUSH(HPM->cmdline_load_plugins, aStrdup(params));
return true;
}
@@ -535,9 +605,9 @@ void hplugins_config_read(void) {
return;
plist = libconfig->lookup(&plugins_conf, "plugins_list");
- for (i = 0; i < HPM->cmdline_plugins_count; i++) {
+ for (i = 0; i < VECTOR_LENGTH(HPM->cmdline_load_plugins); i++) {
config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
- config_setting_set_string(entry, HPM->cmdline_plugins[i]);
+ config_setting_set_string(entry, VECTOR_INDEX(HPM->cmdline_load_plugins, i));
}
if (plist != NULL) {
@@ -584,83 +654,117 @@ void hplugins_config_read(void) {
}
libconfig->destroy(&plugins_conf);
- if( HPM->plugin_count )
- ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", HPM->plugin_count);
+ if (VECTOR_LENGTH(HPM->plugins))
+ ShowStatus("HPM: There are '"CL_WHITE"%"PRIuS""CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", VECTOR_LENGTH(HPM->plugins));
}
-CPCMD(plugins) {
- if( HPM->plugin_count == 0 ) {
+
+/**
+ * Console command: plugins
+ *
+ * Shows a list of loaded plugins.
+ *
+ * @see CPCMD()
+ */
+CPCMD(plugins)
+{
+ int i;
+
+ if (VECTOR_LENGTH(HPM->plugins) == 0) {
ShowInfo("HPC: there are no plugins loaded\n");
- } else {
- unsigned int i;
+ return;
+ }
- ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count);
+ ShowInfo("HPC: There are '"CL_WHITE"%"PRIuS""CL_RESET"' plugins loaded\n", VECTOR_LENGTH(HPM->plugins));
- for(i = 0; i < HPM->plugin_count; i++) {
- ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename);
- }
+ for(i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) {
+ struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i);
+ ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n", plugin->info->name, plugin->filename);
}
}
-/*
- 0 = unknown
- 1 = OK
- 2 = incomplete
+/**
+ * Parses a packet through the registered plugin.
+ *
+ * @param fd The connection fd.
+ * @param point The packet hooking point.
+ * @retval 0 unknown packet
+ * @retval 1 OK
+ * @retval 2 incomplete packet
*/
-unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) {
- unsigned int i;
+unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point)
+{
+ struct HPluginPacket *packet = NULL;
+ int i;
+ int16 length;
- for(i = 0; i < HPM->packetsc[point]; i++) {
- if( HPM->packets[point][i].cmd == RFIFOW(fd,0) )
- break;
- }
+ ARR_FIND(0, VECTOR_LENGTH(HPM->packets[point]), i, VECTOR_INDEX(HPM->packets[point], i).cmd == RFIFOW(fd,0));
- if( i != HPM->packetsc[point] ) {
- struct HPluginPacket *packet = &HPM->packets[point][i];
- short length;
+ if (i == VECTOR_LENGTH(HPM->packets[point]))
+ return 0;
- if( (length = packet->len) == -1 ) {
- if( (length = RFIFOW(fd, 2)) > (int)RFIFOREST(fd) )
- return 2;
- }
+ packet = &VECTOR_INDEX(HPM->packets[point], i);
+ length = packet->len;
+ if (length == -1)
+ length = RFIFOW(fd, 2);
- packet->receive(fd);
- RFIFOSKIP(fd, length);
- return 1;
- }
+ if (length > (int)RFIFOREST(fd))
+ return 2;
- return 0;
+ packet->receive(fd);
+ RFIFOSKIP(fd, length);
+ return 1;
}
-char *hplugins_id2name (unsigned int pid) {
- unsigned int i;
+/**
+ * Retrieves a plugin name by ID.
+ *
+ * @param pid The plugin identifier.
+ * @return The plugin name.
+ * @retval "core" if the plugin ID belongs to the Hercules core.
+ * @retval "UnknownPlugin" if the plugin wasn't found.
+ */
+char *hplugins_id2name(unsigned int pid)
+{
+ int i;
if (pid == HPM_PID_CORE)
return "core";
- for( i = 0; i < HPM->plugin_count; i++ ) {
- if( HPM->plugins[i]->idx == pid )
- return HPM->plugins[i]->info->name;
+ for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) {
+ struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i);
+ if (plugin->idx == pid)
+ return plugin->info->name;
}
return "UnknownPlugin";
}
-char* HPM_file2ptr(const char *file) {
- unsigned int i;
- for(i = 0; i < HPM->fnamec; i++) {
- if( HPM->fnames[i].addr == file )
- return HPM->fnames[i].name;
- }
+/**
+ * Returns a retained permanent pointer to a source filename, for memory-manager reporting use.
+ *
+ * The returned pointer is safe to be used as filename in the memory manager
+ * functions, and it will be available during and after the memory manager
+ * shutdown (for memory leak reporting purposes).
+ *
+ * @param file The string/filename to retain
+ * @return A retained copy of the source string.
+ */
+const char *HPM_file2ptr(const char *file)
+{
+ int i;
- i = HPM->fnamec;
+ ARR_FIND(0, HPM->filenames.count, i, HPM->filenames.data[i].addr == file);
+ if (i != HPM->filenames.count) {
+ return HPM->filenames.data[i].name;
+ }
/* we handle this memory outside of the server's memory manager because we need it to exist after the memory manager goes down */
- HPM->fnames = realloc(HPM->fnames,(++HPM->fnamec)*sizeof(struct HPMFileNameCache));
+ HPM->filenames.data = realloc(HPM->filenames.data, (++HPM->filenames.count)*sizeof(struct HPMFileNameCache));
- HPM->fnames[i].addr = file;
- HPM->fnames[i].name = strdup(file);
+ HPM->filenames.data[i].addr = file;
+ HPM->filenames.data[i].name = strdup(file);
- return HPM->fnames[i].name;
+ return HPM->filenames.data[i].name;
}
void* HPM_mmalloc(size_t size, const char *file, int line, const char *func) {
return iMalloc->malloc(size,HPM_file2ptr(file),line,func);
@@ -678,22 +782,74 @@ char* HPM_astrdup(const char *p, const char *file, int line, const char *func) {
return iMalloc->astrdup(p,HPM_file2ptr(file),line,func);
}
-bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point) {
- unsigned int i;
+/**
+ * Parses a configuration entry through the registered plugins.
+ *
+ * @param w1 The configuration entry name.
+ * @param w2 The configuration entry value.
+ * @param point The type of configuration file.
+ * @retval true if a registered plugin was found to handle the entry.
+ * @retval false if no registered plugins could be found.
+ */
+bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point)
+{
+ int i;
+ ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[point]), i, strcmpi(w1, VECTOR_INDEX(HPM->config_listeners[point], i).key) == 0);
+ if (i == VECTOR_LENGTH(HPM->config_listeners[point]))
+ return false;
- /* exists? */
- for(i = 0; i < HPM->confsc[point]; i++) {
- if( !strcmpi(w1,HPM->confs[point][i].key) )
- break;
+ VECTOR_INDEX(HPM->config_listeners[point], i).func(w2);
+ return true;
+}
+
+/**
+ * Helper to destroy an interface's hplugin_data store and release any owned memory.
+ *
+ * The pointer will be cleared.
+ *
+ * @param storeptr[in,out] A pointer to the plugin data store.
+ */
+void hplugin_data_store_destroy(struct hplugin_data_store **storeptr)
+{
+ struct hplugin_data_store *store;
+ nullpo_retv(storeptr);
+ store = *storeptr;
+ if (store == NULL)
+ return;
+
+ while (VECTOR_LENGTH(store->entries) > 0) {
+ struct hplugin_data_entry *entry = VECTOR_POP(store->entries);
+ if (entry->flag.free) {
+ aFree(entry->data);
+ }
+ aFree(entry);
}
+ VECTOR_CLEAR(store->entries);
+ aFree(store);
+ *storeptr = NULL;
+}
- /* trigger and we're set! */
- if( i != HPM->confsc[point] ) {
- HPM->confs[point][i].func(w2);
- return true;
+/**
+ * Helper to create and initialize an interface's hplugin_data store.
+ *
+ * The store is owned by the caller, and it should be eventually destroyed by
+ * \c hdata_destroy.
+ *
+ * @param storeptr[in,out] A pointer to the data store to initialize.
+ * @param type[in] The store type.
+ */
+void hplugin_data_store_create(struct hplugin_data_store **storeptr, enum HPluginDataTypes type)
+{
+ struct hplugin_data_store *store;
+ nullpo_retv(storeptr);
+
+ if (*storeptr == NULL) {
+ CREATE(*storeptr, struct hplugin_data_store, 1);
}
+ store = *storeptr;
- return false;
+ store->type = type;
+ VECTOR_INIT(store->entries);
}
/**
@@ -747,14 +903,14 @@ void HPM_datacheck_final(void) {
}
void hpm_init(void) {
- unsigned int i;
+ int i;
datacheck_db = NULL;
datacheck_data = NULL;
datacheck_version = 0;
- HPM->symbols = NULL;
- HPM->plugins = NULL;
- HPM->plugin_count = HPM->symbol_count = 0;
+ VECTOR_INIT(HPM->plugins);
+ VECTOR_INIT(HPM->symbols);
+
HPM->off = false;
memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface));
@@ -772,9 +928,12 @@ void hpm_init(void) {
return;
}
- for(i = 0; i < hpPHP_MAX; i++) {
- HPM->packets[i] = NULL;
- HPM->packetsc[i] = 0;
+ for (i = 0; i < hpPHP_MAX; i++) {
+ VECTOR_INIT(HPM->packets[i]);
+ }
+
+ for (i = 0; i < HPCT_MAX; i++) {
+ VECTOR_INIT(HPM->config_listeners[i]);
}
#ifdef CONSOLE_INPUT
@@ -782,84 +941,68 @@ void hpm_init(void) {
#endif
return;
}
+
+/**
+ * Releases the retained filenames cache.
+ */
void hpm_memdown(void)
{
- /* this memory is handled outside of the server's memory manager and thus cleared after memory manager goes down */
-
- if (HPM->fnames) {
- unsigned int i;
- for (i = 0; i < HPM->fnamec; i++) {
- free(HPM->fnames[i].name);
+ /* this memory is handled outside of the server's memory manager and
+ * thus cleared after memory manager goes down */
+ if (HPM->filenames.count) {
+ int i;
+ for (i = 0; i < HPM->filenames.count; i++) {
+ free(HPM->filenames.data[i].name);
}
- free(HPM->fnames);
+ free(HPM->filenames.data);
+ HPM->filenames.data = NULL;
+ HPM->filenames.count = 0;
}
}
-void hpm_final(void) {
- unsigned int i;
+
+void hpm_final(void)
+{
+ int i;
HPM->off = true;
- if( HPM->plugins )
- {
- for( i = 0; i < HPM->plugin_count; i++ ) {
- HPM->unload(HPM->plugins[i]);
- }
- aFree(HPM->plugins);
+ while (VECTOR_LENGTH(HPM->plugins)) {
+ HPM->unload(VECTOR_LAST(HPM->plugins));
}
+ VECTOR_CLEAR(HPM->plugins);
- if( HPM->symbols )
- {
- for( i = 0; i < HPM->symbol_count; i++ ) {
- aFree(HPM->symbols[i]);
- }
- aFree(HPM->symbols);
+ while (VECTOR_LENGTH(HPM->symbols)) {
+ aFree(VECTOR_POP(HPM->symbols));
}
+ VECTOR_CLEAR(HPM->symbols);
- for( i = 0; i < hpPHP_MAX; i++ ) {
- if( HPM->packets[i] )
- aFree(HPM->packets[i]);
+ for (i = 0; i < hpPHP_MAX; i++) {
+ VECTOR_CLEAR(HPM->packets[i]);
}
- for( i = 0; i < HPCT_MAX; i++ ) {
- if( HPM->confsc[i] )
- aFree(HPM->confs[i]);
+ for (i = 0; i < HPCT_MAX; i++) {
+ VECTOR_CLEAR(HPM->config_listeners[i]);
}
- if (HPM->cmdline_plugins) {
- int j;
- for (j = 0; j < HPM->cmdline_plugins_count; j++)
- aFree(HPM->cmdline_plugins[j]);
- aFree(HPM->cmdline_plugins);
- HPM->cmdline_plugins = NULL;
- HPM->cmdline_plugins_count = 0;
+
+ while (VECTOR_LENGTH(HPM->cmdline_load_plugins)) {
+ aFree(VECTOR_POP(HPM->cmdline_load_plugins));
}
+ VECTOR_CLEAR(HPM->cmdline_load_plugins);
/* HPM->fnames is cleared after the memory manager goes down */
iMalloc->post_shutdown = hpm_memdown;
return;
}
-void hpm_defaults(void) {
- unsigned int i;
+void hpm_defaults(void)
+{
HPM = &HPM_s;
- HPM->fnames = NULL;
- HPM->fnamec = 0;
+ memset(&HPM->filenames, 0, sizeof(HPM->filenames));
+ VECTOR_INIT(HPM->cmdline_load_plugins);
HPM->force_return = false;
HPM->hooking = false;
/* */
- HPM->fnames = NULL;
- HPM->fnamec = 0;
- for(i = 0; i < hpPHP_MAX; i++) {
- HPM->packets[i] = NULL;
- HPM->packetsc[i] = 0;
- }
- for(i = 0; i < HPCT_MAX; i++) {
- HPM->confs[i] = NULL;
- HPM->confsc[i] = 0;
- }
- HPM->cmdline_plugins = NULL;
- HPM->cmdline_plugins_count = 0;
- /* */
HPM->init = hpm_init;
HPM->final = hpm_final;
@@ -876,10 +1019,13 @@ void hpm_defaults(void) {
HPM->parse_packets = hplugins_parse_packets;
HPM->load_sub = NULL;
HPM->addhook_sub = NULL;
- HPM->grabHPData = hplugins_grabHPData;
- HPM->grabHPDataSub = NULL;
HPM->parseConf = hplugins_parse_conf;
HPM->DataCheck = HPM_DataCheck;
HPM->datacheck_init = HPM_datacheck_init;
HPM->datacheck_final = HPM_datacheck_final;
+
+ HPM->data_store_destroy = hplugin_data_store_destroy;
+ HPM->data_store_create = hplugin_data_store_create;
+ HPM->data_store_validate = hplugin_data_store_validate;
+ HPM->data_store_validate_sub = NULL;
}
diff --git a/src/common/HPM.h b/src/common/HPM.h
index c13132cfc..5420e5300 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -9,6 +9,7 @@
#endif
#include "common/hercules.h"
+#include "common/db.h"
#include "common/HPMi.h"
#ifdef WIN32
@@ -56,18 +57,32 @@ struct hplugin {
struct HPMi_interface *hpi;
};
+/**
+ * Symbols shared between core and plugins.
+ */
struct hpm_symbol {
- char *name;
- void *ptr;
+ const char *name; ///< The symbol name
+ void *ptr; ///< The symbol value
};
-struct HPluginData {
- unsigned int pluginID;
- unsigned int type;
+/**
+ * A plugin custom data, to be injected in various interfaces and objects.
+ */
+struct hplugin_data_entry {
+ uint32 pluginID; ///< The owner plugin identifier.
+ uint32 classid; ///< The entry's object type, managed by the plugin (for plugins that need more than one entry).
struct {
- unsigned int free : 1;
+ unsigned int free : 1; ///< Whether the entry data should be automatically cleared by the HPM.
} flag;
- void *data;
+ void *data; ///< The entry data.
+};
+
+/**
+ * A store for plugin custom data entries.
+ */
+struct hplugin_data_store {
+ enum HPluginDataTypes type; ///< The store type.
+ VECTOR_DECL(struct hplugin_data_entry *) entries; ///< The store entries.
};
struct HPluginPacket {
@@ -82,10 +97,6 @@ struct HPMFileNameCache {
char *name;
};
-struct HPDataOperationStorage {
- void **HPDataSRCPtr;
- unsigned int *hdatac;
-};
/* */
struct HPConfListenStorage {
unsigned int pluginID;
@@ -102,22 +113,20 @@ struct HPM_interface {
/* hooking */
bool force_return;
/* data */
- struct hplugin **plugins;
- unsigned int plugin_count;
- struct hpm_symbol **symbols;
- unsigned int symbol_count;
+ VECTOR_DECL(struct hplugin *) plugins;
+ VECTOR_DECL(struct hpm_symbol *) symbols;
/* packet hooking points */
- struct HPluginPacket *packets[hpPHP_MAX];
- unsigned int packetsc[hpPHP_MAX];
+ VECTOR_DECL(struct HPluginPacket) packets[hpPHP_MAX];
/* plugin file ptr caching */
- struct HPMFileNameCache *fnames;
- unsigned int fnamec;
+ struct {
+ // This doesn't use a VECTOR because it needs to exist after the memory manager goes down.
+ int count;
+ struct HPMFileNameCache *data;
+ } filenames;
/* config listen */
- struct HPConfListenStorage *confs[HPCT_MAX];
- unsigned int confsc[HPCT_MAX];
+ VECTOR_DECL(struct HPConfListenStorage) config_listeners[HPCT_MAX];
/** Plugins requested through the command line */
- char **cmdline_plugins;
- int cmdline_plugins_count;
+ VECTOR_DECL(char *) cmdline_load_plugins;
/* funcs */
void (*init) (void);
void (*final) (void);
@@ -128,21 +137,24 @@ struct HPM_interface {
bool (*iscompatible) (char* version);
void (*event) (enum hp_event_types type);
void *(*import_symbol) (char *name, unsigned int pID);
- void (*share) (void *, char *);
+ void (*share) (void *value, const char *name);
void (*config_read) (void);
char *(*pid2name) (unsigned int pid);
unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point);
void (*load_sub) (struct hplugin *plugin);
bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
- void (*grabHPData) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
- /* for server-specific HPData e.g. map_session_data */
- bool (*grabHPDataSub) (struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
/* for custom config parsing */
bool (*parseConf) (const char *w1, const char *w2, enum HPluginConfType point);
/* validates plugin data */
bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, int version, char *name);
void (*datacheck_init) (const struct s_HPMDataCheck *src, unsigned int length, int version);
void (*datacheck_final) (void);
+
+ void (*data_store_create) (struct hplugin_data_store **storeptr, enum HPluginDataTypes type);
+ void (*data_store_destroy) (struct hplugin_data_store **storeptr);
+ bool (*data_store_validate) (enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize);
+ /* for server-specific HPData e.g. map_session_data */
+ bool (*data_store_validate_sub) (enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize);
};
CMDLINEARG(loadplugin);
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index 4fd16114b..510ea9d4e 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -201,6 +201,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
#ifdef COMMON_SOCKET_H
{ "hSockOpt", sizeof(struct hSockOpt), SERVER_TYPE_ALL },
{ "s_subnet", sizeof(struct s_subnet), SERVER_TYPE_ALL },
+ { "s_subnet_vector", sizeof(struct s_subnet_vector), SERVER_TYPE_ALL },
{ "socket_data", sizeof(struct socket_data), SERVER_TYPE_ALL },
{ "socket_interface", sizeof(struct socket_interface), SERVER_TYPE_ALL },
#else
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
index e03f52e3b..9a61dd256 100644
--- a/src/common/HPMi.h
+++ b/src/common/HPMi.h
@@ -14,6 +14,7 @@ struct script_state;
struct AtCommandInfo;
struct socket_data;
struct map_session_data;
+struct hplugin_data_store;
#define HPM_VERSION "1.1"
#define HPM_ADDCONF_LENGTH 40
@@ -59,30 +60,34 @@ enum HPluginHookType {
HOOK_TYPE_POST,
};
+/**
+ * Data types for plugin custom data.
+ */
enum HPluginDataTypes {
- HPDT_SESSION,
- HPDT_MSD,
- HPDT_NPCD,
- HPDT_MAP,
- HPDT_INSTANCE,
- HPDT_GUILD,
- HPDT_PARTY,
- HPDT_MOBDB,
- HPDT_MOBDATA,
- HPDT_ITEMDATA,
- HPDT_BGDATA,
- HPDT_AUTOTRADE_VEND,
+ HPDT_UNKNOWN, ///< Unknown type (such as an uninitialized store).
+ HPDT_SESSION, ///< For struct socket_data.
+ HPDT_MSD, ///< For struct map_session_data.
+ HPDT_NPCD, ///< For struct npc_data.
+ HPDT_MAP, ///< For struct map_data.
+ HPDT_INSTANCE, ///< For struct instance_data.
+ HPDT_GUILD, ///< For struct guild.
+ HPDT_PARTY, ///< For struct party_data.
+ HPDT_MOBDB, ///< For struct mob_db.
+ HPDT_MOBDATA, ///< For struct mob_data.
+ HPDT_ITEMDATA, ///< For struct item_data.
+ HPDT_BGDATA, ///< For struct battleground_data.
+ HPDT_AUTOTRADE_VEND, ///< For struct autotrade_vending.
};
/* used in macros and conf storage */
enum HPluginConfType {
- HPCT_BATTLE, /* battle-conf (map-server) */
- HPCT_LOGIN, /* login-server.conf (login-server) */
- HPCT_CHAR, /* char-server.conf (char-server) */
- HPCT_CHAR_INTER, /* inter-server.conf (char-server) */
- HPCT_MAP_INTER, /* inter-server.conf (map-server) */
- HPCT_LOG, /* logs.conf (map-server) */
- HPCT_SCRIPT, /* script.conf (map-server) */
+ HPCT_BATTLE, ///< battle-conf (map-server)
+ HPCT_LOGIN, ///< login-server.conf (login-server)
+ HPCT_CHAR, ///< char-server.conf (char-server)
+ HPCT_CHAR_INTER, ///< inter-server.conf (char-server)
+ HPCT_MAP_INTER, ///< inter-server.conf (map-server)
+ HPCT_LOG, ///< logs.conf (map-server)
+ HPCT_SCRIPT, ///< script.conf (map-server)
HPCT_MAX,
};
@@ -96,53 +101,53 @@ enum HPluginConfType {
#define addArg(name, param,func,help) (HPMi->addArg(HPMi->pid,(name),(param),(cmdline_arg_ ## func),(help)))
/* HPData handy redirects */
/* session[] */
-#define addToSession(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_SESSION,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromSession(ptr,index) (HPMi->getFromHPData(HPDT_SESSION,HPMi->pid,(ptr),(index)))
-#define removeFromSession(ptr,index) (HPMi->removeFromHPData(HPDT_SESSION,HPMi->pid,(ptr),(index)))
+#define addToSession(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_SESSION,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromSession(ptr,classid) (HPMi->getFromHPData(HPDT_SESSION,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromSession(ptr,classid) (HPMi->removeFromHPData(HPDT_SESSION,HPMi->pid,(ptr)->hdata,(classid)))
/* map_session_data */
-#define addToMSD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MSD,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromMSD(ptr,index) (HPMi->getFromHPData(HPDT_MSD,HPMi->pid,(ptr),(index)))
-#define removeFromMSD(ptr,index) (HPMi->removeFromHPData(HPDT_MSD,HPMi->pid,(ptr),(index)))
+#define addToMSD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MSD,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromMSD(ptr,classid) (HPMi->getFromHPData(HPDT_MSD,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromMSD(ptr,classid) (HPMi->removeFromHPData(HPDT_MSD,HPMi->pid,(ptr)->hdata,(classid)))
/* npc_data */
-#define addToNPCD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_NPCD,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromNPCD(ptr,index) (HPMi->getFromHPData(HPDT_NPCD,HPMi->pid,(ptr),(index)))
-#define removeFromNPCD(ptr,index) (HPMi->removeFromHPData(HPDT_NPCD,HPMi->pid,(ptr),(index)))
+#define addToNPCD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_NPCD,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromNPCD(ptr,classid) (HPMi->getFromHPData(HPDT_NPCD,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromNPCD(ptr,classid) (HPMi->removeFromHPData(HPDT_NPCD,HPMi->pid,(ptr)->hdata,(classid)))
/* map_data */
-#define addToMAPD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MAP,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromMAPD(ptr,index) (HPMi->getFromHPData(HPDT_MAP,HPMi->pid,(ptr),(index)))
-#define removeFromMAPD(ptr,index) (HPMi->removeFromHPData(HPDT_MAP,HPMi->pid,(ptr),(index)))
+#define addToMAPD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MAP,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromMAPD(ptr,classid) (HPMi->getFromHPData(HPDT_MAP,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromMAPD(ptr,classid) (HPMi->removeFromHPData(HPDT_MAP,HPMi->pid,(ptr)->hdata,(classid)))
/* party_data */
-#define addToPAD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_PARTY,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromPAD(ptr,index) (HPMi->getFromHPData(HPDT_PARTY,HPMi->pid,(ptr),(index)))
-#define removeFromPAD(ptr,index) (HPMi->removeFromHPData(HPDT_PARTY,HPMi->pid,(ptr),(index)))
+#define addToPAD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_PARTY,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromPAD(ptr,classid) (HPMi->getFromHPData(HPDT_PARTY,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromPAD(ptr,classid) (HPMi->removeFromHPData(HPDT_PARTY,HPMi->pid,(ptr)->hdata,(classid)))
/* guild */
-#define addToGLD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_GUILD,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromGLD(ptr,index) (HPMi->getFromHPData(HPDT_GUILD,HPMi->pid,(ptr),(index)))
-#define removeFromGLD(ptr,index) (HPMi->removeFromHPData(HPDT_GUILD,HPMi->pid,(ptr),(index)))
+#define addToGLD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_GUILD,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromGLD(ptr,classid) (HPMi->getFromHPData(HPDT_GUILD,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromGLD(ptr,classid) (HPMi->removeFromHPData(HPDT_GUILD,HPMi->pid,(ptr)->hdata,(classid)))
/* instance_data */
-#define addToINSTD(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_INSTANCE,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromINSTD(ptr,index) (HPMi->getFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr),(index)))
-#define removeFromINSTD(ptr,index) (HPMi->removeFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr),(index)))
+#define addToINSTD(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_INSTANCE,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromINSTD(ptr,classid) (HPMi->getFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromINSTD(ptr,classid) (HPMi->removeFromHPData(HPDT_INSTANCE,HPMi->pid,(ptr)->hdata,(classid)))
/* mob_db */
-#define addToMOBDB(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MOBDB,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromMOBDB(ptr,index) (HPMi->getFromHPData(HPDT_MOBDB,HPMi->pid,(ptr),(index)))
-#define removeFromMOBDB(ptr,index) (HPMi->removeFromHPData(HPDT_MOBDB,HPMi->pid,(ptr),(index)))
+#define addToMOBDB(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MOBDB,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromMOBDB(ptr,classid) (HPMi->getFromHPData(HPDT_MOBDB,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromMOBDB(ptr,classid) (HPMi->removeFromHPData(HPDT_MOBDB,HPMi->pid,(ptr)->hdata,(classid)))
/* mob_data */
-#define addToMOBDATA(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_MOBDATA,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromMOBDATA(ptr,index) (HPMi->getFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr),(index)))
-#define removeFromMOBDATA(ptr,index) (HPMi->removeFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr),(index)))
+#define addToMOBDATA(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_MOBDATA,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromMOBDATA(ptr,classid) (HPMi->getFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromMOBDATA(ptr,classid) (HPMi->removeFromHPData(HPDT_MOBDATA,HPMi->pid,(ptr)->hdata,(classid)))
/* item_data */
-#define addToITEMDATA(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_ITEMDATA,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromITEMDATA(ptr,index) (HPMi->getFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr),(index)))
-#define removeFromITEMDATA(ptr,index) (HPMi->removeFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr),(index)))
+#define addToITEMDATA(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_ITEMDATA,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromITEMDATA(ptr,classid) (HPMi->getFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromITEMDATA(ptr,classid) (HPMi->removeFromHPData(HPDT_ITEMDATA,HPMi->pid,(ptr)->hdata,(classid)))
/* battleground_data */
-#define addToBGDATA(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_BGDATA,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromBGDATA(ptr,index) (HPMi->getFromHPData(HPDT_BGDATA,HPMi->pid,(ptr),(index)))
-#define removeFromBGDATA(ptr,index) (HPMi->removeFromHPData(HPDT_BGDATA,HPMi->pid,(ptr),(index)))
+#define addToBGDATA(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_BGDATA,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromBGDATA(ptr,classid) (HPMi->getFromHPData(HPDT_BGDATA,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromBGDATA(ptr,classid) (HPMi->removeFromHPData(HPDT_BGDATA,HPMi->pid,(ptr)->hdata,(classid)))
/* autotrade_vending */
-#define addToATVEND(ptr,data,index,autofree) (HPMi->addToHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr),(data),(index),(autofree)))
-#define getFromATVEND(ptr,index) (HPMi->getFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr),(index)))
-#define removeFromATVEND(ptr,index) (HPMi->removeFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr),(index)))
+#define addToATVEND(ptr,data,classid,autofree) (HPMi->addToHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,&(ptr)->hdata,(data),(classid),(autofree)))
+#define getFromATVEND(ptr,classid) (HPMi->getFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr)->hdata,(classid)))
+#define removeFromATVEND(ptr,classid) (HPMi->removeFromHPData(HPDT_AUTOTRADE_VEND,HPMi->pid,(ptr)->hdata,(classid)))
/// HPMi->addCommand
#define addAtcommand(cname,funcname) do { \
@@ -205,9 +210,9 @@ struct HPMi_interface {
bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st), bool isDeprecated);
void (*addCPCommand) (char *name, CParseFunc func);
/* HPM Custom Data */
- void (*addToHPData) (enum HPluginDataTypes type, unsigned int pluginID, void *ptr, void *data, unsigned int index, bool autofree);
- void *(*getFromHPData) (enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index);
- void (*removeFromHPData) (enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index);
+ void (*addToHPData) (enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store **storeptr, void *data, uint32 classid, bool autofree);
+ void *(*getFromHPData) (enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid);
+ void (*removeFromHPData) (enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid);
/* packet */
bool (*addPacket) (unsigned short cmd, unsigned short length, void (*receive)(int fd), unsigned int point, unsigned int pluginID);
/* Hooking */
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h
index 575428f96..64f21f7e0 100644
--- a/src/common/cbasetypes.h
+++ b/src/common/cbasetypes.h
@@ -391,7 +391,7 @@ typedef char bool;
//////////////////////////////////////////////////////////////////////////
// length of a static array
-#define ARRAYLENGTH(A) ( sizeof(A)/sizeof((A)[0]) )
+#define ARRAYLENGTH(A) ( (int)(sizeof(A)/sizeof((A)[0])) )
//////////////////////////////////////////////////////////////////////////
// Make sure va_copy exists
diff --git a/src/common/console.c b/src/common/console.c
index eb55d7462..c8ca4ae87 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -9,6 +9,7 @@
#include "common/cbasetypes.h"
#include "common/core.h"
+#include "common/nullpo.h"
#include "common/showmsg.h"
#include "common/sysinfo.h"
@@ -124,14 +125,16 @@ CPCMD_C(mem_report,server) {
/**
* Displays command list
**/
-CPCMD(help) {
- unsigned int i = 0;
- for ( i = 0; i < console->input->cmd_list_count; i++ ) {
- if( console->input->cmd_list[i]->next_count ) {
- ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",console->input->cmd_list[i]->cmd);
- console->input->parse_list_subs(console->input->cmd_list[i],2);
+CPCMD(help)
+{
+ int i;
+ for (i = 0; i < VECTOR_LENGTH(console->input->command_list); i++) {
+ struct CParseEntry *entry = VECTOR_INDEX(console->input->command_list, i);
+ if (entry->type == CPET_CATEGORY) {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n", entry->cmd);
+ console->input->parse_list_subs(entry, 2);
} else {
- ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->input->cmd_list[i]->cmd);
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n", entry->cmd);
}
}
}
@@ -171,7 +174,7 @@ void console_load_defaults(void)
* 'sql' is the main category
* CP_DEF_C(category)
**/
-#define CP_DEF_C(x) { #x , NULL , NULL, NULL }
+#define CP_DEF_C(x) { #x , CPET_CATEGORY, NULL , NULL, NULL }
/**
* Defines a sub-category.
*
@@ -181,20 +184,21 @@ void console_load_defaults(void)
* 'update' is a sub-category
* CP_DEF_C2(command, category)
**/
-#define CP_DEF_C2(x,y) { #x , NULL , #y, NULL }
+#define CP_DEF_C2(x,y) { #x , CPET_CATEGORY, NULL , #y, NULL }
/**
* Defines a command that is inside a category or sub-category
* CP_DEF_S(command, category/sub-category)
**/
-#define CP_DEF_S(x,y) { #x, CPCMD_C_A(x,y), #y, NULL }
+#define CP_DEF_S(x,y) { #x, CPET_FUNCTION, CPCMD_C_A(x,y), #y, NULL }
/**
* Defines a command that is _not_ inside any category
* CP_DEF_S(command)
**/
-#define CP_DEF(x) { #x , CPCMD_A(x), NULL, NULL }
+#define CP_DEF(x) { #x , CPET_FUNCTION, CPCMD_A(x), NULL, NULL }
struct {
char *name;
+ int type;
CParseFunc func;
char *connect;
struct CParseEntry *self;
@@ -215,43 +219,49 @@ void console_load_defaults(void)
CP_DEF_C2(update,sql),
CP_DEF_S(skip,update),
};
- unsigned int i, len = ARRAYLENGTH(default_list);
+ int len = ARRAYLENGTH(default_list);
struct CParseEntry *cmd;
+ int i;
- RECREATE(console->input->cmds,struct CParseEntry *, len);
+ VECTOR_ENSURE(console->input->commands, len, 1);
for(i = 0; i < len; i++) {
CREATE(cmd, struct CParseEntry, 1);
safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH);
- if( default_list[i].func )
- cmd->u.func = default_list[i].func;
- else
- cmd->u.next = NULL;
+ cmd->type = default_list[i].type;
- cmd->next_count = 0;
+ switch (cmd->type) {
+ case CPET_FUNCTION:
+ cmd->u.func = default_list[i].func;
+ break;
+ case CPET_CATEGORY:
+ VECTOR_INIT(cmd->u.children);
+ break;
+ case CPET_UNKNOWN:
+ break;
+ }
- console->input->cmd_count++;
- console->input->cmds[i] = cmd;
+ VECTOR_PUSH(console->input->commands, cmd);
default_list[i].self = cmd;
- if( !default_list[i].connect ) {
- RECREATE(console->input->cmd_list,struct CParseEntry *, ++console->input->cmd_list_count);
- console->input->cmd_list[console->input->cmd_list_count - 1] = cmd;
+ if (!default_list[i].connect) {
+ VECTOR_ENSURE(console->input->command_list, 1, 1);
+ VECTOR_PUSH(console->input->command_list, cmd);
}
}
- for(i = 0; i < len; i++) {
- unsigned int k;
- if( !default_list[i].connect )
+ for (i = 0; i < len; i++) {
+ int k;
+ if (!default_list[i].connect)
continue;
- for(k = 0; k < console->input->cmd_count; k++) {
- if( strcmpi(default_list[i].connect,console->input->cmds[k]->cmd) == 0 ) {
- cmd = default_list[i].self;
- RECREATE(console->input->cmds[k]->u.next, struct CParseEntry *, ++console->input->cmds[k]->next_count);
- console->input->cmds[k]->u.next[console->input->cmds[k]->next_count - 1] = cmd;
- break;
- }
+ ARR_FIND(0, VECTOR_LENGTH(console->input->commands), k, strcmpi(default_list[i].connect, VECTOR_INDEX(console->input->commands, k)->cmd) == 0);
+ if (k != VECTOR_LENGTH(console->input->commands)) {
+ struct CParseEntry *parent = VECTOR_INDEX(console->input->commands, k);
+ Assert_retb(parent->type == CPET_CATEGORY);
+ cmd = default_list[i].self;
+ VECTOR_ENSURE(parent->u.children, 1, 1);
+ VECTOR_PUSH(parent->u.children, cmd);
}
}
#undef CP_DEF_C
@@ -260,8 +270,15 @@ void console_load_defaults(void)
#undef CP_DEF
}
-void console_parse_create(char *name, CParseFunc func) {
- unsigned int i;
+/**
+ * Creates a new console command entry.
+ *
+ * @param name The command name.
+ * @param func The command callback.
+ */
+void console_parse_create(char *name, CParseFunc func)
+{
+ int i;
char *tok;
char sublist[CP_CMD_LENGTH * 5];
struct CParseEntry *cmd;
@@ -269,123 +286,142 @@ void console_parse_create(char *name, CParseFunc func) {
safestrncpy(sublist, name, CP_CMD_LENGTH * 5);
tok = strtok(sublist,":");
- for ( i = 0; i < console->input->cmd_list_count; i++ ) {
- if( strcmpi(tok,console->input->cmd_list[i]->cmd) == 0 )
- break;
- }
+ ARR_FIND(0, VECTOR_LENGTH(console->input->command_list), i, strcmpi(tok, VECTOR_INDEX(console->input->command_list, i)->cmd) == 0);
- if( i == console->input->cmd_list_count ) {
- RECREATE(console->input->cmds,struct CParseEntry *, ++console->input->cmd_count);
+ if (i == VECTOR_LENGTH(console->input->command_list)) {
CREATE(cmd, struct CParseEntry, 1);
safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH);
- cmd->next_count = 0;
- console->input->cmds[console->input->cmd_count - 1] = cmd;
- RECREATE(console->input->cmd_list,struct CParseEntry *, ++console->input->cmd_list_count);
- console->input->cmd_list[console->input->cmd_list_count - 1] = cmd;
- i = console->input->cmd_list_count - 1;
+ cmd->type = CPET_UNKNOWN;
+ VECTOR_ENSURE(console->input->commands, 1, 1);
+ VECTOR_PUSH(console->input->commands, cmd);
+ VECTOR_ENSURE(console->input->command_list, 1, 1);
+ VECTOR_PUSH(console->input->command_list, cmd);
}
- cmd = console->input->cmd_list[i];
- while( ( tok = strtok(NULL, ":") ) != NULL ) {
- for(i = 0; i < cmd->next_count; i++) {
- if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 )
- break;
+ cmd = VECTOR_INDEX(console->input->command_list, i);
+ while ((tok = strtok(NULL, ":")) != NULL) {
+ if (cmd->type == CPET_UNKNOWN) {
+ cmd->type = CPET_CATEGORY;
+ VECTOR_INIT(cmd->u.children);
}
-
- if ( i == cmd->next_count ) {
- RECREATE(console->input->cmds,struct CParseEntry *, ++console->input->cmd_count);
- CREATE(console->input->cmds[console->input->cmd_count-1], struct CParseEntry, 1);
- safestrncpy(console->input->cmds[console->input->cmd_count-1]->cmd, tok, CP_CMD_LENGTH);
- console->input->cmds[console->input->cmd_count-1]->next_count = 0;
- RECREATE(cmd->u.next, struct CParseEntry *, ++cmd->next_count);
- cmd->u.next[cmd->next_count - 1] = console->input->cmds[console->input->cmd_count-1];
- cmd = console->input->cmds[console->input->cmd_count-1];
+ Assert_retv(cmd->type == CPET_CATEGORY);
+
+ ARR_FIND(0, VECTOR_LENGTH(cmd->u.children), i, strcmpi(VECTOR_INDEX(cmd->u.children, i)->cmd,tok) == 0);
+ if (i == VECTOR_LENGTH(cmd->u.children)) {
+ struct CParseEntry *entry;
+ CREATE(entry, struct CParseEntry, 1);
+ safestrncpy(entry->cmd, tok, CP_CMD_LENGTH);
+ entry->type = CPET_UNKNOWN;
+ VECTOR_ENSURE(console->input->commands, 1, 1);
+ VECTOR_PUSH(console->input->commands, entry);
+ VECTOR_ENSURE(cmd->u.children, 1, 1);
+ VECTOR_PUSH(cmd->u.children, entry);
+ cmd = entry;
continue;
}
+ cmd = VECTOR_INDEX(cmd->u.children, i);
}
+ Assert_retv(cmd->type != CPET_CATEGORY);
+ cmd->type = CPET_FUNCTION;
cmd->u.func = func;
}
-void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) {
- unsigned int i;
+
+/**
+ * Shows the help message for a console command category.
+ *
+ * @param cmd The command entry.
+ * @param depth The current tree depth (for display purposes).
+ */
+void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth)
+{
+ int i;
char msg[CP_CMD_LENGTH * 2];
- for( i = 0; i < cmd->next_count; i++ ) {
- if( cmd->u.next[i]->next_count ) {
- memset(msg, '-', depth);
- snprintf(msg + depth,( CP_CMD_LENGTH * 2 ) - depth, " '"CL_WHITE"%s"CL_RESET"'",cmd->u.next[i]->cmd);
- ShowInfo("%s subs\n",msg);
- console->input->parse_list_subs(cmd->u.next[i],depth + 1);
- } else {
- memset(msg, '-', depth);
- snprintf(msg + depth,(CP_CMD_LENGTH * 2) - depth, " %s",cmd->u.next[i]->cmd);
+ Assert_retv(cmd->type == CPET_CATEGORY);
+ for (i = 0; i < VECTOR_LENGTH(cmd->u.children); i++) {
+ struct CParseEntry *child = VECTOR_INDEX(cmd->u.children, i);
+ memset(msg, '-', depth);
+ snprintf(msg + depth, (CP_CMD_LENGTH * 2) - depth, " '"CL_WHITE"%s"CL_RESET"'", child->cmd);
+ if (child->type == CPET_FUNCTION) {
ShowInfo("%s\n",msg);
+ } else {
+ ShowInfo("%s subs\n",msg);
+ console->input->parse_list_subs(child,depth + 1);
}
}
}
-void console_parse_sub(char *line) {
+
+/**
+ * Parses a console command.
+ *
+ * @param line The input line.
+ */
+void console_parse_sub(char *line)
+{
struct CParseEntry *cmd;
char bline[200];
char *tok;
char sublist[CP_CMD_LENGTH * 5];
- unsigned int i, len = 0;
+ int i;
+ unsigned int len = 0;
memcpy(bline, line, 200);
tok = strtok(line, " ");
- for ( i = 0; i < console->input->cmd_list_count; i++ ) {
- if( strcmpi(tok,console->input->cmd_list[i]->cmd) == 0 )
- break;
- }
-
- if( i == console->input->cmd_list_count ) {
+ ARR_FIND(0, VECTOR_LENGTH(console->input->command_list), i, strcmpi(tok, VECTOR_INDEX(console->input->command_list, i)->cmd) == 0);
+ if (i == VECTOR_LENGTH(console->input->command_list)) {
ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known command, type '"CL_WHITE"help"CL_RESET"' to list all commands\n",line);
return;
}
- cmd = console->input->cmd_list[i];
+ cmd = VECTOR_INDEX(console->input->command_list, i);
- len += snprintf(sublist,CP_CMD_LENGTH * 5,"%s", cmd->cmd) + 1;
+ len += snprintf(sublist,CP_CMD_LENGTH * 5,"%s", cmd->cmd);
- if( cmd->next_count == 0 && console->input->cmd_list[i]->u.func ) {
+ if (cmd->type == CPET_FUNCTION) {
char *r = NULL;
if( (tok = strtok(NULL, " ")) ) {
r = bline;
r += len + 1;
}
cmd->u.func(r);
- } else {
- while( ( tok = strtok(NULL, " ") ) != NULL ) {
- for( i = 0; i < cmd->next_count; i++ ) {
- if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 )
- break;
- }
- if( i == cmd->next_count ) {
- if( strcmpi("help",tok) == 0 ) {
- if( cmd->next_count ) {
- ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist);
- console->input->parse_list_subs(cmd,2);
- } else {
- ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist);
- }
- return;
+ return;
+ }
+
+ while (( tok = strtok(NULL, " ") ) != NULL) {
+ struct CParseEntry *entry = NULL;
+
+ Assert_retv(cmd->type == CPET_CATEGORY);
+
+ ARR_FIND(0, VECTOR_LENGTH(cmd->u.children), i, strcmpi(VECTOR_INDEX(cmd->u.children, i)->cmd, tok) == 0);
+ if (i == VECTOR_LENGTH(cmd->u.children)) {
+ if (strcmpi("help", tok) == 0) {
+ if (VECTOR_LENGTH(cmd->u.children)) {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist);
+ console->input->parse_list_subs(cmd,2);
+ } else {
+ ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist);
}
- ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd);
- ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
return;
}
- if( cmd->u.next[i]->next_count == 0 && cmd->u.next[i]->u.func ) {
- char *r = NULL;
- if( (tok = strtok(NULL, " ")) ) {
- r = bline;
- r += len + strlen(cmd->u.next[i]->cmd) + 1;
- }
- cmd->u.next[i]->u.func(r);
- return;
- } else
- cmd = cmd->u.next[i];
- len += snprintf(sublist + len,(CP_CMD_LENGTH * 5) - len,":%s", cmd->cmd);
+ ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd);
+ ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
+ return;
+ }
+ entry = VECTOR_INDEX(cmd->u.children, i);
+ if (entry->type == CPET_FUNCTION) {
+ char *r = NULL;
+ if ((tok = strtok(NULL, " "))) {
+ r = bline;
+ r += len + strlen(entry->cmd) + 1;
+ }
+ entry->u.func(r);
+ return;
}
- ShowError("Is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
+
+ cmd = entry;
+ len += snprintf(sublist + len,(CP_CMD_LENGTH * 5) - len," %s", cmd->cmd);
}
+ ShowError("Is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
}
void console_parse(char* line) {
int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */
@@ -472,27 +508,33 @@ void console_setSQL(Sql *SQL_handle) {
}
#endif /* CONSOLE_INPUT */
-void console_init (void) {
+void console_init(void)
+{
#ifdef CONSOLE_INPUT
- console->input->cmd_count = console->input->cmd_list_count = 0;
+ VECTOR_INIT(console->input->command_list);
+ VECTOR_INIT(console->input->commands);
console->input->load_defaults();
console->input->parse_init();
#endif
}
-void console_final(void) {
+
+void console_final(void)
+{
#ifdef CONSOLE_INPUT
- unsigned int i;
console->input->parse_final();
- for( i = 0; i < console->input->cmd_count; i++ ) {
- if( console->input->cmds[i]->next_count )
- aFree(console->input->cmds[i]->u.next);
- aFree(console->input->cmds[i]);
+ while (VECTOR_LENGTH(console->input->commands)) {
+ struct CParseEntry *entry = VECTOR_POP(console->input->commands);
+ if (entry->type == CPET_CATEGORY)
+ VECTOR_CLEAR(entry->u.children);
+ aFree(entry);
}
- aFree(console->input->cmds);
- aFree(console->input->cmd_list);
+ VECTOR_CLEAR(console->input->commands);
+ VECTOR_CLEAR(console->input->command_list);
#endif
}
-void console_defaults(void) {
+
+void console_defaults(void)
+{
console = &console_s;
console->init = console_init;
console->final = console_final;
diff --git a/src/common/console.h b/src/common/console.h
index ffb4a165b..ef6db0cb4 100644
--- a/src/common/console.h
+++ b/src/common/console.h
@@ -5,6 +5,7 @@
#define COMMON_CONSOLE_H
#include "common/hercules.h"
+#include "common/db.h"
#include "common/mutex.h"
#include "common/spinlock.h"
#include "common/sql.h"
@@ -33,13 +34,20 @@ typedef void (*CParseFunc)(char *line);
#define CPCMD_C_A(x,y) console_parse_ ##y ##x
#define CP_CMD_LENGTH 20
+
+enum CONSOLE_PARSE_ENTRY_TYPE {
+ CPET_UNKNOWN,
+ CPET_FUNCTION,
+ CPET_CATEGORY,
+};
+
struct CParseEntry {
char cmd[CP_CMD_LENGTH];
+ int type; ///< Entry type (@see enum CONSOLE_PARSE_ENTRY_TYPE)
union {
CParseFunc func;
- struct CParseEntry **next;
+ VECTOR_DECL(struct CParseEntry *) children;
} u;
- unsigned short next_count;
};
#ifdef CONSOLE_INPUT
@@ -51,10 +59,8 @@ struct console_input_interface {
ramutex *ptmutex;/* parse thread mutex */
racond *ptcond;/* parse thread cond */
/* */
- struct CParseEntry **cmd_list;
- struct CParseEntry **cmds;
- unsigned int cmd_count;
- unsigned int cmd_list_count;
+ VECTOR_DECL(struct CParseEntry *) command_list;
+ VECTOR_DECL(struct CParseEntry *) commands;
/* */
Sql *SQL;
/* */
diff --git a/src/common/core.c b/src/common/core.c
index dcc96fa41..8564b8acc 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -207,8 +207,9 @@ const char *cmdline_arg_source(struct CmdlineArgData *arg) {
bool cmdline_arg_add(unsigned int pluginID, const char *name, char shortname, CmdlineExecFunc func, const char *help, unsigned int options) {
struct CmdlineArgData *data = NULL;
- RECREATE(cmdline->args_data, struct CmdlineArgData, ++cmdline->args_data_count);
- data = &cmdline->args_data[cmdline->args_data_count-1];
+ VECTOR_ENSURE(cmdline->args_data, 1, 1);
+ VECTOR_PUSHZEROED(cmdline->args_data);
+ data = &VECTOR_LAST(cmdline->args_data);
data->pluginID = pluginID;
data->name = aStrdup(name);
data->shortname = shortname;
@@ -228,8 +229,8 @@ static CMDLINEARG(help)
ShowInfo("\n");
ShowInfo("Options:\n");
- for (i = 0; i < cmdline->args_data_count; i++) {
- struct CmdlineArgData *data = &cmdline->args_data[i];
+ for (i = 0; i < VECTOR_LENGTH(cmdline->args_data); i++) {
+ struct CmdlineArgData *data = &VECTOR_INDEX(cmdline->args_data, i);
char altname[16], paramnames[256];
if (data->shortname) {
snprintf(altname, sizeof(altname), " [-%c]", data->shortname);
@@ -288,8 +289,9 @@ bool cmdline_arg_next_value(const char *name, int current_arg, int argc)
*/
int cmdline_exec(int argc, char **argv, unsigned int options)
{
- int count = 0, i, j;
+ int count = 0, i;
for (i = 1; i < argc; i++) {
+ int j;
struct CmdlineArgData *data = NULL;
const char *arg = argv[i];
if (arg[0] != '-') { // All arguments must begin with '-'
@@ -297,17 +299,17 @@ int cmdline_exec(int argc, char **argv, unsigned int options)
exit(EXIT_FAILURE);
}
if (arg[1] != '-' && strlen(arg) == 2) {
- ARR_FIND(0, cmdline->args_data_count, j, cmdline->args_data[j].shortname == arg[1]);
+ ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), j, VECTOR_INDEX(cmdline->args_data, j).shortname == arg[1]);
} else {
- ARR_FIND(0, cmdline->args_data_count, j, strcmpi(cmdline->args_data[j].name, arg) == 0);
+ ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), j, strcmpi(VECTOR_INDEX(cmdline->args_data, j).name, arg) == 0);
}
- if (j == cmdline->args_data_count) {
+ if (j == VECTOR_LENGTH(cmdline->args_data)) {
if (options&(CMDLINE_OPT_SILENT|CMDLINE_OPT_PREINIT))
continue;
ShowError("Unknown option '%s'.\n", arg);
exit(EXIT_FAILURE);
}
- data = &cmdline->args_data[j];
+ data = &VECTOR_INDEX(cmdline->args_data, j);
if (data->options&CMDLINE_OPT_PARAM) {
if (!cmdline->arg_next_value(arg, i, argc))
exit(EXIT_FAILURE);
@@ -346,15 +348,15 @@ void cmdline_init(void)
#endif // !MINICORE
cmdline_args_init_local();
}
+
void cmdline_final(void)
{
- int i;
- for (i = 0; i < cmdline->args_data_count; i++) {
- aFree(cmdline->args_data[i].name);
- aFree(cmdline->args_data[i].help);
+ while (VECTOR_LENGTH(cmdline->args_data) > 0) {
+ struct CmdlineArgData *data = &VECTOR_POP(cmdline->args_data);
+ aFree(data->name);
+ aFree(data->help);
}
- if (cmdline->args_data)
- aFree(cmdline->args_data);
+ VECTOR_CLEAR(cmdline->args_data);
}
struct cmdline_interface cmdline_s;
@@ -364,8 +366,7 @@ void cmdline_defaults(void)
{
cmdline = &cmdline_s;
- cmdline->args_data = NULL;
- cmdline->args_data_count = 0;
+ VECTOR_INIT(cmdline->args_data);
cmdline->init = cmdline_init;
cmdline->final = cmdline_final;
diff --git a/src/common/core.h b/src/common/core.h
index c92bf4fa6..f8e748db4 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -6,6 +6,7 @@
#define COMMON_CORE_H
#include "common/hercules.h"
+#include "common/db.h"
/* so that developers with --enable-debug can raise signals from any section of the code they'd like */
#ifdef DEBUG
@@ -46,8 +47,7 @@ struct CmdlineArgData {
};
struct cmdline_interface {
- struct CmdlineArgData *args_data;
- int args_data_count;
+ VECTOR_DECL(struct CmdlineArgData) args_data;
void (*init) (void);
void (*final) (void);
diff --git a/src/common/db.h b/src/common/db.h
index 73d44a755..afec62d86 100644
--- a/src/common/db.h
+++ b/src/common/db.h
@@ -935,608 +935,785 @@ void db_defaults(void);
HPShared struct db_interface *DB;
-/// Finds an entry in an array.
-/// ex: ARR_FIND(0, size, i, list[i] == target);
-///
-/// @param __start Starting index (ex: 0)
-/// @param __end End index (ex: size of the array)
-/// @param __var Index variable
-/// @param __cmp Expression that returns true when the target entry is found
-#define ARR_FIND(__start, __end, __var, __cmp) \
- do{ \
- for( (__var) = (__start); (__var) < (__end); ++(__var) ) \
- if( __cmp ) \
+/**
+ * Array Helper macros
+ */
+
+/**
+ * Finds an entry in an array.
+ *
+ * @code
+ * ARR_FIND(0, size, i, list[i] == target);
+ * @endcode
+ *
+ * To differentiate between the found and not found cases, the caller code can
+ * compare _end and _var after this macro returns.
+ *
+ * @param _start Starting index (ex: 0).
+ * @param _end End index (ex: size of the array).
+ * @param _var Index variable.
+ * @param _cmp Search expression (should return true when the target entry is found).
+ */
+#define ARR_FIND(_start, _end, _var, _cmp) \
+ do { \
+ for ((_var) = (_start); (_var) < (_end); ++(_var)) \
+ if (_cmp) \
break; \
- }while(0)
-
-/// Moves an entry of the array.
-/// Use ARR_MOVERIGHT/ARR_MOVELEFT if __from and __to are direct numbers.
-/// ex: ARR_MOVE(i, 0, list, int);// move index i to index 0
-///
-///
-/// @param __from Initial index of the entry
-/// @param __to Target index of the entry
-/// @param __arr Array
-/// @param __type Type of entry
-#define ARR_MOVE(__from, __to, __arr, __type) \
- do{ \
- if( (__from) != (__to) ) \
- { \
- __type __backup__; \
- memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
- if( (__from) < (__to) ) \
- memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
- else if( (__from) > (__to) ) \
- memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
- memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+ } while(false)
+
+/**
+ * Moves an entry of the array.
+ *
+ * @code
+ * ARR_MOVE(i, 0, list, int); // move index i to index 0
+ * @endcode
+ *
+ * @remark
+ * Use ARR_MOVERIGHT/ARR_MOVELEFT if _from and _to are direct numbers.
+ *
+ * @param _from Initial index of the entry.
+ * @param _to Target index of the entry.
+ * @param _arr Array.
+ * @param _type Type of entry.
+ */
+#define ARR_MOVE(_from, _to, _arr, _type) \
+ do { \
+ if ((_from) != (_to)) { \
+ _type _backup_; \
+ memmove(&_backup_, (_arr)+(_from), sizeof(_type)); \
+ if ((_from) < (_to)) \
+ memmove((_arr)+(_from), (_arr)+(_from)+1, ((_to)-(_from))*sizeof(_type)); \
+ else if ((_from) > (_to)) \
+ memmove((_arr)+(_to)+1, (_arr)+(_to), ((_from)-(_to))*sizeof(_type)); \
+ memmove((_arr)+(_to), &_backup_, sizeof(_type)); \
} \
- }while(0)
-
-/// Moves an entry of the array to the right.
-/// ex: ARR_MOVERIGHT(1, 4, list, int);// move index 1 to index 4
-///
-/// @param __from Initial index of the entry
-/// @param __to Target index of the entry
-/// @param __arr Array
-/// @param __type Type of entry
-#define ARR_MOVERIGHT(__from, __to, __arr, __type) \
- do{ \
- __type __backup__; \
- memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
- memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
- memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
- }while(0)
-
-/// Moves an entry of the array to the left.
-/// ex: ARR_MOVELEFT(3, 0, list, int);// move index 3 to index 0
-///
-/// @param __from Initial index of the entry
-/// @param __end Target index of the entry
-/// @param __arr Array
-/// @param __type Type of entry
-#define ARR_MOVELEFT(__from, __to, __arr, __type) \
- do{ \
- __type __backup__; \
- memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
- memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
- memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
- }while(0)
-
-/////////////////////////////////////////////////////////////////////
-// Vector library based on defines. (dynamic array)
-// uses aMalloc, aRealloc, aFree
-
-/// Declares an anonymous vector struct.
-///
-/// @param __type Type of data
-#define VECTOR_DECL(__type) \
+ } while(false)
+
+/**
+ * Moves an entry of the array to the right.
+ *
+ * @code
+ * ARR_MOVERIGHT(1, 4, list, int); // move index 1 to index 4
+ * @endcode
+ *
+ * @param _from Initial index of the entry.
+ * @param _to Target index of the entry.
+ * @param _arr Array.
+ * @param _type Type of entry.
+ */
+#define ARR_MOVERIGHT(_from, _to, _arr, _type) \
+ do { \
+ _type _backup_; \
+ memmove(&_backup_, (_arr)+(_from), sizeof(_type)); \
+ memmove((_arr)+(_from), (_arr)+(_from)+1, ((_to)-(_from))*sizeof(_type)); \
+ memmove((_arr)+(_to), &_backup_, sizeof(_type)); \
+ } while(false)
+
+/**
+ * Moves an entry of the array to the left.
+ *
+ * @code
+ * ARR_MOVELEFT(3, 0, list, int); // move index 3 to index 0
+ * @endcode
+ *
+ * @param _from Initial index of the entry.
+ * @param _end Target index of the entry.
+ * @param _arr Array.
+ * @param _type Type of entry.
+ */
+#define ARR_MOVELEFT(_from, _to, _arr, _type) \
+ do { \
+ _type _backup_; \
+ memmove(&_backup_, (_arr)+(_from), sizeof(_type)); \
+ memmove((_arr)+(_to)+1, (_arr)+(_to), ((_from)-(_to))*sizeof(_type)); \
+ memmove((_arr)+(_to), &_backup_, sizeof(_type)); \
+ } while(false)
+
+/**
+ * Vector library based on defines (dynamic array).
+ *
+ * @remark
+ * This library uses aMalloc, aRealloc, aFree.
+ */
+
+/**
+ * Declares an anonymous vector struct.
+ *
+ * @param _type Type of data to be contained.
+ */
+#define VECTOR_DECL(_type) \
struct { \
- size_t _max_; \
- size_t _len_; \
- __type* _data_; \
+ int _max_; \
+ int _len_; \
+ _type *_data_; \
}
-/// Declares a named vector struct.
-///
-/// @param __name Structure name
-/// @param __type Type of data
-#define VECTOR_STRUCT_DECL(__name,__type) \
- struct __name { \
- size_t _max_; \
- size_t _len_; \
- __type* _data_; \
+/**
+ * Declares a named vector struct.
+ *
+ * @param _name Structure name.
+ * @param _type Type of data to be contained.
+ */
+#define VECTOR_STRUCT_DECL(_name, _type) \
+ struct _name { \
+ int _max_; \
+ int _len_; \
+ _type *_data_; \
}
-/// Declares and initializes an anonymous vector variable.
-///
-/// @param __type Type of data
-/// @param __var Variable name
-#define VECTOR_VAR(__type,__var) \
- VECTOR_DECL(__type) __var = {0,0,NULL}
-
-/// Declares and initializes a named vector variable.
-///
-/// @param __name Structure name
-/// @param __var Variable name
-#define VECTOR_STRUCT_VAR(__name,__var) \
- struct __name __var = {0,0,NULL}
-
-/// Initializes a vector.
-///
-/// @param __vec Vector
-#define VECTOR_INIT(__vec) \
- memset(&(__vec), 0, sizeof(__vec))
-
-/// Returns the internal array of values.
-///
-/// @param __vec Vector
-/// @return Array of values
-#define VECTOR_DATA(__vec) \
- ( (__vec)._data_ )
-
-/// Returns the length of the vector.
-///
-/// @param __vec Vector
-/// @return Length
-#define VECTOR_LENGTH(__vec) \
- ( (__vec)._len_ )
-
-/// Returns the capacity of the vector.
-///
-/// @param __vec Vector
-/// @return Capacity
-#define VECTOR_CAPACITY(__vec) \
- ( (__vec)._max_ )
-
-/// Returns the value at the target index.
-/// Assumes the index exists.
-///
-/// @param __vec Vector
-/// @param __idx Index
-/// @return Value
-#define VECTOR_INDEX(__vec,__idx) \
- ( VECTOR_DATA(__vec)[__idx] )
-
-/// Returns the first value of the vector.
-/// Assumes the array is not empty.
-///
-/// @param __vec Vector
-/// @return First value
-#define VECTOR_FIRST(__vec) \
- ( VECTOR_INDEX(__vec,0) )
-
-/// Returns the last value of the vector.
-/// Assumes the array is not empty.
-///
-/// @param __vec Vector
-/// @return Last value
-#define VECTOR_LAST(__vec) \
- ( VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)-1) )
-
-/// Resizes the vector.
-/// Excess values are discarded, new positions are zeroed.
-///
-/// @param __vec Vector
-/// @param __n Size
-#define VECTOR_RESIZE(__vec,__n) \
- do{ \
- if( (__n) > VECTOR_CAPACITY(__vec) ) \
- { /* increase size */ \
- if( VECTOR_CAPACITY(__vec) == 0 ) VECTOR_DATA(__vec) = aMalloc((__n)*sizeof(VECTOR_FIRST(__vec))); /* allocate new */ \
- else VECTOR_DATA(__vec) = aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec))); /* reallocate */ \
- memset(VECTOR_DATA(__vec)+VECTOR_LENGTH(__vec), 0, (VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec))*sizeof(VECTOR_FIRST(__vec))); /* clear new data */ \
- VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \
- } \
- else if( (__n) == 0 && VECTOR_CAPACITY(__vec) ) \
- { /* clear vector */ \
- aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* free data */ \
- VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \
- VECTOR_LENGTH(__vec) = 0; /* clear length */ \
- } \
- else if( (__n) < VECTOR_CAPACITY(__vec) ) \
- { /* reduce size */ \
- VECTOR_DATA(__vec) = aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec))); /* reallocate */ \
- VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \
- if( VECTOR_LENGTH(__vec) > (__n) ) VECTOR_LENGTH(__vec) = (__n); /* update length */ \
+/**
+ * Declares and initializes an anonymous vector variable.
+ *
+ * @param _type Type of data to be contained.
+ * @param _var Variable name.
+ */
+#define VECTOR_VAR(_type, _var) \
+ VECTOR_DECL(_type) _var = {0, 0, NULL}
+
+/**
+ * Declares and initializes a named vector variable.
+ *
+ * @param _name Structure name.
+ * @param _var Variable name.
+ */
+#define VECTOR_STRUCT_VAR(_name, _var) \
+ struct _name _var = {0, 0, NULL}
+
+/**
+ * Initializes a vector.
+ *
+ * @param _vec Vector.
+ */
+#define VECTOR_INIT(_vec) \
+ memset(&(_vec), 0, sizeof(_vec))
+
+/**
+ * Returns the internal array of values.
+ *
+ * @param _vec Vector.
+ * @return Internal array of values.
+ */
+#define VECTOR_DATA(_vec) \
+ ( (_vec)._data_ )
+
+/**
+ * Returns the length of the vector (number of elements in use).
+ *
+ * @param _vec Vector
+ * @return Length
+ */
+#define VECTOR_LENGTH(_vec) \
+ ( (_vec)._len_ )
+
+/**
+ * Returns the capacity of the vector (number of elements allocated).
+ *
+ * @param _vec Vector.
+ * @return Capacity.
+ */
+#define VECTOR_CAPACITY(_vec) \
+ ( (_vec)._max_ )
+
+/**
+ * Returns the value at the target index.
+ *
+ * Assumes the index exists.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ * @return Value.
+ */
+#define VECTOR_INDEX(_vec, _idx) \
+ ( VECTOR_DATA(_vec)[_idx] )
+
+/**
+ * Returns the first value of the vector.
+ *
+ * Assumes the array is not empty.
+ *
+ * @param _vec Vector.
+ * @return First value.
+ */
+#define VECTOR_FIRST(_vec) \
+ ( VECTOR_INDEX(_vec, 0) )
+
+/**
+ * Returns the last value of the vector.
+ *
+ * Assumes the array is not empty.
+ *
+ * @param _vec Vector.
+ * @return Last value.
+ */
+#define VECTOR_LAST(_vec) \
+ ( VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)-1) )
+
+/**
+ * Resizes the vector.
+ *
+ * Excess values are discarded, new positions are zeroed.
+ *
+ * @param _vec Vector.
+ * @param _n New size.
+ */
+#define VECTOR_RESIZE(_vec, _n) \
+ do { \
+ if ((_n) > VECTOR_CAPACITY(_vec)) { \
+ /* increase size */ \
+ if (VECTOR_CAPACITY(_vec) == 0) \
+ VECTOR_DATA(_vec) = aMalloc((_n)*sizeof(VECTOR_FIRST(_vec))); /* allocate new */ \
+ else \
+ VECTOR_DATA(_vec) = aRealloc(VECTOR_DATA(_vec), (_n)*sizeof(VECTOR_FIRST(_vec))); /* reallocate */ \
+ memset(VECTOR_DATA(_vec)+VECTOR_LENGTH(_vec), 0, (VECTOR_CAPACITY(_vec)-VECTOR_LENGTH(_vec))*sizeof(VECTOR_FIRST(_vec))); /* clear new data */ \
+ VECTOR_CAPACITY(_vec) = (_n); /* update capacity */ \
+ } else if ((_n) == 0 && VECTOR_CAPACITY(_vec) > 0) { \
+ /* clear vector */ \
+ aFree(VECTOR_DATA(_vec)); VECTOR_DATA(_vec) = NULL; /* free data */ \
+ VECTOR_CAPACITY(_vec) = 0; /* clear capacity */ \
+ VECTOR_LENGTH(_vec) = 0; /* clear length */ \
+ } else if ((_n) < VECTOR_CAPACITY(_vec)) { \
+ /* reduce size */ \
+ VECTOR_DATA(_vec) = aRealloc(VECTOR_DATA(_vec), (_n)*sizeof(VECTOR_FIRST(_vec))); /* reallocate */ \
+ VECTOR_CAPACITY(_vec) = (_n); /* update capacity */ \
+ if (VECTOR_LENGTH(_vec) > (_n)) \
+ VECTOR_LENGTH(_vec) = (_n); /* update length */ \
} \
- }while(0)
-
-/// Ensures that the array has the target number of empty positions.
-/// Increases the capacity in multiples of __step.
-///
-/// @param __vec Vector
-/// @param __n Empty positions
-/// @param __step Increase
-#define VECTOR_ENSURE(__vec,__n,__step) \
- do{ \
- size_t _empty_ = VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec); \
- if( (__n) > _empty_ ) { \
- while( (__n) > _empty_ ) _empty_ += (__step); \
- VECTOR_RESIZE(__vec,_empty_+VECTOR_LENGTH(__vec)); \
+ } while(false)
+
+/**
+ * Ensures that the array has the target number of empty positions.
+ *
+ * Increases the capacity in multiples of _step.
+ *
+ * @param _vec Vector.
+ * @param _n Desired empty positions.
+ * @param _step Increase.
+ */
+#define VECTOR_ENSURE(_vec, _n, _step) \
+ do { \
+ int _empty_ = VECTOR_CAPACITY(_vec)-VECTOR_LENGTH(_vec); \
+ if ((_n) > _empty_) { \
+ while ((_n) > _empty_) \
+ _empty_ += (_step); \
+ VECTOR_RESIZE(_vec, _empty_+VECTOR_LENGTH(_vec)); \
} \
- }while(0)
-
-/// Inserts a zeroed value in the target index.
-/// Assumes the index is valid and there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __idx Index
-#define VECTOR_INSERTZEROED(__vec,__idx) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
- memset(&VECTOR_INDEX(__vec,__idx), 0, sizeof(VECTOR_INDEX(__vec,__idx))); /* set zeroed value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
-
-/// Inserts a value in the target index. (using the '=' operator)
-/// Assumes the index is valid and there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __idx Index
-/// @param __val Value
-#define VECTOR_INSERT(__vec,__idx,__val) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
- VECTOR_INDEX(__vec,__idx) = (__val); /* set value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
-
-/// Inserts a value in the target index. (using memcpy)
-/// Assumes the index is valid and there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __idx Index
-/// @param __val Value
-#define VECTOR_INSERTCOPY(__vec,__idx,__val) \
- VECTOR_INSERTARRAY(__vec,__idx,&(__val),1)
-
-/// Inserts the values of the array in the target index. (using memcpy)
-/// Assumes the index is valid and there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __idx Index
-/// @param __pval Array of values
-/// @param __n Number of values
-#define VECTOR_INSERTARRAY(__vec,__idx,__pval,__n) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,(__idx)+(__n)),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
- memcpy(&VECTOR_INDEX(__vec,__idx), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \
- VECTOR_LENGTH(__vec) += (__n); /* increase length */ \
- }while(0)
-
-/// Inserts a zeroed value in the end of the vector.
-/// Assumes there is enough capacity.
-///
-/// @param __vec Vector
-#define VECTOR_PUSHZEROED(__vec) \
- do{ \
- memset(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), 0, sizeof(VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)))); /* set zeroed value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
-
-/// Inserts a value in the end of the vector. (using the '=' operator)
-/// Assumes there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __val Value
-#define VECTOR_PUSH(__vec,__val) \
- do{ \
- VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)) = (__val); /* set value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
-
-/// Inserts a value in the end of the vector. (using memcpy)
-/// Assumes there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __val Value
-#define VECTOR_PUSHCOPY(__vec,__val) \
- VECTOR_PUSHARRAY(__vec,&(__val),1)
-
-/// Inserts the values of the array in the end of the vector. (using memcpy)
-/// Assumes there is enough capacity.
-///
-/// @param __vec Vector
-/// @param __pval Array of values
-/// @param __n Number of values
-#define VECTOR_PUSHARRAY(__vec,__pval,__n) \
- do{ \
- memcpy(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \
- VECTOR_LENGTH(__vec) += (__n); /* increase length */ \
- }while(0)
-
-/// Removes and returns the last value of the vector.
-/// Assumes the array is not empty.
-///
-/// @param __vec Vector
-/// @return Removed value
-#define VECTOR_POP(__vec) \
- ( VECTOR_INDEX(__vec,--VECTOR_LENGTH(__vec)) )
-
-/// Removes the last N values of the vector and returns the value of the last pop.
-/// Assumes there are enough values.
-///
-/// @param __vec Vector
-/// @param __n Number of pops
-/// @return Last removed value
-#define VECTOR_POPN(__vec,__n) \
- ( VECTOR_INDEX(__vec,(VECTOR_LENGTH(__vec)-=(__n))) )
-
-/// Removes the target index from the vector.
-/// Assumes the index is valid and there are enough values.
-///
-/// @param __vec Vector
-/// @param __idx Index
-#define VECTOR_ERASE(__vec,__idx) \
- VECTOR_ERASEN(__vec,__idx,1)
-
-/// Removes N values from the target index of the vector.
-/// Assumes the index is valid and there are enough values.
-///
-/// @param __vec Vector
-/// @param __idx Index
-/// @param __n Number of values
-#define VECTOR_ERASEN(__vec,__idx,__n) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec)-(__n) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,__idx),&VECTOR_INDEX(__vec,(__idx)+(__n)),(VECTOR_LENGTH(__vec)-((__idx)+(__n)))*sizeof(VECTOR_FIRST(__vec))); \
- VECTOR_LENGTH(__vec) -= (__n); /* decrease length */ \
- }while(0)
-
-/// Clears the vector, freeing allocated data.
-///
-/// @param __vec Vector
-#define VECTOR_CLEAR(__vec) \
- do{ \
- if( VECTOR_CAPACITY(__vec) ) \
- { \
- aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* clear allocated array */ \
- VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \
- VECTOR_LENGTH(__vec) = 0; /* clear length */ \
+ } while(false)
+
+/**
+ * Inserts a zeroed value in the target index.
+ *
+ * Assumes the index is valid and there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ */
+#define VECTOR_INSERTZEROED(_vec, _idx) \
+ do { \
+ if ((_idx) < VECTOR_LENGTH(_vec)) /* move data */ \
+ memmove(&VECTOR_INDEX(_vec, (_idx)+1), &VECTOR_INDEX(_vec, _idx), (VECTOR_LENGTH(_vec)-(_idx))*sizeof(VECTOR_FIRST(_vec))); \
+ memset(&VECTOR_INDEX(_vec, _idx), 0, sizeof(VECTOR_INDEX(_vec, _idx))); /* set zeroed value */ \
+ ++VECTOR_LENGTH(_vec); /* increase length */ \
+ } while(false)
+
+/**
+ * Inserts a value in the target index (using the '=' operator).
+ *
+ * Assumes the index is valid and there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ * @param _val Value.
+ */
+#define VECTOR_INSERT(_vec, _idx, _val) \
+ do { \
+ if ((_idx) < VECTOR_LENGTH(_vec)) /* move data */ \
+ memmove(&VECTOR_INDEX(_vec, (_idx)+1), &VECTOR_INDEX(_vec, _idx), (VECTOR_LENGTH(_vec)-(_idx))*sizeof(VECTOR_FIRST(_vec))); \
+ VECTOR_INDEX(_vec, _idx) = (_val); /* set value */ \
+ ++VECTOR_LENGTH(_vec); /* increase length */ \
+ } while(false)
+
+/**
+ * Inserts a value in the target index (using memcpy).
+ *
+ * Assumes the index is valid and there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ * @param _val Value.
+ */
+#define VECTOR_INSERTCOPY(_vec, _idx, _val) \
+ VECTOR_INSERTARRAY(_vec, _idx, &(_val), 1)
+
+/**
+ * Inserts the values of the array in the target index (using memcpy).
+ *
+ * Assumes the index is valid and there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ * @param _pval Array of values.
+ * @param _n Number of values.
+ */
+#define VECTOR_INSERTARRAY(_vec, _idx, _pval, _n) \
+ do { \
+ if ((_idx) < VECTOR_LENGTH(_vec)) /* move data */ \
+ memmove(&VECTOR_INDEX(_vec, (_idx)+(_n)), &VECTOR_INDEX(_vec, _idx), (VECTOR_LENGTH(_vec)-(_idx))*sizeof(VECTOR_FIRST(_vec))); \
+ memcpy(&VECTOR_INDEX(_vec, _idx), (_pval), (_n)*sizeof(VECTOR_FIRST(_vec))); /* set values */ \
+ VECTOR_LENGTH(_vec) += (_n); /* increase length */ \
+ } while(false)
+
+/**
+ * Inserts a zeroed value in the end of the vector.
+ *
+ * Assumes there is enough capacity.
+ *
+ * @param _vec Vector.
+ */
+#define VECTOR_PUSHZEROED(_vec) \
+ do { \
+ memset(&VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)), 0, sizeof(VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)))); /* set zeroed value */ \
+ ++VECTOR_LENGTH(_vec); /* increase length */ \
+ } while(false)
+
+/**
+ * Appends a value at the end of the vector (using the '=' operator).
+ *
+ * Assumes there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _val Value.
+ */
+#define VECTOR_PUSH(_vec, _val) \
+ do { \
+ VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)) = (_val); /* set value */ \
+ ++VECTOR_LENGTH(_vec); /* increase length */ \
+ }while(false)
+
+/**
+ * Appends a value at the end of the vector (using memcpy).
+ *
+ * Assumes there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _val Value.
+ */
+#define VECTOR_PUSHCOPY(_vec, _val) \
+ VECTOR_PUSHARRAY(_vec, &(_val), 1)
+
+/**
+ * Appends the values of the array at the end of the vector (using memcpy).
+ *
+ * Assumes there is enough capacity.
+ *
+ * @param _vec Vector.
+ * @param _pval Array of values.
+ * @param _n Number of values.
+ */
+#define VECTOR_PUSHARRAY(_vec, _pval, _n) \
+ do { \
+ memcpy(&VECTOR_INDEX(_vec, VECTOR_LENGTH(_vec)), (_pval), (_n)*sizeof(VECTOR_FIRST(_vec))); /* set values */ \
+ VECTOR_LENGTH(_vec) += (_n); /* increase length */ \
+ } while(false)
+
+/**
+ * Removes and returns the last value of the vector.
+ *
+ * Assumes the array is not empty.
+ *
+ * @param _vec Vector.
+ * @return Removed value.
+ */
+#define VECTOR_POP(_vec) \
+ ( VECTOR_INDEX(_vec, --VECTOR_LENGTH(_vec)) )
+
+/**
+ * Removes the last N values of the vector and returns the value of the last pop.
+ *
+ * Assumes there are enough values.
+ *
+ * @param _vec Vector.
+ * @param _n Number of pops.
+ * @return Last removed value.
+ */
+#define VECTOR_POPN(_vec, _n) \
+ ( VECTOR_INDEX(_vec, (VECTOR_LENGTH(_vec) -= (_n))) )
+
+/**
+ * Removes the target index from the vector.
+ *
+ * Assumes the index is valid and there are enough values.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ */
+#define VECTOR_ERASE(_vec, _idx) \
+ VECTOR_ERASEN(_vec, _idx, 1)
+
+/**
+ * Removes N values from the target index of the vector.
+ *
+ * Assumes the index is valid and there are enough values.
+ *
+ * @param _vec Vector.
+ * @param _idx Index.
+ * @param _n Number of values to remove.
+ */
+#define VECTOR_ERASEN(_vec, _idx, _n) \
+ do { \
+ if ((_idx) < VECTOR_LENGTH(_vec)-(_n) ) /* move data */ \
+ memmove(&VECTOR_INDEX(_vec, _idx), &VECTOR_INDEX(_vec, (_idx)+(_n)), (VECTOR_LENGTH(_vec)-((_idx)+(_n)))*sizeof(VECTOR_FIRST(_vec))); \
+ VECTOR_LENGTH(_vec) -= (_n); /* decrease length */ \
+ } while(false)
+
+/**
+ * Clears the vector, freeing allocated data.
+ *
+ * @param _vec Vector.
+ */
+#define VECTOR_CLEAR(_vec) \
+ do { \
+ if (VECTOR_CAPACITY(_vec) > 0) { \
+ aFree(VECTOR_DATA(_vec)); VECTOR_DATA(_vec) = NULL; /* clear allocated array */ \
+ VECTOR_CAPACITY(_vec) = 0; /* clear capacity */ \
+ VECTOR_LENGTH(_vec) = 0; /* clear length */ \
} \
- }while(0)
-
-/////////////////////////////////////////////////////////////////////
-// Binary heap library based on defines. (uses the vector defines above)
-// uses aMalloc, aRealloc, aFree
-// WARNING: BHEAP implementation details affect behaviour of A* pathfinding
-
-/// Declares an anonymous binary heap struct.
-///
-/// @param __type Type of data
-#define BHEAP_DECL(__type) VECTOR_DECL(__type)
-
-/// Declares a named binary heap struct.
-///
-/// @param __name Structure name
-/// @param __type Type of data
-#define BHEAP_STRUCT_DECL(__name,__type) VECTOR_STRUCT_DECL(__name,__type)
-
-/// Declares and initializes an anonymous binary heap variable.
-///
-/// @param __type Type of data
-/// @param __var Variable name
-#define BHEAP_VAR(__type,__var) VECTOR_VAR(__type,__var)
-
-/// Declares and initializes a named binary heap variable.
-///
-/// @param __name Structure name
-/// @param __var Variable name
-#define BHEAP_STRUCT_VAR(__name,__var) VECTOR_STRUCT_VAR(__name,__var)
-
-/// Initializes a heap.
-///
-/// @param __heap Binary heap
-#define BHEAP_INIT(__heap) VECTOR_INIT(__heap)
-
-/// Returns the internal array of values.
-///
-/// @param __heap Binary heap
-/// @return Array of values
-#define BHEAP_DATA(__heap) VECTOR_DATA(__heap)
-
-/// Returns the length of the heap.
-///
-/// @param __heap Binary heap
-/// @return Length
-#define BHEAP_LENGTH(__heap) VECTOR_LENGTH(__heap)
-
-/// Returns the capacity of the heap.
-///
-/// @param __heap Binary heap
-/// @return Capacity
-#define BHEAP_CAPACITY(__heap) VECTOR_CAPACITY(__heap)
-
-/// Ensures that the heap has the target number of empty positions.
-/// Increases the capacity in multiples of __step.
-///
-/// @param __heap Binary heap
-/// @param __n Empty positions
-/// @param __step Increase
-#define BHEAP_ENSURE(__heap,__n,__step) VECTOR_ENSURE(__heap,__n,__step)
-
-/// Returns the top value of the heap.
-/// Assumes the heap is not empty.
-///
-/// @param __heap Binary heap
-/// @return Value at the top
-#define BHEAP_PEEK(__heap) VECTOR_INDEX(__heap,0)
-
-/// Inserts a value in the heap. (using the '=' operator)
-/// Assumes there is enough capacity.
-///
-/// The comparator takes two values as arguments, returns:
-/// - negative if the first value is on the top
-/// - positive if the second value is on the top
-/// - 0 if they are equal
-///
-/// @param __heap Binary heap
-/// @param __val Value
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_PUSH(__heap,__val,__topcmp,__swp) \
- do{ \
- size_t _i_ = VECTOR_LENGTH(__heap); \
- VECTOR_PUSH(__heap,__val); /* insert at end */ \
- while( _i_ ) \
- { /* restore heap property in parents */ \
- size_t _parent_ = (_i_-1)/2; \
- if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \
+ } while(false)
+
+/**
+ * Binary heap library based on defines.
+ *
+ * Uses the VECTOR defines above.
+ * Uses aMalloc, aRealloc, aFree.
+ *
+ * @warning
+ * BHEAP implementation details affect behaviour of A* pathfinding.
+ */
+
+/**
+ * Declares an anonymous binary heap struct.
+ *
+ * @param _type Type of data.
+ */
+#define BHEAP_DECL(_type) \
+ VECTOR_DECL(_type)
+
+/**
+ * Declares a named binary heap struct.
+ *
+ * @param _name Structure name.
+ * @param _type Type of data.
+ */
+#define BHEAP_STRUCT_DECL(_name, _type) \
+ VECTOR_STRUCT_DECL(_name, _type)
+
+/**
+ * Declares and initializes an anonymous binary heap variable.
+ *
+ * @param _type Type of data.
+ * @param _var Variable name.
+ */
+#define BHEAP_VAR(_type, _var) \
+ VECTOR_VAR(_type, _var)
+
+/**
+ * Declares and initializes a named binary heap variable.
+ *
+ * @param _name Structure name.
+ * @param _var Variable name.
+ */
+#define BHEAP_STRUCT_VAR(_name, _var) \
+ VECTOR_STRUCT_VAR(_name, _var)
+
+/**
+ * Initializes a heap.
+ *
+ * @param _heap Binary heap.
+ */
+#define BHEAP_INIT(_heap) \
+ VECTOR_INIT(_heap)
+
+/**
+ * Returns the internal array of values.
+ *
+ * @param _heap Binary heap.
+ * @return Internal array of values.
+ */
+#define BHEAP_DATA(_heap) \
+ VECTOR_DATA(_heap)
+
+/**
+ * Returns the length of the heap.
+ *
+ * @param _heap Binary heap.
+ * @return Length.
+ */
+#define BHEAP_LENGTH(_heap) \
+ VECTOR_LENGTH(_heap)
+
+/**
+ * Returns the capacity of the heap.
+ *
+ * @param _heap Binary heap.
+ * @return Capacity.
+ */
+#define BHEAP_CAPACITY(_heap) \
+ VECTOR_CAPACITY(_heap)
+
+/**
+ * Ensures that the heap has the target number of empty positions.
+ *
+ * Increases the capacity in multiples of _step.
+ *
+ * @param _heap Binary heap.
+ * @param _n Required empty positions.
+ * @param _step Increase.
+ */
+#define BHEAP_ENSURE(_heap, _n, _step) \
+ VECTOR_ENSURE(_heap, _n, _step)
+
+/**
+ * Returns the top value of the heap.
+ *
+ * Assumes the heap is not empty.
+ *
+ * @param _heap Binary heap.
+ * @return Value at the top.
+ */
+#define BHEAP_PEEK(_heap) \
+ VECTOR_INDEX(_heap, 0)
+
+/**
+ * Inserts a value in the heap (using the '=' operator).
+ *
+ * Assumes there is enough capacity.
+ *
+ * The comparator takes two values as arguments, returns:
+ * - negative if the first value is on the top
+ * - positive if the second value is on the top
+ * - 0 if they are equal
+ *
+ * @param _heap Binary heap.
+ * @param _val Value.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_PUSH(_heap, _val, _topcmp, _swp) \
+ do { \
+ int _i_ = VECTOR_LENGTH(_heap); \
+ VECTOR_PUSH(_heap, _val); /* insert at end */ \
+ while (_i_ > 0) { \
+ /* restore heap property in parents */ \
+ int _parent_ = (_i_-1)/2; \
+ if (_topcmp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)) < 0) \
break; /* done */ \
- __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \
+ _swp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)); \
_i_ = _parent_; \
} \
- }while(0)
-
-/// See BHEAP_PUSH. Version used by A* implementation, matching client bheap.
-///
-/// @param __heap Binary heap
-/// @param __val Value
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_PUSH2(__heap,__val,__topcmp,__swp) \
- do{ \
- size_t _i_ = VECTOR_LENGTH(__heap); \
- VECTOR_PUSH(__heap,__val); /* insert at end */ \
- BHEAP_SIFTDOWN(__heap,0,_i_,__topcmp,__swp); \
- }while(0)
-
-/// Removes the top value of the heap. (using the '=' operator)
-/// Assumes the heap is not empty.
-///
-/// The comparator takes two values as arguments, returns:
-/// - negative if the first value is on the top
-/// - positive if the second value is on the top
-/// - 0 if they are equal
-///
-/// @param __heap Binary heap
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_POP(__heap,__topcmp,__swp) BHEAP_POPINDEX(__heap,0,__topcmp,__swp)
-
-/// See BHEAP_POP. Version used by A* implementation, matching client bheap.
-///
-/// @param __heap Binary heap
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_POP2(__heap,__topcmp,__swp) \
- do{ \
- VECTOR_INDEX(__heap,0) = VECTOR_POP(__heap); /* put last at index */ \
- if( !VECTOR_LENGTH(__heap) ) /* removed last, nothing to do */ \
+ } while(false)
+
+/**
+ * Variant of BHEAP_PUSH used by A* implementation, matching client bheap.
+ *
+ * @see BHEAP_PUSH.
+ *
+ * @param _heap Binary heap.
+ * @param _val Value.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_PUSH2(_heap, _val, _topcmp, _swp) \
+ do { \
+ int _i_ = VECTOR_LENGTH(_heap); \
+ VECTOR_PUSH(_heap, _val); /* insert at end */ \
+ BHEAP_SIFTDOWN(_heap, 0, _i_, _topcmp, _swp); \
+ } while(false)
+
+/**
+ * Removes the top value of the heap (using the '=' operator).
+ *
+ * Assumes the heap is not empty.
+ *
+ * The comparator takes two values as arguments, returns:
+ * - negative if the first value is on the top
+ * - positive if the second value is on the top
+ * - 0 if they are equal
+ *
+ * @param _heap Binary heap.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_POP(_heap, _topcmp, _swp) \
+ BHEAP_POPINDEX(_heap, 0, _topcmp, _swp)
+
+/**
+ * Variant of BHEAP_POP used by A* implementation, matching client bheap.
+ *
+ * @see BHEAP_POP.
+ *
+ * @param _heap Binary heap.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_POP2(_heap, _topcmp, _swp) \
+ do { \
+ VECTOR_INDEX(_heap, 0) = VECTOR_POP(_heap); /* put last at index */ \
+ if (VECTOR_LENGTH(_heap) == 0) /* removed last, nothing to do */ \
break; \
- BHEAP_SIFTUP(__heap,0,__topcmp,__swp); \
- }while(0)
-
-/// Removes the target value of the heap. (using the '=' operator)
-/// Assumes the index exists.
-///
-/// The comparator takes two values as arguments, returns:
-/// - negative if the first value is on the top
-/// - positive if the second value is on the top
-/// - 0 if they are equal
-///
-/// @param __heap Binary heap
-/// @param __idx Index
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_POPINDEX(__heap,__idx,__topcmp,__swp) \
- do{ \
- size_t _i_ = __idx; \
- VECTOR_INDEX(__heap,__idx) = VECTOR_POP(__heap); /* put last at index */ \
- if( _i_ >= VECTOR_LENGTH(__heap)) /* removed last, nothing to do */ \
+ BHEAP_SIFTUP(_heap, 0, _topcmp, _swp); \
+ } while(false)
+
+/**
+ * Removes the target value of the heap (using the '=' operator).
+ *
+ * Assumes the index exists.
+ *
+ * The comparator takes two values as arguments, returns:
+ * - negative if the first value is on the top
+ * - positive if the second value is on the top
+ * - 0 if they are equal
+ *
+ * @param _heap Binary heap.
+ * @param _idx Index.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_POPINDEX(_heap, _idx, _topcmp, _swp) \
+ do { \
+ int _i_ = _idx; \
+ VECTOR_INDEX(_heap, _idx) = VECTOR_POP(_heap); /* put last at index */ \
+ if (_i_ >= VECTOR_LENGTH(_heap)) /* removed last, nothing to do */ \
break; \
- while( _i_ ) \
- { /* restore heap property in parents */ \
- size_t _parent_ = (_i_-1)/2; \
- if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \
+ while (_i_ > 0) { \
+ /* restore heap property in parents */ \
+ int _parent_ = (_i_-1)/2; \
+ if (_topcmp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)) < 0) \
break; /* done */ \
- __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \
+ _swp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i_)); \
_i_ = _parent_; \
} \
- while( _i_ < VECTOR_LENGTH(__heap) ) \
- { /* restore heap property in childs */ \
- size_t _lchild_ = _i_*2 + 1; \
- size_t _rchild_ = _i_*2 + 2; \
- if( (_lchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)) <= 0) && \
- (_rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)) <= 0) ) \
+ while (_i_ < VECTOR_LENGTH(_heap)) { \
+ /* restore heap property in children */ \
+ int _lchild_ = _i_*2 + 1; \
+ int _rchild_ = _i_*2 + 2; \
+ if ((_lchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _lchild_)) <= 0) \
+ && (_rchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _rchild_)) <= 0)) { \
break; /* done */ \
- else if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) <= 0 ) \
- { /* left child */ \
- __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \
+ } else if (_rchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _lchild_), VECTOR_INDEX(_heap, _rchild_)) <= 0) { \
+ /* left child */ \
+ _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _lchild_)); \
_i_ = _lchild_; \
- } \
- else \
- { /* right child */ \
- __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \
+ } else { \
+ /* right child */ \
+ _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _rchild_)); \
_i_ = _rchild_; \
} \
} \
- }while(0)
-
-/// Follow path up towards (but not all the way to) the root, swapping nodes until finding
-/// a place where the new item that was placed at __idx fits.
-/// Only goes as high as __startidx (usually 0).
-///
-/// @param __heap Binary heap
-/// @param __startidx Index of an ancestor of __idx
-/// @param __idx Index of an inserted element
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_SIFTDOWN(__heap,__startidx,__idx,__topcmp,__swp) \
- do{ \
- size_t _i2_ = __idx; \
- while( _i2_ > __startidx ) \
- { /* restore heap property in parents */ \
- size_t _parent_ = (_i2_-1)/2; \
- if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i2_)) <= 0 ) \
+ } while(false)
+
+/**
+ * Follow path up towards (but not all the way to) the root, swapping nodes
+ * until finding a place where the new item that was placed at _idx fits.
+ *
+ * Only goes as high as _startidx (usually 0).
+ *
+ * @param _heap Binary heap.
+ * @param _startidx Index of an ancestor of _idx.
+ * @param _idx Index of an inserted element.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_SIFTDOWN(_heap, _startidx, _idx, _topcmp, _swp) \
+ do { \
+ int _i2_ = _idx; \
+ while (_i2_ > _startidx) { \
+ /* restore heap property in parents */ \
+ int _parent_ = (_i2_-1)/2; \
+ if (_topcmp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i2_)) <= 0) \
break; /* done */ \
- __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i2_)); \
+ _swp(VECTOR_INDEX(_heap, _parent_), VECTOR_INDEX(_heap, _i2_)); \
_i2_ = _parent_; \
} \
- }while(0)
-
-/// Repeatedly swap the smaller child with parent, after placing a new item at __idx.
-///
-/// @param __heap Binary heap
-/// @param __idx Index of an inserted element
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_SIFTUP(__heap,__idx,__topcmp,__swp) \
- do{ \
- size_t _i_ = __idx; \
- size_t _lchild_ = _i_*2 + 1; \
- while( _lchild_ < VECTOR_LENGTH(__heap) ) \
- { /* restore heap property in childs */ \
- size_t _rchild_ = _i_*2 + 2; \
- if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) < 0 ) \
- { /* left child */ \
- __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \
+ } while(false)
+
+/**
+ * Repeatedly swap the smaller child with parent, after placing a new item at _idx.
+ *
+ * @param _heap Binary heap.
+ * @param _idx Index of an inserted element.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_SIFTUP(_heap, _idx, _topcmp, _swp) \
+ do { \
+ int _i_ = _idx; \
+ int _lchild_ = _i_*2 + 1; \
+ while (_lchild_ < VECTOR_LENGTH(_heap)) { \
+ /* restore heap property in children */ \
+ int _rchild_ = _i_*2 + 2; \
+ if (_rchild_ >= VECTOR_LENGTH(_heap) || _topcmp(VECTOR_INDEX(_heap, _lchild_), VECTOR_INDEX(_heap, _rchild_)) < 0) { \
+ /* left child */ \
+ _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _lchild_)); \
_i_ = _lchild_; \
- } \
- else \
- { /* right child */ \
- __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \
+ } else { \
+ /* right child */ \
+ _swp(VECTOR_INDEX(_heap, _i_), VECTOR_INDEX(_heap, _rchild_)); \
_i_ = _rchild_; \
} \
_lchild_ = _i_*2 + 1; \
} \
- BHEAP_SIFTDOWN(__heap,__idx,_i_,__topcmp,__swp); \
- }while(0)
-
-/// Call this after modifying the item at __idx__ to restore the heap
-///
-/// @param __heap Binary heap
-/// @param __idx Index
-/// @param __topcmp Comparator
-/// @param __swp Swapper
-#define BHEAP_UPDATE(__heap,__idx,__topcmp,__swp) \
- do{ \
- BHEAP_SIFTDOWN(__heap,0,__idx,__topcmp,__swp); \
- BHEAP_SIFTUP(__heap,__idx,__topcmp,__swp); \
- }while(0)
-
-/// Clears the binary heap, freeing allocated data.
-///
-/// @param __heap Binary heap
-#define BHEAP_CLEAR(__heap) VECTOR_CLEAR(__heap)
-
-/// Generic comparator for a min-heap. (minimum value at top)
-/// Returns -1 if v1 is smaller, 1 if v2 is smaller, 0 if equal.
-///
-/// @param v1 First value
-/// @param v2 Second value
-/// @return negative if v1 is top, positive if v2 is top, 0 if equal
-#define BHEAP_MINTOPCMP(v1,v2) ( v1 == v2 ? 0 : v1 < v2 ? -1 : 1 )
-
-/// Generic comparator for a max-heap. (maximum value at top)
-/// Returns -1 if v1 is bigger, 1 if v2 is bigger, 0 if equal.
-///
-/// @param v1 First value
-/// @param v2 Second value
-/// @return negative if v1 is top, positive if v2 is top, 0 if equal
-#define BHEAP_MAXTOPCMP(v1,v2) ( v1 == v2 ? 0 : v1 > v2 ? -1 : 1 )
+ BHEAP_SIFTDOWN(_heap, _idx, _i_, _topcmp, _swp); \
+ } while(false)
+
+/**
+ * Restores a heap (after modifying the item at _idx).
+ *
+ * @param _heap Binary heap.
+ * @param _idx Index.
+ * @param _topcmp Comparator.
+ * @param _swp Swapper.
+ */
+#define BHEAP_UPDATE(_heap, _idx, _topcmp, _swp) \
+ do { \
+ BHEAP_SIFTDOWN(_heap, 0, _idx, _topcmp, _swp); \
+ BHEAP_SIFTUP(_heap, _idx, _topcmp, _swp); \
+ } while(false)
+
+/**
+ * Clears the binary heap, freeing allocated data.
+ *
+ * @param _heap Binary heap.
+ */
+#define BHEAP_CLEAR(_heap) \
+ VECTOR_CLEAR(_heap)
+
+/**
+ * Generic comparator for a min-heap (minimum value at top).
+ *
+ * Returns -1 if v1 is smaller, 1 if v2 is smaller, 0 if equal.
+ *
+ * @warning
+ * Arguments may be evaluted more than once.
+ *
+ * @param v1 First value.
+ * @param v2 Second value.
+ * @return negative if v1 is top, positive if v2 is top, 0 if equal.
+ */
+#define BHEAP_MINTOPCMP(v1, v2) \
+ ( v1 == v2 ? 0 : v1 < v2 ? -1 : 1 )
+
+/**
+ * Generic comparator for a max-heap (maximum value at top).
+ *
+ * Returns -1 if v1 is bigger, 1 if v2 is bigger, 0 if equal.
+ *
+ * @warning
+ * Arguments may be evaluted more than once.
+ *
+ * @param v1 First value.
+ * @param v2 Second value.
+ * @return negative if v1 is top, positive if v2 is top, 0 if equal.
+ */
+#define BHEAP_MAXTOPCMP(v1, v2) \
+ ( v1 == v2 ? 0 : v1 > v2 ? -1 : 1 )
#endif /* COMMON_DB_H */
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 012eec935..73d4510a1 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -198,7 +198,7 @@
#define JOBL_BABY 0x2000 //8192
#define JOBL_THIRD 0x4000 //16384
-struct HPluginData;
+struct hplugin_data_store;
enum item_types {
IT_HEALING = 0,
@@ -661,10 +661,7 @@ struct guild {
unsigned short instances;
struct channel_data *channel;
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
struct guild_castle {
diff --git a/src/common/socket.c b/src/common/socket.c
index de8ca4682..f1318ab47 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -623,7 +623,6 @@ static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseF
sockt->session[fd]->rdata_tick = sockt->last_tick;
sockt->session[fd]->session_data = NULL;
sockt->session[fd]->hdata = NULL;
- sockt->session[fd]->hdatac = 0;
return 0;
}
@@ -638,16 +637,7 @@ static void delete_session(int fd)
aFree(sockt->session[fd]->wdata);
if( sockt->session[fd]->session_data )
aFree(sockt->session[fd]->session_data);
- if (sockt->session[fd]->hdata) {
- unsigned int i;
- for(i = 0; i < sockt->session[fd]->hdatac; i++) {
- if( sockt->session[fd]->hdata[i]->flag.free ) {
- aFree(sockt->session[fd]->hdata[i]->data);
- }
- aFree(sockt->session[fd]->hdata[i]);
- }
- aFree(sockt->session[fd]->hdata);
- }
+ HPM->data_store_destroy(&sockt->session[fd]->hdata);
aFree(sockt->session[fd]);
sockt->session[fd] = NULL;
}
@@ -977,7 +967,7 @@ static int connect_check_(uint32 ip)
// Search the allow list
for( i=0; i < access_allownum; ++i ){
- if( (ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask) ){
+ if (SUBNET_MATCH(ip, access_allow[i].ip, access_allow[i].mask)) {
if( access_debug ){
ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
CONVIP(ip),
@@ -990,7 +980,7 @@ static int connect_check_(uint32 ip)
}
// Search the deny list
for( i=0; i < access_denynum; ++i ){
- if( (ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask) ){
+ if (SUBNET_MATCH(ip, access_deny[i].ip, access_deny[i].mask)) {
if( access_debug ){
ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
CONVIP(ip),
@@ -1226,20 +1216,9 @@ void socket_final(void)
aFree(sockt->session);
- if (sockt->lan_subnet)
- aFree(sockt->lan_subnet);
- sockt->lan_subnet = NULL;
- sockt->lan_subnet_count = 0;
-
- if (sockt->allowed_ip)
- aFree(sockt->allowed_ip);
- sockt->allowed_ip = NULL;
- sockt->allowed_ip_count = 0;
-
- if (sockt->trusted_ip)
- aFree(sockt->trusted_ip);
- sockt->trusted_ip = NULL;
- sockt->trusted_ip_count = 0;
+ VECTOR_CLEAR(sockt->lan_subnets);
+ VECTOR_CLEAR(sockt->allowed_ips);
+ VECTOR_CLEAR(sockt->trusted_ips);
}
/// Closes a socket.
@@ -1615,13 +1594,13 @@ void send_shortlist_do_sends()
uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info)
{
int i;
- ARR_FIND(0, sockt->lan_subnet_count, i, (sockt->lan_subnet[i].ip & sockt->lan_subnet[i].mask) == (ip & sockt->lan_subnet[i].mask));
- if (i < sockt->lan_subnet_count) {
+ ARR_FIND(0, VECTOR_LENGTH(sockt->lan_subnets), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->lan_subnets, i).ip, VECTOR_INDEX(sockt->lan_subnets, i).mask));
+ if (i != VECTOR_LENGTH(sockt->lan_subnets)) {
if (info) {
- info->ip = sockt->lan_subnet[i].ip;
- info->mask = sockt->lan_subnet[i].mask;
+ info->ip = VECTOR_INDEX(sockt->lan_subnets, i).ip;
+ info->mask = VECTOR_INDEX(sockt->lan_subnets, i).mask;
}
- return sockt->lan_subnet[i].ip;
+ return VECTOR_INDEX(sockt->lan_subnets, i).ip;
}
if (info) {
info->ip = info->mask = 0;
@@ -1639,8 +1618,8 @@ uint32 socket_lan_subnet_check(uint32 ip, struct s_subnet *info)
bool socket_allowed_ip_check(uint32 ip)
{
int i;
- ARR_FIND(0, sockt->allowed_ip_count, i, (sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == (ip & sockt->allowed_ip[i].mask) );
- if (i < sockt->allowed_ip_count)
+ ARR_FIND(0, VECTOR_LENGTH(sockt->allowed_ips), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->allowed_ips, i).ip, VECTOR_INDEX(sockt->allowed_ips, i).mask));
+ if (i != VECTOR_LENGTH(sockt->allowed_ips))
return true;
return sockt->trusted_ip_check(ip); // If an address is trusted, it's automatically also allowed.
}
@@ -1655,8 +1634,8 @@ bool socket_allowed_ip_check(uint32 ip)
bool socket_trusted_ip_check(uint32 ip)
{
int i;
- ARR_FIND(0, sockt->trusted_ip_count, i, (sockt->trusted_ip[i].ip & sockt->trusted_ip[i].mask) == (ip & sockt->trusted_ip[i].mask));
- if (i < sockt->trusted_ip_count)
+ ARR_FIND(0, VECTOR_LENGTH(sockt->trusted_ips), i, SUBNET_MATCH(ip, VECTOR_INDEX(sockt->trusted_ips, i).ip, VECTOR_INDEX(sockt->trusted_ips, i).mask));
+ if (i != VECTOR_LENGTH(sockt->trusted_ips))
return true;
return false;
}
@@ -1667,39 +1646,38 @@ bool socket_trusted_ip_check(uint32 ip)
* Entries will be appended to the variable-size array pointed to by list/count.
*
* @param[in] t The list to parse.
- * @param[in,out] list Pointer to the head of the output array to append to. Must not be NULL (but the array may be empty).
- * @param[in,out] count Pointer to the counter of the output array to append to. Must not be NULL (but it may contain zero).
+ * @param[in,out] list Vector to append to. Must not be NULL (but the vector may be empty).
* @param[in] filename Current filename, for output/logging reasons.
* @param[in] groupname Current group name, for output/logging reasons.
* @return The amount of entries read, zero in case of errors.
*/
-int socket_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname)
+int socket_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname)
{
int i, len;
char ipbuf[64], maskbuf[64];
nullpo_retr(0, list);
- nullpo_retr(0, count);
if (t == NULL)
return 0;
len = libconfig->setting_length(t);
+ VECTOR_ENSURE(*list, len, 1);
for (i = 0; i < len; ++i) {
const char *subnet = libconfig->setting_get_string_elem(t, i);
- struct s_subnet *l = NULL;
+ struct s_subnet *entry = NULL;
if (sscanf(subnet, "%63[^:]:%63[^:]", ipbuf, maskbuf) != 2) {
ShowWarning("Invalid IP:Subnet entry in configuration file %s: '%s' (%s)\n", filename, subnet, groupname);
+ continue;
}
- RECREATE(*list, struct s_subnet, *count + 1);
- l = *list;
- l[*count].ip = sockt->str2ip(ipbuf);
- l[*count].mask = sockt->str2ip(maskbuf);
- ++*count;
+ VECTOR_PUSHZEROED(*list);
+ entry = &VECTOR_LAST(*list);
+ entry->ip = sockt->str2ip(ipbuf);
+ entry->mask = sockt->str2ip(maskbuf);
}
- return *count;
+ return (int)VECTOR_LENGTH(*list);
}
/**
@@ -1718,45 +1696,29 @@ void socket_net_config_read(const char *filename)
return;
}
- if (sockt->lan_subnet) {
- aFree(sockt->lan_subnet);
- sockt->lan_subnet = NULL;
- }
- sockt->lan_subnet_count = 0;
- if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "lan_subnets"), &sockt->lan_subnet, &sockt->lan_subnet_count, filename, "lan_subnets") > 0)
- ShowStatus("Read information about %d LAN subnets.\n", sockt->lan_subnet_count);
+ VECTOR_CLEAR(sockt->lan_subnets);
+ if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "lan_subnets"), &sockt->lan_subnets, filename, "lan_subnets") > 0)
+ ShowStatus("Read information about %d LAN subnets.\n", (int)VECTOR_LENGTH(sockt->lan_subnets));
- if (sockt->trusted_ip) {
- aFree(sockt->trusted_ip);
- sockt->trusted_ip = NULL;
- }
- sockt->trusted_ip_count = 0;
- if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "trusted"), &sockt->trusted_ip, &sockt->trusted_ip_count, filename, "trusted") > 0)
- ShowStatus("Read information about %d trusted IP ranges.\n", sockt->trusted_ip_count);
- for (i = 0; i < sockt->allowed_ip_count; ++i) {
- if ((sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == 0) {
- ShowError("Using a wildcard IP range in the trusted server IPs is NOT RECOMMENDED.\n");
- ShowNotice("Please edit your '%s' trusted list to fit your network configuration.\n", filename);
- break;
- }
+ VECTOR_CLEAR(sockt->trusted_ips);
+ if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "trusted"), &sockt->trusted_ips, filename, "trusted") > 0)
+ ShowStatus("Read information about %d trusted IP ranges.\n", (int)VECTOR_LENGTH(sockt->trusted_ips));
+ ARR_FIND(0, VECTOR_LENGTH(sockt->trusted_ips), i, SUBNET_MATCH(0, VECTOR_INDEX(sockt->trusted_ips, i).ip, VECTOR_INDEX(sockt->trusted_ips, i).mask));
+ if (i != VECTOR_LENGTH(sockt->trusted_ips)) {
+ ShowError("Using a wildcard IP range in the trusted server IPs is NOT RECOMMENDED.\n");
+ ShowNotice("Please edit your '%s' trusted list to fit your network configuration.\n", filename);
}
- if (sockt->allowed_ip) {
- aFree(sockt->allowed_ip);
- sockt->allowed_ip = NULL;
- }
- sockt->allowed_ip_count = 0;
- if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "allowed"), &sockt->allowed_ip, &sockt->allowed_ip_count, filename, "allowed") > 0)
- ShowStatus("Read information about %d allowed server IP ranges.\n", sockt->allowed_ip_count);
- if (sockt->allowed_ip_count == 0) {
+ VECTOR_CLEAR(sockt->allowed_ips);
+ if (sockt->net_config_read_sub(libconfig->lookup(&network_config, "allowed"), &sockt->allowed_ips, filename, "allowed") > 0)
+ ShowStatus("Read information about %d allowed server IP ranges.\n", (int)VECTOR_LENGTH(sockt->allowed_ips));
+ if (VECTOR_LENGTH(sockt->allowed_ips) + VECTOR_LENGTH(sockt->trusted_ips) == 0) {
ShowError("No allowed server IP ranges configured. This server won't be able to accept connections from any char servers.\n");
}
- for (i = 0; i < sockt->allowed_ip_count; ++i) {
- if ((sockt->allowed_ip[i].ip & sockt->allowed_ip[i].mask) == 0) {
- ShowWarning("Using a wildcard IP range in the allowed server IPs is NOT RECOMMENDED.\n");
- ShowNotice("Please edit your '%s' allowed list to fit your network configuration.\n", filename);
- break;
- }
+ ARR_FIND(0, VECTOR_LENGTH(sockt->allowed_ips), i, SUBNET_MATCH(0, VECTOR_INDEX(sockt->allowed_ips, i).ip, VECTOR_INDEX(sockt->allowed_ips, i).mask));
+ if (i != VECTOR_LENGTH(sockt->allowed_ips)) {
+ ShowWarning("Using a wildcard IP range in the allowed server IPs is NOT RECOMMENDED.\n");
+ ShowNotice("Please edit your '%s' allowed list to fit your network configuration.\n", filename);
}
libconfig->destroy(&network_config);
return;
@@ -1773,12 +1735,9 @@ void socket_defaults(void) {
memset(&sockt->addr_, 0, sizeof(sockt->addr_));
sockt->naddr_ = 0;
/* */
- sockt->lan_subnet_count = 0;
- sockt->lan_subnet = NULL;
- sockt->allowed_ip_count = 0;
- sockt->allowed_ip = NULL;
- sockt->trusted_ip_count = 0;
- sockt->trusted_ip = NULL;
+ VECTOR_INIT(sockt->lan_subnets);
+ VECTOR_INIT(sockt->allowed_ips);
+ VECTOR_INIT(sockt->trusted_ips);
sockt->init = socket_init;
sockt->final = socket_final;
diff --git a/src/common/socket.h b/src/common/socket.h
index a995bffc8..426f8e4bb 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -7,6 +7,7 @@
#include "common/hercules.h"
#include "common/conf.h"
+#include "common/db.h"
#ifdef WIN32
# include "common/winapi.h"
@@ -17,7 +18,7 @@
# include <sys/types.h>
#endif
-struct HPluginData;
+struct hplugin_data_store;
#define FIFOSIZE_SERVERLINK 256*1024
@@ -104,9 +105,7 @@ struct socket_data {
ParseFunc func_parse;
void* session_data; // stores application-specific data related to the session
-
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store.
};
struct hSockOpt {
@@ -120,6 +119,9 @@ struct s_subnet {
uint32 mask;
};
+/// A vector of subnets/IP ranges.
+VECTOR_STRUCT_DECL(s_subnet_vector, struct s_subnet);
+
/// Use a shortlist of sockets instead of iterating all sessions for sockets
/// that have data to send or need eof handling.
/// Adapted to use a static array instead of a linked list.
@@ -131,6 +133,11 @@ struct s_subnet {
#define CONVIP(ip) ((ip)>>24)&0xFF,((ip)>>16)&0xFF,((ip)>>8)&0xFF,((ip)>>0)&0xFF
#define MAKEIP(a,b,c,d) ((uint32)( ( ( (a)&0xFF ) << 24 ) | ( ( (b)&0xFF ) << 16 ) | ( ( (c)&0xFF ) << 8 ) | ( ( (d)&0xFF ) << 0 ) ))
+/// Applies a subnet mask to an IP
+#define APPLY_MASK(ip, mask) ((ip)&(mask))
+/// Verifies the match between two IPs, with a subnet mask applied
+#define SUBNET_MATCH(ip1, ip2, mask) (APPLY_MASK((ip1), (mask)) == APPLY_MASK((ip2), (mask)))
+
/**
* Socket.c interface, mostly for reading however.
**/
@@ -145,12 +152,9 @@ struct socket_interface {
struct socket_data **session;
- struct s_subnet *lan_subnet; ///< LAN subnets array
- int lan_subnet_count; ///< LAN subnets count
- struct s_subnet *trusted_ip; ///< Trusted IP ranges array
- int trusted_ip_count; ///< Trusted IP ranges count
- struct s_subnet *allowed_ip; ///< Allowed server IP ranges array
- int allowed_ip_count; ///< Allowed server IP ranges count
+ struct s_subnet_vector lan_subnets; ///< LAN subnets.
+ struct s_subnet_vector trusted_ips; ///< Trusted IP ranges
+ struct s_subnet_vector allowed_ips; ///< Allowed server IP ranges
/* */
void (*init) (void);
@@ -189,7 +193,7 @@ struct socket_interface {
uint32 (*lan_subnet_check) (uint32 ip, struct s_subnet *info);
bool (*allowed_ip_check) (uint32 ip);
bool (*trusted_ip_check) (uint32 ip);
- int (*net_config_read_sub) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*net_config_read_sub) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
void (*net_config_read) (const char *filename);
};
diff --git a/src/common/timer.c b/src/common/timer.c
index 793706511..f6ce00d54 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -239,6 +239,10 @@ int64 timer_gettick(void) {
/// Adds a timer to the timer_heap
static void push_timer_heap(int tid) {
BHEAP_ENSURE(timer_heap, 1, 256);
+#ifdef __clang_analyzer__ // Clang's static analyzer warns that BHEAP_ENSURE might set BHEAP_DATA(timer_heap) to NULL.
+#include "assert.h"
+ assert(BHEAP_DATA(timer_heap) != NULL);
+#endif // __clang_analyzer__
BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP, swap);
}
@@ -348,14 +352,21 @@ int64 timer_addtick(int tid, int64 tick) {
return timer->settick(tid, timer_data[tid].tick+tick);
}
-/// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one).
-/// Returns the new tick value, or -1 if it fails.
-int64 timer_settick(int tid, int64 tick) {
- size_t i;
+/**
+ * Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one).
+ *
+ * @param tid The timer ID.
+ * @param tick New expiration time.
+ * @return The new tick value.
+ * @retval -1 in case of failure.
+ */
+int64 timer_settick(int tid, int64 tick)
+{
+ int i;
// search timer position
ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid);
- if( i == BHEAP_LENGTH(timer_heap) ) {
+ if (i == BHEAP_LENGTH(timer_heap)) {
ShowError("timer_settick: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
return -1;
}
@@ -373,13 +384,18 @@ int64 timer_settick(int tid, int64 tick) {
return tick;
}
-/// Executes all expired timers.
-/// Returns the value of the smallest non-expired timer (or 1 second if there aren't any).
-int do_timer(int64 tick) {
+/**
+ * Executes all expired timers.
+ *
+ * @param tick The current tick.
+ * @return The value of the smallest non-expired timer (or 1 second if there aren't any).
+ */
+int do_timer(int64 tick)
+{
int64 diff = TIMER_MAX_INTERVAL; // return value
// process all timers one by one
- while( BHEAP_LENGTH(timer_heap) ) {
+ while (BHEAP_LENGTH(timer_heap) > 0) {
int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick)
diff = DIFF_TICK(timer_data[tid].tick, tick);
diff --git a/src/login/HPMlogin.c b/src/login/HPMlogin.c
index 895cbad16..b900f28fe 100644
--- a/src/login/HPMlogin.c
+++ b/src/login/HPMlogin.c
@@ -32,13 +32,19 @@
// HPMDataCheck comes after all the other includes
#include "common/HPMDataCheck.h"
-bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
- /* record address */
- switch( type ) {
+/**
+ * HPM plugin data store validator sub-handler (login-server)
+ *
+ * @see HPM_interface::data_store_validate
+ */
+bool HPM_login_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize)
+{
+ switch (type) {
+ // No supported types at the moment
default:
- return false;
+ break;
}
- return true;
+ return false;
}
void HPM_login_plugin_load_sub(struct hplugin *plugin) {
@@ -46,6 +52,8 @@ void HPM_login_plugin_load_sub(struct hplugin *plugin) {
}
void HPM_login_do_init(void) {
+ HPM->load_sub = HPM_login_plugin_load_sub;
+ HPM->data_store_validate_sub = HPM_login_data_store_validate;
HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
HPM_shared_symbols(SERVER_TYPE_LOGIN);
}
diff --git a/src/login/HPMlogin.h b/src/login/HPMlogin.h
index 2a4d5c538..35d4bd01c 100644
--- a/src/login/HPMlogin.h
+++ b/src/login/HPMlogin.h
@@ -13,7 +13,7 @@
struct hplugin;
-bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+bool HPM_login_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize);
void HPM_login_plugin_load_sub(struct hplugin *plugin);
diff --git a/src/login/login.c b/src/login/login.c
index 572bd594f..1d8ef489a 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -768,7 +768,7 @@ void login_fromchar_parse_accinfo(int fd)
//--------------------------------
int login_parse_fromchar(int fd)
{
- int j, id;
+ int id;
uint32 ipl;
char ip[16];
@@ -795,11 +795,12 @@ int login_parse_fromchar(int fd)
while( RFIFOREST(fd) >= 2 ) {
uint16 command = RFIFOW(fd,0);
- if( HPM->packetsc[hpParse_FromChar] ) {
- if( (j = HPM->parse_packets(fd,hpParse_FromChar)) ) {
- if( j == 1 ) continue;
- if( j == 2 ) return 0;
- }
+ if (VECTOR_LENGTH(HPM->packets[hpParse_FromChar]) > 0) {
+ int result = HPM->parse_packets(fd,hpParse_FromChar);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
switch( command ) {
@@ -1574,7 +1575,6 @@ void login_parse_request_connection(int fd, struct login_session_data* sd, const
int login_parse_login(int fd)
{
struct login_session_data* sd = (struct login_session_data*)sockt->session[fd]->session_data;
- int result;
char ip[16];
uint32 ipl = sockt->session[fd]->client_addr;
@@ -1608,11 +1608,12 @@ int login_parse_login(int fd)
while( RFIFOREST(fd) >= 2 ) {
uint16 command = RFIFOW(fd,0);
- if( HPM->packetsc[hpParse_Login] ) {
- if( (result = HPM->parse_packets(fd,hpParse_Login)) ) {
- if( result == 1 ) continue;
- if( result == 2 ) return 0;
- }
+ if (VECTOR_LENGTH(HPM->packets[hpParse_Login]) > 0) {
+ int result = HPM->parse_packets(fd,hpParse_Login);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
switch( command ) {
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
index ac78e8c84..edbe74039 100644
--- a/src/map/HPMmap.c
+++ b/src/map/HPMmap.c
@@ -85,57 +85,31 @@ struct HPM_atcommand_list {
struct HPM_atcommand_list *atcommand_list = NULL;
unsigned int atcommand_list_items = 0;
-bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
- /* record address */
- switch( type ) {
+/**
+ * HPM plugin data store validator sub-handler (map-server)
+ *
+ * @see HPM_interface::data_store_validate
+ */
+bool HPM_map_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize)
+{
+ switch (type) {
case HPDT_MSD:
- ret->HPDataSRCPtr = (void**)(&((struct map_session_data *)ptr)->hdata);
- ret->hdatac = &((struct map_session_data *)ptr)->hdatac;
- break;
case HPDT_NPCD:
- ret->HPDataSRCPtr = (void**)(&((struct npc_data *)ptr)->hdata);
- ret->hdatac = &((struct npc_data *)ptr)->hdatac;
- break;
case HPDT_MAP:
- ret->HPDataSRCPtr = (void**)(&((struct map_data *)ptr)->hdata);
- ret->hdatac = &((struct map_data *)ptr)->hdatac;
- break;
case HPDT_PARTY:
- ret->HPDataSRCPtr = (void**)(&((struct party_data *)ptr)->hdata);
- ret->hdatac = &((struct party_data *)ptr)->hdatac;
- break;
case HPDT_GUILD:
- ret->HPDataSRCPtr = (void**)(&((struct guild *)ptr)->hdata);
- ret->hdatac = &((struct guild *)ptr)->hdatac;
- break;
case HPDT_INSTANCE:
- ret->HPDataSRCPtr = (void**)(&((struct instance_data *)ptr)->hdata);
- ret->hdatac = &((struct instance_data *)ptr)->hdatac;
- break;
case HPDT_MOBDB:
- ret->HPDataSRCPtr = (void**)(&((struct mob_db *)ptr)->hdata);
- ret->hdatac = &((struct mob_db *)ptr)->hdatac;
- break;
case HPDT_MOBDATA:
- ret->HPDataSRCPtr = (void**)(&((struct mob_data *)ptr)->hdata);
- ret->hdatac = &((struct mob_data *)ptr)->hdatac;
- break;
case HPDT_ITEMDATA:
- ret->HPDataSRCPtr = (void**)(&((struct item_data *)ptr)->hdata);
- ret->hdatac = &((struct item_data *)ptr)->hdatac;
- break;
case HPDT_BGDATA:
- ret->HPDataSRCPtr = (void**)(&((struct battleground_data *)ptr)->hdata);
- ret->hdatac = &((struct battleground_data *)ptr)->hdatac;
- break;
case HPDT_AUTOTRADE_VEND:
- ret->HPDataSRCPtr = (void**)(&((struct autotrade_vending *)ptr)->hdata);
- ret->hdatac = &((struct autotrade_vending *)ptr)->hdatac;
- break;
+ // Initialized by the caller.
+ return true;
default:
- return false;
+ break;
}
- return true;
+ return false;
}
void HPM_map_plugin_load_sub(struct hplugin *plugin) {
@@ -188,7 +162,7 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in
void HPM_map_do_init(void) {
HPM->load_sub = HPM_map_plugin_load_sub;
- HPM->grabHPDataSub = HPM_map_grabHPData;
+ HPM->data_store_validate_sub = HPM_map_data_store_validate;
HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
HPM_shared_symbols(SERVER_TYPE_MAP);
}
diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h
index 00a8f43c3..b1957b139 100644
--- a/src/map/HPMmap.h
+++ b/src/map/HPMmap.h
@@ -15,7 +15,7 @@
struct hplugin;
struct map_session_data;
-bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+bool HPM_map_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize);
bool HPM_map_add_atcommand(char *name, AtCommandFunc func);
void HPM_map_atcommands(void);
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 5df05d301..be6b7a863 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -880,17 +880,9 @@ void do_init_battleground(bool minimal) {
*/
int bg_team_db_final(DBKey key, DBData *data, va_list ap) {
struct battleground_data* bgd = DB->data2ptr(data);
- int i;
- nullpo_ret(bgd);
- for(i = 0; i < bgd->hdatac; i++ ) {
- if( bgd->hdata[i]->flag.free ) {
- aFree(bgd->hdata[i]->data);
- }
- aFree(bgd->hdata[i]);
- }
- if( bgd->hdata )
- aFree(bgd->hdata);
-
+
+ HPM->data_store_destroy(&bgd->hdata);
+
return 0;
}
diff --git a/src/map/battleground.h b/src/map/battleground.h
index 094037f43..dcf92d6d8 100644
--- a/src/map/battleground.h
+++ b/src/map/battleground.h
@@ -10,7 +10,7 @@
#include "common/db.h"
#include "common/mmo.h" // struct party
-struct HPluginData;
+struct hplugin_data_store;
struct block_list;
struct map_session_data;
@@ -53,9 +53,7 @@ struct battleground_data {
// Logout Event
char logout_event[EVENT_NAME_LENGTH];
char die_event[EVENT_NAME_LENGTH];
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
struct bg_arena {
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 1e376e3bc..a27038ff7 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -1351,7 +1351,7 @@ void chrif_skillid2idx(int fd) {
*
*------------------------------------------*/
int chrif_parse(int fd) {
- int packet_len, cmd, r;
+ int packet_len, cmd;
// only process data from the char-server
if ( fd != chrif->fd ) {
@@ -1375,22 +1375,22 @@ int chrif_parse(int fd) {
}
}
- while ( RFIFOREST(fd) >= 2 ) {
-
- if( HPM->packetsc[hpChrif_Parse] ) {
- if( (r = HPM->parse_packets(fd,hpChrif_Parse)) ) {
- if( r == 1 ) continue;
- if( r == 2 ) return 0;
- }
+ while (RFIFOREST(fd) >= 2) {
+ if (VECTOR_LENGTH(HPM->packets[hpChrif_Parse]) > 0) {
+ int result = HPM->parse_packets(fd,hpChrif_Parse);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
cmd = RFIFOW(fd,0);
if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(chrif->packet_len_table) || chrif->packet_len_table[cmd-0x2af8] == 0) {
- r = intif->parse(fd); // Passed on to the intif
+ int result = intif->parse(fd); // Passed on to the intif
- if (r == 1) continue; // Treated in intif
- if (r == 2) return 0; // Didn't have enough data (len==-1)
+ if (result == 1) continue; // Treated in intif
+ if (result == 2) return 0; // Didn't have enough data (len==-1)
ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd);
sockt->eof(fd);
diff --git a/src/map/clif.c b/src/map/clif.c
index 59c8a7197..9c7d327e6 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -18578,12 +18578,12 @@ int clif_parse(int fd) {
if (RFIFOREST(fd) < 2)
return 0;
- if( HPM->packetsc[hpClif_Parse] ) {
- int r;
- if( (r = HPM->parse_packets(fd,hpClif_Parse)) ) {
- if( r == 1 ) continue;
- if( r == 2 ) return 0;
- }
+ if (VECTOR_LENGTH(HPM->packets[hpClif_Parse]) > 0) {
+ int result = HPM->parse_packets(fd,hpClif_Parse);
+ if (result == 1)
+ continue;
+ if (result == 2)
+ return 0;
}
if( sd )
diff --git a/src/map/guild.c b/src/map/guild.c
index 7a187b625..f8798f821 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -1763,16 +1763,7 @@ int guild_broken(int guild_id,int flag)
if( g->instance )
aFree(g->instance);
- if( g->hdata )
- {
- for( i = 0; i < g->hdatac; i++ ) {
- if( g->hdata[i]->flag.free ) {
- aFree(g->hdata[i]->data);
- }
- aFree(g->hdata[i]);
- }
- aFree(g->hdata);
- }
+ HPM->data_store_destroy(&g->hdata);
idb_remove(guild->db,guild_id);
return 0;
@@ -2250,7 +2241,6 @@ void do_init_guild(bool minimal) {
void do_final_guild(void) {
DBIterator *iter = db_iterator(guild->db);
struct guild *g;
- int i;
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) {
if( g->channel != NULL )
@@ -2259,16 +2249,7 @@ void do_final_guild(void) {
aFree(g->instance);
g->instance = NULL;
}
- if( g->hdata )
- {
- for( i = 0; i < g->hdatac; i++ ) {
- if( g->hdata[i]->flag.free ) {
- aFree(g->hdata[i]->data);
- }
- aFree(g->hdata[i]);
- }
- aFree(g->hdata);
- }
+ HPM->data_store_destroy(&g->hdata);
}
dbi_destroy(iter);
diff --git a/src/map/instance.c b/src/map/instance.c
index 300247fe7..0936a5ace 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -588,19 +588,7 @@ void instance_destroy(int instance_id) {
instance->list[instance_id].state = INSTANCE_FREE;
instance->list[instance_id].num_map = 0;
- if (instance->list[instance_id].hdata)
- {
- for( j = 0; j < instance->list[instance_id].hdatac; j++ ) {
- if( instance->list[instance_id].hdata[j]->flag.free ) {
- aFree(instance->list[instance_id].hdata[j]->data);
- }
- aFree(instance->list[instance_id].hdata[j]);
- }
- aFree(instance->list[instance_id].hdata);
- }
-
- instance->list[instance_id].hdata = NULL;
- instance->list[instance_id].hdatac = 0;
+ HPM->data_store_destroy(&instance->list[instance_id].hdata);
}
/*--------------------------------------
diff --git a/src/map/instance.h b/src/map/instance.h
index 589e1a511..058cd2c3d 100644
--- a/src/map/instance.h
+++ b/src/map/instance.h
@@ -9,7 +9,7 @@
#include "common/hercules.h"
#include "common/mmo.h" // struct point
-struct HPluginData;
+struct hplugin_data_store;
struct block_list;
struct map_session_data;
@@ -52,10 +52,7 @@ struct instance_data {
unsigned int original_progress_timeout;
struct point respawn; ///< reload spawn
-
- /** HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
struct instance_interface {
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index ccedee72a..ccfff2246 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -2100,17 +2100,7 @@ void destroy_item_data(struct item_data* self, int free_self)
script->free_code(self->unequip_script);
if( self->combos )
aFree(self->combos);
- if (self->hdata)
- {
- int i;
- for (i = 0; i < self->hdatac; i++ ) {
- if (self->hdata[i]->flag.free ) {
- aFree(self->hdata[i]->data);
- }
- aFree(self->hdata[i]);
- }
- aFree(self->hdata);
- }
+ HPM->data_store_destroy(&self->hdata);
#if defined(DEBUG)
// trash item
memset(self, 0xDD, sizeof(struct item_data));
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index a3edd451e..64b800b87 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -13,6 +13,7 @@
#include "common/sql.h"
struct script_code;
+struct hplugin_data_store;
/**
* Defines
@@ -488,10 +489,7 @@ struct item_data {
/* TODO add a pointer to some sort of (struct extra) and gather all the not-common vals into it to save memory */
struct item_group *group;
struct item_package *package;
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
#define itemdb_name(n) (itemdb->search(n)->name)
diff --git a/src/map/map.c b/src/map/map.c
index e01a25366..b142ed1f3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3239,16 +3239,7 @@ void do_final_maps(void) {
if( map->list[i].qi_data )
aFree(map->list[i].qi_data);
- if( map->list[i].hdata )
- {
- for( v = 0; v < map->list[i].hdatac; v++ ) {
- if( map->list[i].hdata[v]->flag.free ) {
- aFree(map->list[i].hdata[v]->data);
- }
- aFree(map->list[i].hdata[v]);
- }
- aFree(map->list[i].hdata);
- }
+ HPM->data_store_destroy(&map->list[i].hdata);
}
map->zone_db_clear();
diff --git a/src/map/map.h b/src/map/map.h
index 3ac39e54f..961a45793 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -19,6 +19,7 @@
struct mob_data;
struct npc_data;
struct channel_data;
+struct hplugin_data_store;
enum E_MAPSERVER_ST {
MAPSERVER_ST_RUNNING = CORE_ST_LAST,
@@ -736,10 +737,7 @@ struct map_data {
/* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */
unsigned short hpmeter_visible;
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
/// Stores information about a remote map (for multi-mapserver setups).
diff --git a/src/map/mob.c b/src/map/mob.c
index 2fe9fe8fb..01f585b6f 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -4708,16 +4708,7 @@ int do_init_mob(bool minimal) {
void mob_destroy_mob_db(int index)
{
struct mob_db *data = mob->db_data[index];
- if (data->hdata) {
- int i;
- for (i = 0; i < data->hdatac; i++) {
- if (data->hdata[i]->flag.free ) {
- aFree(data->hdata[i]->data);
- }
- aFree(data->hdata[i]);
- }
- aFree(data->hdata);
- }
+ HPM->data_store_destroy(&data->hdata);
aFree(data);
mob->db_data[index] = NULL;
}
diff --git a/src/map/mob.h b/src/map/mob.h
index 4b8a054b5..bb26258c6 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -11,6 +11,8 @@
#include "common/hercules.h"
#include "common/mmo.h" // struct item
+struct hplugin_data_store;
+
#define MAX_RANDOMMONSTER 5
// Change this to increase the table size in your mob_db to accommodate a larger mob database.
@@ -138,10 +140,7 @@ struct mob_db {
int maxskill;
struct mob_skill skill[MAX_MOBSKILL];
struct spawn_info spawn[10];
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
struct mob_data {
@@ -208,14 +207,10 @@ struct mob_data {
* MvP Tombstone NPC ID
**/
int tomb_nid;
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
-
enum {
MST_TARGET = 0,
MST_RANDOM, //Random Target!
diff --git a/src/map/npc.c b/src/map/npc.c
index a0c14a058..24b22beb3 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2321,16 +2321,7 @@ int npc_unload(struct npc_data* nd, bool single)
nd->ud = NULL;
}
- if (nd->hdata) {
- unsigned int i;
- for (i = 0; i < nd->hdatac; i++) {
- if (nd->hdata[i]->flag.free) {
- aFree(nd->hdata[i]->data);
- }
- aFree(nd->hdata[i]);
- }
- aFree(nd->hdata);
- }
+ HPM->data_store_destroy(&nd->hdata);
aFree(nd);
diff --git a/src/map/npc.h b/src/map/npc.h
index 14b89d128..bf3d1494d 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -11,7 +11,7 @@
#include "common/hercules.h"
#include "common/db.h"
-struct HPluginData;
+struct hplugin_data_store;
struct view_data;
enum npc_parse_options {
@@ -102,9 +102,7 @@ struct npc_data {
char killer_name[NAME_LENGTH];
} tomb;
} u;
- /* HPData Support for npc_data */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
diff --git a/src/map/party.c b/src/map/party.c
index db285a4b4..f7e7d431c 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -103,16 +103,7 @@ int party_db_final(DBKey key, DBData *data, va_list ap) {
if (p->instance)
aFree(p->instance);
- if (p->hdata) {
- int i;
- for (i = 0; i < p->hdatac; i++) {
- if (p->hdata[i]->flag.free) {
- aFree(p->hdata[i]->data);
- }
- aFree(p->hdata[i]);
- }
- aFree(p->hdata);
- }
+ HPM->data_store_destroy(&p->hdata);
}
return 0;
}
@@ -608,16 +599,8 @@ int party_broken(int party_id)
if( p->instance )
aFree(p->instance);
- if( p->hdata )
- {
- for( j = 0; j < p->hdatac; j++ ) {
- if( p->hdata[j]->flag.free ) {
- aFree(p->hdata[j]->data);
- }
- aFree(p->hdata[j]);
- }
- aFree(p->hdata);
- }
+ HPM->data_store_destroy(&p->hdata);
+
idb_remove(party->db,party_id);
return 0;
}
diff --git a/src/map/party.h b/src/map/party.h
index c7893add2..df7c03f05 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -15,7 +15,7 @@
#define PARTY_BOOKING_JOBS 6
#define PARTY_BOOKING_RESULTS 10
-struct HPluginData;
+struct hplugin_data_store;
struct party_member_data {
struct map_session_data *sd;
@@ -35,10 +35,7 @@ struct party_data {
unsigned snovice :1; ///< There's a Super Novice
unsigned tk : 1; ///< There's a taekwon
} state;
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
#define PB_NOTICE_LENGTH (36 + 1)
diff --git a/src/map/path.c b/src/map/path.c
index a482fc473..29701d445 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -45,7 +45,7 @@ struct path_node {
};
/// Binary heap of path nodes
-BHEAP_STRUCT_DECL(node_heap, struct path_node*);
+BHEAP_STRUCT_DECL(node_heap, struct path_node *);
/// Comparator for binary heap of path nodes (minimum cost at top)
#define NODE_MINTOPCMP(i,j) ((i)->f_cost - (j)->f_cost)
diff --git a/src/map/pc.c b/src/map/pc.c
index dc7014701..99f5b867e 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -11332,14 +11332,7 @@ void pc_autotrade_populate(struct map_session_data *sd) {
pc->autotrade_update(sd,PAUC_START);
- for(i = 0; i < data->hdatac; i++ ) {
- if( data->hdata[i]->flag.free ) {
- aFree(data->hdata[i]->data);
- }
- aFree(data->hdata[i]);
- }
- if( data->hdata )
- aFree(data->hdata);
+ HPM->data_store_destroy(&data->hdata);
idb_remove(pc->at_db, sd->status.char_id);
}
@@ -11349,16 +11342,7 @@ void pc_autotrade_populate(struct map_session_data *sd) {
*/
int pc_autotrade_final(DBKey key, DBData *data, va_list ap) {
struct autotrade_vending* at_v = DB->data2ptr(data);
- int i;
- for(i = 0; i < at_v->hdatac; i++ ) {
- if( at_v->hdata[i]->flag.free ) {
- aFree(at_v->hdata[i]->data);
- }
- aFree(at_v->hdata[i]);
- }
- if( at_v->hdata )
- aFree(at_v->hdata);
-
+ HPM->data_store_destroy(&at_v->hdata);
return 0;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index e6e95978d..2c8b24acf 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -539,10 +539,7 @@ END_ZEROED_BLOCK;
unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); ///< parse_cmd_func used by this player
unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules]
-
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
/* expiration_time timer id */
int expiration_tid;
@@ -757,9 +754,7 @@ struct autotrade_vending {
struct item list[MAX_VENDING];
struct s_vending vending[MAX_VENDING];
unsigned char vend_num;
- /* HPM Custom Struct */
- struct HPluginData **hdata;
- unsigned int hdatac;
+ struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
/*=====================================
diff --git a/src/map/unit.c b/src/map/unit.c
index 04a8befc2..dcb5ec900 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2654,17 +2654,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
sd->quest_log = NULL;
sd->num_quests = sd->avail_quests = 0;
}
-
- if (sd->hdata) {
- unsigned int k;
- for( k = 0; k < sd->hdatac; k++ ) {
- if( sd->hdata[k]->flag.free ) {
- aFree(sd->hdata[k]->data);
- }
- aFree(sd->hdata[k]);
- }
- aFree(sd->hdata);
- }
+ HPM->data_store_destroy(&sd->hdata);
break;
}
case BL_PET:
@@ -2775,17 +2765,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
if( md->tomb_nid )
mob->mvptomb_destroy(md);
- if (md->hdata)
- {
- unsigned int k;
- for (k = 0; k < md->hdatac; k++) {
- if( md->hdata[k]->flag.free ) {
- aFree(md->hdata[k]->data);
- }
- aFree(md->hdata[k]);
- }
- aFree(md->hdata);
- }
+ HPM->data_store_destroy(&md->hdata);
break;
}
case BL_HOM:
diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
index 2e35992bc..e113611e4 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
@@ -15775,15 +15775,15 @@ bool HP_sockt_trusted_ip_check(uint32 ip) {
}
return retVal___;
}
-int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) {
+int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) {
int hIndex = 0;
int retVal___ = 0;
if( HPMHooks.count.HP_sockt_net_config_read_sub_pre ) {
- int (*preHookFunc) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*preHookFunc) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_pre[hIndex].func;
- retVal___ = preHookFunc(t, list, count, filename, groupname);
+ retVal___ = preHookFunc(t, list, filename, groupname);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
@@ -15791,13 +15791,13 @@ int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, in
}
}
{
- retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, count, filename, groupname);
+ retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, filename, groupname);
}
if( HPMHooks.count.HP_sockt_net_config_read_sub_post ) {
- int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, t, list, count, filename, groupname);
+ retVal___ = postHookFunc(retVal___, t, list, filename, groupname);
}
}
return retVal___;
diff --git a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
index 94b298d36..5d4fad4d8 100644
--- a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
@@ -5048,15 +5048,15 @@ bool HP_sockt_trusted_ip_check(uint32 ip) {
}
return retVal___;
}
-int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) {
+int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) {
int hIndex = 0;
int retVal___ = 0;
if( HPMHooks.count.HP_sockt_net_config_read_sub_pre ) {
- int (*preHookFunc) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*preHookFunc) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_pre[hIndex].func;
- retVal___ = preHookFunc(t, list, count, filename, groupname);
+ retVal___ = preHookFunc(t, list, filename, groupname);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
@@ -5064,13 +5064,13 @@ int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, in
}
}
{
- retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, count, filename, groupname);
+ retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, filename, groupname);
}
if( HPMHooks.count.HP_sockt_net_config_read_sub_post ) {
- int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, t, list, count, filename, groupname);
+ retVal___ = postHookFunc(retVal___, t, list, filename, groupname);
}
}
return retVal___;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 8f5ca680d..7ae0d9d48 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -69770,15 +69770,15 @@ bool HP_sockt_trusted_ip_check(uint32 ip) {
}
return retVal___;
}
-int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname) {
+int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname) {
int hIndex = 0;
int retVal___ = 0;
if( HPMHooks.count.HP_sockt_net_config_read_sub_pre ) {
- int (*preHookFunc) (config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*preHookFunc) (config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_pre[hIndex].func;
- retVal___ = preHookFunc(t, list, count, filename, groupname);
+ retVal___ = preHookFunc(t, list, filename, groupname);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
@@ -69786,13 +69786,13 @@ int HP_sockt_net_config_read_sub(config_setting_t *t, struct s_subnet **list, in
}
}
{
- retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, count, filename, groupname);
+ retVal___ = HPMHooks.source.sockt.net_config_read_sub(t, list, filename, groupname);
}
if( HPMHooks.count.HP_sockt_net_config_read_sub_post ) {
- int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet **list, int *count, const char *filename, const char *groupname);
+ int (*postHookFunc) (int retVal___, config_setting_t *t, struct s_subnet_vector *list, const char *filename, const char *groupname);
for(hIndex = 0; hIndex < HPMHooks.count.HP_sockt_net_config_read_sub_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_sockt_net_config_read_sub_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, t, list, count, filename, groupname);
+ retVal___ = postHookFunc(retVal___, t, list, filename, groupname);
}
}
return retVal___;