diff options
author | ai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2011-07-10 06:17:06 +0000 |
---|---|---|
committer | ai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2011-07-10 06:17:06 +0000 |
commit | 9ef634559f3cde232586b1dc6fd00bea3f3d8e53 (patch) | |
tree | 541295af8a6fbfe15b09da353680be6dd4d6b3ff /src/common | |
parent | 9c100697bf79604fcef8b7eedbadeed45c63b41b (diff) | |
download | hercules-9ef634559f3cde232586b1dc6fd00bea3f3d8e53.tar.gz hercules-9ef634559f3cde232586b1dc6fd00bea3f3d8e53.tar.bz2 hercules-9ef634559f3cde232586b1dc6fd00bea3f3d8e53.tar.xz hercules-9ef634559f3cde232586b1dc6fd00bea3f3d8e53.zip |
* Merged changes from trunk [14827:14894/trunk].
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/renewal@14895 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 144 | ||||
-rw-r--r-- | src/common/Makefile.in | 25 | ||||
-rw-r--r-- | src/common/cbasetypes.h | 111 | ||||
-rw-r--r-- | src/common/core.c | 14 | ||||
-rw-r--r-- | src/common/core.h | 13 | ||||
-rw-r--r-- | src/common/db.c | 91 | ||||
-rw-r--r-- | src/common/db.h | 20 | ||||
-rw-r--r-- | src/common/ers.h | 2 | ||||
-rw-r--r-- | src/common/grfio.c | 36 | ||||
-rw-r--r-- | src/common/grfio.h | 5 | ||||
-rw-r--r-- | src/common/malloc.c | 10 | ||||
-rw-r--r-- | src/common/mmo.h | 19 | ||||
-rw-r--r-- | src/common/plugin.h | 2 | ||||
-rw-r--r-- | src/common/plugins.h | 3 | ||||
-rw-r--r-- | src/common/random.c | 83 | ||||
-rw-r--r-- | src/common/random.h | 18 | ||||
-rw-r--r-- | src/common/socket.c | 5 | ||||
-rw-r--r-- | src/common/socket.h | 2 | ||||
-rw-r--r-- | src/common/sql.c | 4 | ||||
-rw-r--r-- | src/common/sql.h | 2 | ||||
-rw-r--r-- | src/common/strlib.c | 136 | ||||
-rw-r--r-- | src/common/strlib.h | 23 | ||||
-rw-r--r-- | src/common/timer.c | 4 | ||||
-rw-r--r-- | src/common/timer.h | 10 | ||||
-rw-r--r-- | src/common/utils.h | 3 |
25 files changed, 571 insertions, 214 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 000000000..21feb53f9 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,144 @@ + +# +# Create svnversion.h +# +message( STATUS "Creating svnversion.h" ) +if( SVNVERSION ) + file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h + "#ifndef SVNVERSION\n#define SVNVERSION ${SVNVERSION}\n#endif\n" ) +else() + file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h "" ) +endif() +set( GLOBAL_INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "" ) +set( SVNVERSION ${SVNVERSION} + CACHE STRING "SVN version of the source code" ) +if( WITH_COMPONENT_DEVELOPMENT ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h + DESTINATION "src/common" + COMPONENT Development_base ) +endif() +message( STATUS "Creating svnversion.h - done" ) + + +##################################################################### +# setup +# +set( COMMON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" + CACHE PATH "common source directory" ) +mark_as_advanced( COMMON_SOURCE_DIR ) + +set( COMMON_ALL_HEADERS + "${CMAKE_CURRENT_BINARY_DIR}/svnversion.h" + "${COMMON_SOURCE_DIR}/cbasetypes.h" + "${COMMON_SOURCE_DIR}/mmo.h" + "${COMMON_SOURCE_DIR}/plugin.h" + "${COMMON_SOURCE_DIR}/version.h" + ) + +set( COMMON_MINI_HEADERS + ${COMMON_ALL_HEADERS} + "${COMMON_SOURCE_DIR}/core.h" + "${COMMON_SOURCE_DIR}/malloc.h" + "${COMMON_SOURCE_DIR}/showmsg.h" + "${COMMON_SOURCE_DIR}/strlib.h" + CACHE INTERNAL "" ) +set( COMMON_MINI_SOURCES + "${COMMON_SOURCE_DIR}/core.c" + "${COMMON_SOURCE_DIR}/malloc.c" + "${COMMON_SOURCE_DIR}/showmsg.c" + "${COMMON_SOURCE_DIR}/strlib.c" + CACHE INTERNAL "" ) +set( COMMON_MINI_DEFINITIONS MINICORE CACHE INTERNAL "" ) + + +# +# common_base +# +if( WITH_ZLIB ) +message( STATUS "Creating target common_base" ) +set( COMMON_BASE_HEADERS + ${COMMON_ALL_HEADERS} + "${COMMON_SOURCE_DIR}/core.h" + "${COMMON_SOURCE_DIR}/db.h" + "${COMMON_SOURCE_DIR}/ers.h" + "${COMMON_SOURCE_DIR}/grfio.h" + "${COMMON_SOURCE_DIR}/lock.h" + "${COMMON_SOURCE_DIR}/malloc.h" + "${COMMON_SOURCE_DIR}/mapindex.h" + "${COMMON_SOURCE_DIR}/md5calc.h" + "${COMMON_SOURCE_DIR}/nullpo.h" + "${COMMON_SOURCE_DIR}/plugins.h" + "${COMMON_SOURCE_DIR}/random.h" + "${COMMON_SOURCE_DIR}/showmsg.h" + "${COMMON_SOURCE_DIR}/socket.h" + "${COMMON_SOURCE_DIR}/strlib.h" + "${COMMON_SOURCE_DIR}/timer.h" + "${COMMON_SOURCE_DIR}/utils.h" + CACHE INTERNAL "common_base headers" ) +set( COMMON_BASE_SOURCES + "${COMMON_SOURCE_DIR}/core.c" + "${COMMON_SOURCE_DIR}/db.c" + "${COMMON_SOURCE_DIR}/ers.c" + "${COMMON_SOURCE_DIR}/grfio.c" + "${COMMON_SOURCE_DIR}/lock.c" + "${COMMON_SOURCE_DIR}/malloc.c" + "${COMMON_SOURCE_DIR}/mapindex.c" + "${COMMON_SOURCE_DIR}/md5calc.c" + "${COMMON_SOURCE_DIR}/nullpo.c" + "${COMMON_SOURCE_DIR}/plugins.c" + "${COMMON_SOURCE_DIR}/random.c" + "${COMMON_SOURCE_DIR}/showmsg.c" + "${COMMON_SOURCE_DIR}/socket.c" + "${COMMON_SOURCE_DIR}/strlib.c" + "${COMMON_SOURCE_DIR}/timer.c" + "${COMMON_SOURCE_DIR}/utils.c" + CACHE INTERNAL "common_base sources" ) +set( LIBRARIES ${ZLIB_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MT19937AR_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +set( SOURCE_FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} ) +source_group( mt19937ar FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} ) +add_library( common_base ${SOURCE_FILES} ) +target_link_libraries( common_base ${LIBRARIES} ) +set_target_properties( common_base PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +include_directories( ${INCLUDE_DIRS} ) +message( STATUS "Creating target common_base - done" ) +set( HAVE_common_base ON CACHE BOOL "common_base target is available" ) +mark_as_advanced( HAVE_common_base ) +else() +message( STATUS "Skipping target common_base (requires ZLIB)" ) +unset( HAVE_common_base CACHE ) +endif() + + +# +# common_sql +# +if( HAVE_common_base AND WITH_MYSQL ) +message( STATUS "Creating target common_sql" ) +set( COMMON_SQL_HEADERS + ${COMMON_ALL_HEADERS} + "${CMAKE_CURRENT_SOURCE_DIR}/sql.h" + CACHE INTERNAL "common_sql headers" ) +set( COMMON_SQL_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/sql.c" + CACHE INTERNAL "common_sql sources" ) +set( DEPENDENCIES common_base ) +set( LIBRARIES ${MYSQL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MYSQL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +set( SOURCE_FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} ) +source_group( common FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} ) +add_library( common_sql ${SOURCE_FILES} ) +add_dependencies( common_sql ${DEPENDENCIES} ) +target_link_libraries( common_sql ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( common_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +include_directories( ${INCLUDE_DIRS} ) +message( STATUS "Creating target common_sql - done" ) +set( HAVE_common_sql ON CACHE BOOL "common_sql target is available" ) +mark_as_advanced( HAVE_common_sql ) +else() +message( STATUS "Skipping target common_sql (requires common_base and MYSQL)" ) +unset( HAVE_common_sql CACHE ) +endif() diff --git a/src/common/Makefile.in b/src/common/Makefile.in index bda9e1911..37606dde2 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -2,15 +2,19 @@ COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/plugins.o obj_all/lock.o \ obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \ obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \ - obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o + obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o COMMON_H = svnversion.h mmo.h plugin.h version.h \ core.h socket.h timer.h db.h plugins.h lock.h \ nullpo.h malloc.h showmsg.h strlib.h utils.h \ - grfio.h mapindex.h ers.h md5calc.h + grfio.h mapindex.h ers.h md5calc.h random.h COMMON_SQL_OBJ = obj_sql/sql.o COMMON_SQL_H = sql.h +MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o +MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h +MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar + HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) ALL_DEPENDS=txt sql @@ -19,6 +23,7 @@ else ALL_TARGET=txt SQL_DEPENDS=needs_mysql endif +TXT_DEPENDS=common @SET_MAKE@ @@ -27,7 +32,7 @@ endif all: $(ALL_DEPENDS) -txt: common +txt: $(TXT_DEPENDS) sql: $(SQL_DEPENDS) @@ -54,16 +59,16 @@ obj_all: obj_sql: -mkdir obj_sql -common: obj_all $(COMMON_OBJ) +common: obj_all $(COMMON_OBJ) $(MT19937AR_OBJ) common_sql: obj_sql $(COMMON_SQL_OBJ) -obj_all/%.o: %.c $(COMMON_H) - @CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/%.o: %.c $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_all/mini%.o: %.c $(COMMON_H) - @CC@ @CFLAGS@ -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/mini%.o: %.c $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< @@ -80,3 +85,7 @@ else svnversion.h: @printf "\n" > svnversion.h endif + +# missing object files +MT19937AR_OBJ: + @$(MAKE) -C ../../3rdparty/mt19937ar diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index aee54a4bc..e2fe17555 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -78,14 +78,9 @@ // NOTE: Visual C++ uses <inttypes.h> and <stdint.h> provided in /3rdparty ////////////////////////////////////////////////////////////////////////// #include <inttypes.h> - -////////////////////////////////////////////////////////////////////////// -// typedefs to compensate type size change from 32bit to 64bit -// MS implements LLP64 model, normal unix does LP64, -// only Silicon Graphics/Cray goes ILP64 so don't care (and don't support) -////////////////////////////////////////////////////////////////////////// - +#include <stdint.h> #include <limits.h> + // ILP64 isn't supported, so always 32 bits? #ifndef UINT_MAX #define UINT_MAX 0xffffffff @@ -95,49 +90,56 @@ // Integers with guaranteed _exact_ size. ////////////////////////////////////////////////////////////////////////// -#define SIZEOF_LONG 4 -#define SIZEOF_INT 4 -#define HAVE_INT_8_16_32 +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; -typedef char int8; -typedef short int16; -typedef int int32; +typedef int8_t sint8; +typedef int16_t sint16; +typedef int32_t sint32; +typedef int64_t sint64; -typedef signed char sint8; -typedef signed short sint16; -typedef signed int sint32; - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; #undef UINT8_MIN #undef UINT16_MIN #undef UINT32_MIN -#define UINT8_MIN ((uint8) 0) -#define UINT16_MIN ((uint16)0) -#define UINT32_MIN ((uint32)0) +#undef UINT64_MIN +#define UINT8_MIN ((uint8) UINT8_C(0x00)) +#define UINT16_MIN ((uint16)UINT16_C(0x0000)) +#define UINT32_MIN ((uint32)UINT32_C(0x00000000)) +#define UINT64_MIN ((uint64)UINT64_C(0x0000000000000000)) #undef UINT8_MAX #undef UINT16_MAX #undef UINT32_MAX -#define UINT8_MAX ((uint8) 0xFF) -#define UINT16_MAX ((uint16)0xFFFF) -#define UINT32_MAX ((uint32)0xFFFFFFFF) +#undef UINT64_MAX +#define UINT8_MAX ((uint8) UINT8_C(0xFF)) +#define UINT16_MAX ((uint16)UINT16_C(0xFFFF)) +#define UINT32_MAX ((uint32)UINT32_C(0xFFFFFFFF)) +#define UINT64_MAX ((uint64)UINT64_C(0xFFFFFFFFFFFFFFFF)) #undef SINT8_MIN #undef SINT16_MIN #undef SINT32_MIN -#define SINT8_MIN ((sint8) 0x80) -#define SINT16_MIN ((sint16)0x8000) -#define SINT32_MIN ((sint32)0x80000000) +#undef SINT64_MIN +#define SINT8_MIN ((sint8) INT8_C(0x80)) +#define SINT16_MIN ((sint16)INT16_C(0x8000)) +#define SINT32_MIN ((sint32)INT32_C(0x80000000)) +#define SINT64_MIN ((sint32)INT64_C(0x8000000000000000)) #undef SINT8_MAX #undef SINT16_MAX #undef SINT32_MAX -#define SINT8_MAX ((sint8) 0x7F) -#define SINT16_MAX ((sint16)0x7FFF) -#define SINT32_MAX ((sint32)0x7FFFFFFF) +#undef SINT64_MAX +#define SINT8_MAX ((sint8) INT8_C(0x7F)) +#define SINT16_MAX ((sint16)INT16_C(0x7FFF)) +#define SINT32_MAX ((sint32)INT32_C(0x7FFFFFFF)) +#define SINT64_MAX ((sint64)INT64_C(0x7FFFFFFFFFFFFFFF)) ////////////////////////////////////////////////////////////////////////// // Integers with guaranteed _minimum_ size. @@ -173,51 +175,10 @@ typedef int ssize_t; ////////////////////////////////////////////////////////////////////////// -// portable 64-bit integers -////////////////////////////////////////////////////////////////////////// -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 int64; -typedef signed __int64 sint64; -typedef unsigned __int64 uint64; -#else -typedef long long int64; -typedef signed long long sint64; -typedef unsigned long long uint64; -#endif - -#ifndef INT64_MIN -#define INT64_MIN (INT64_C(-9223372036854775807)-1) -#endif -#ifndef INT64_MAX -#define INT64_MAX (INT64_C(9223372036854775807)) -#endif -#ifndef UINT64_MAX -#define UINT64_MAX (UINT64_C(18446744073709551615)) -#endif - - -////////////////////////////////////////////////////////////////////////// // pointer sized integers ////////////////////////////////////////////////////////////////////////// -#undef UINTPTR_MIN -#undef UINTPTR_MAX -#undef INTPTR_MIN -#undef INTPTR_MAX -#ifdef __64BIT__ -typedef uint64 uintptr; -typedef int64 intptr; -#define UINTPTR_MIN UINT64_MIN -#define UINTPTR_MAX UINT64_MAX -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#else -typedef uint32 uintptr; -typedef int32 intptr; -#define UINTPTR_MIN UINT32_MIN -#define UINTPTR_MAX UINT32_MAX -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#endif +typedef intptr_t intptr; +typedef uintptr_t uintptr; ////////////////////////////////////////////////////////////////////////// diff --git a/src/common/core.c b/src/common/core.c index b89cc3841..bfa563d8c 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -24,7 +24,12 @@ #include <unistd.h> #endif -int runflag = 1; + +/// Called when a terminate signal is received. +void (*shutdown_callback)(void) = NULL; + + +int runflag = CORE_ST_RUN; int arg_c = 0; char **arg_v = NULL; @@ -78,7 +83,10 @@ static void sig_proc(int sn) case SIGTERM: if (++is_called > 3) exit(EXIT_SUCCESS); - runflag = 0; + if( shutdown_callback != NULL ) + shutdown_callback(); + else + runflag = CORE_ST_STOP;// auto-shutdown break; case SIGSEGV: case SIGFPE: @@ -249,7 +257,7 @@ int main (int argc, char **argv) {// Main runtime cycle int next; - while (runflag) { + while (runflag != CORE_ST_STOP) { next = do_timer(gettick_nocache()); do_sockets(next); } diff --git a/src/common/core.h b/src/common/core.h index fc4af3e3e..beb72d080 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -7,6 +7,7 @@ extern int arg_c; extern char **arg_v; +/// @see E_CORE_ST extern int runflag; extern char *SERVER_NAME; extern char SERVER_TYPE; @@ -18,4 +19,16 @@ extern void set_server_type(void); extern void do_abort(void); extern void do_final(void); +/// The main loop continues until runflag is CORE_ST_STOP +enum E_CORE_ST +{ + CORE_ST_STOP = 0, + CORE_ST_RUN, + CORE_ST_LAST +}; + +/// Called when a terminate signal is received. (Ctrl+C pressed) +/// If NULL, runflag is set to CORE_ST_STOP instead. +extern void (*shutdown_callback)(void); + #endif /* _CORE_H_ */ diff --git a/src/common/db.c b/src/common/db.c index 595ed241d..c9b124455 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -67,13 +67,13 @@ \*****************************************************************************/ #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "db.h" #include "../common/mmo.h" #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/ers.h" +#include "../common/strlib.h" /*****************************************************************************\ * (1) Private typedefs, enums, structures, defines and global variables of * @@ -271,6 +271,7 @@ static struct db_stats { uint32 dbit_remove; uint32 dbit_destroy; uint32 db_iterator; + uint32 db_exists; uint32 db_get; uint32 db_getall; uint32 db_vgetall; @@ -304,7 +305,7 @@ static struct db_stats { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define DB_COUNTSTAT(token) if (stats. ## token != UINT32_MAX) ++stats. ## token #else /* !defined(DB_ENABLE_STATS) */ @@ -630,19 +631,17 @@ static int db_is_key_null(DBType type, DBKey key) static DBKey db_dup_key(DBMap_impl* db, DBKey key) { char *str; + size_t len; DB_COUNTSTAT(db_dup_key); switch (db->type) { case DB_STRING: case DB_ISTRING: - if (db->maxlen) { - CREATE(str, char, db->maxlen +1); - strncpy(str, key.str, db->maxlen); - str[db->maxlen] = '\0'; - key.str = str; - } else { - key.str = (char *)aStrdup(key.str); - } + len = strnlen(key.str, db->maxlen); + str = (char*)aMalloc(len + 1); + memcpy(str, key.str, len); + str[len] = '\0'; + key.str = str; return key; default: @@ -888,8 +887,6 @@ static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen) static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { DB_COUNTSTAT(db_string_cmp); - if (maxlen == 0) - maxlen = UINT16_MAX; return strncmp((const char *)key1.str, (const char *)key2.str, maxlen); } @@ -908,8 +905,6 @@ static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen) static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { DB_COUNTSTAT(db_istring_cmp); - if (maxlen == 0) - maxlen = UINT16_MAX; return strncasecmp((const char *)key1.str, (const char *)key2.str, maxlen); } @@ -951,7 +946,6 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen) /** * Default hasher for DB_STRING databases. - * If maxlen if 0, the maximum number of maxlen is used instead. * @param key Key to be hashed * @param maxlen Maximum length of the key to hash * @return hash of the key @@ -966,8 +960,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) unsigned short i; DB_COUNTSTAT(db_string_hash); - if (maxlen == 0) - maxlen = UINT16_MAX; for (i = 0; *k; ++i) { hash = (hash*33 + ((unsigned char)*k))^(hash>>24); @@ -981,7 +973,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) /** * Default hasher for DB_ISTRING databases. - * If maxlen if 0, the maximum number of maxlen is used instead. * @param key Key to be hashed * @param maxlen Maximum length of the key to hash * @return hash of the key @@ -995,8 +986,6 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) unsigned short i; DB_COUNTSTAT(db_istring_hash); - if (maxlen == 0) - maxlen = UINT16_MAX; for (i = 0; *k; i++) { hash = (hash*33 + ((unsigned char)TOLOWER(*k)))^(hash>>24); @@ -1087,6 +1076,7 @@ static void db_release_both(DBKey key, void *data, DBRelease which) * dbit_obj_destroy - Destroys the iterator, unlocking the database and * * freeing used memory. * * db_obj_iterator - Return a new databse iterator. * + * db_obj_exists - Checks if an entry exists. * * db_obj_get - Get the data identified by the key. * * db_obj_vgetall - Get the data of the matched entries. * * db_obj_getall - Get the data of the matched entries. * @@ -1402,6 +1392,57 @@ static DBIterator* db_obj_iterator(DBMap* self) } /** + * Returns true if the entry exists. + * @param self Interface of the database + * @param key Key that identifies the entry + * @return true is the entry exists + * @protected + * @see DBMap#exists + */ +static bool db_obj_exists(DBMap* self, DBKey key) +{ + DBMap_impl* db = (DBMap_impl*)self; + DBNode node; + int c; + bool found = false; + + DB_COUNTSTAT(db_exists); + if (db == NULL) return false; // nullpo candidate + if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) { + return false; // nullpo candidate + } + + if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) { +#if defined(DEBUG) + if (db->cache->deleted) { + ShowDebug("db_exists: Cache contains a deleted node. Please report this!!!\n"); + return false; + } +#endif + return true; // cache hit + } + + db_free_lock(db); + node = db->ht[db->hash(key, db->maxlen)%HASH_SIZE]; + while (node) { + c = db->cmp(key, node->key, db->maxlen); + if (c == 0) { + if (!(node->deleted)) { + db->cache = node; + found = true; + } + break; + } + if (c < 0) + node = node->left; + else + node = node->right; + } + db_free_unlock(db); + return found; +} + +/** * Get the data of the entry identifid by the key. * @param self Interface of the database * @param key Key that identifies the entry @@ -2326,7 +2367,7 @@ DBReleaser db_custom_release(DBRelease which) * @param type Type of database * @param options Options of the database * @param maxlen Maximum length of the string to be used as key in string - * databases + * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public * @see #DBMap_impl @@ -2351,6 +2392,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi options = db_fix_options(type, options); /* Interface of the database */ db->vtable.iterator = db_obj_iterator; + db->vtable.exists = db_obj_exists; db->vtable.get = db_obj_get; db->vtable.getall = db_obj_getall; db->vtable.vgetall = db_obj_vgetall; @@ -2389,6 +2431,9 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi db->maxlen = maxlen; db->global_lock = 0; + if( db->maxlen == 0 && (type == DB_STRING || type == DB_ISTRING) ) + db->maxlen = UINT16_MAX; + return &db->vtable; } @@ -2493,7 +2538,7 @@ void db_final(void) "dbit_next %10u, dbit_prev %10u,\n" "dbit_exists %10u, dbit_remove %10u,\n" "dbit_destroy %10u, db_iterator %10u,\n" - "db_get %10u,\n" + "db_exits %10u, db_get %10u,\n" "db_getall %10u, db_vgetall %10u,\n" "db_ensure %10u, db_vensure %10u,\n" "db_put %10u, db_remove %10u,\n" @@ -2523,7 +2568,7 @@ void db_final(void) stats.dbit_next, stats.dbit_prev, stats.dbit_exists, stats.dbit_remove, stats.dbit_destroy, stats.db_iterator, - stats.db_get, + stats.db_exists, stats.db_get, stats.db_getall, stats.db_vgetall, stats.db_ensure, stats.db_vensure, stats.db_put, stats.db_remove, diff --git a/src/common/db.h b/src/common/db.h index c1b224bcd..d33b8ec2e 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -205,8 +205,6 @@ typedef int (*DBMatcher)(DBKey key, void* data, va_list args); /** * Format of the comparators used internally by the database system. * Compares key1 to key2. - * <code>maxlen</code> is the maximum number of character used in DB_STRING and - * DB_ISTRING databases. If 0, the maximum number of maxlen is used (64K). * Returns 0 is equal, negative if lower and positive is higher. * @param key1 Key being compared * @param key2 Key we are comparing to @@ -221,8 +219,6 @@ typedef int (*DBComparator)(DBKey key1, DBKey key2, unsigned short maxlen); /** * Format of the hashers used internally by the database system. * Creates the hash of the key. - * <code>maxlen</code> is the maximum number of character used in DB_STRING and - * DB_ISTRING databases. If 0, the maximum number of maxlen is used (64K). * @param key Key being hashed * @param maxlen Maximum number of characters used in DB_STRING and DB_ISTRING * databases. @@ -360,6 +356,15 @@ struct DBMap { DBIterator* (*iterator)(DBMap* self); /** + * Returns true if the entry exists. + * @param self Database + * @param key Key that identifies the entry + * @return true is the entry exists + * @protected + */ + bool (*exists)(DBMap* self, DBKey key); + + /** * Get the data of the entry identifid by the key. * @param self Database * @param key Key that identifies the entry @@ -580,6 +585,11 @@ struct DBMap { # define str2key(k) ((DBKey)(const char *)(k)) #endif /* not DB_MANUAL_CAST_TO_UNION */ +#define db_exists(db,k) ( (db)->exists((db),(k)) ) +#define idb_exists(db,k) ( (db)->exists((db),i2key(k)) ) +#define uidb_exists(db,k) ( (db)->exists((db),ui2key(k)) ) +#define strdb_exists(db,k) ( (db)->exists((db),str2key(k)) ) + #define db_get(db,k) ( (db)->get((db),(k)) ) #define idb_get(db,k) ( (db)->get((db),i2key(k)) ) #define uidb_get(db,k) ( (db)->get((db),ui2key(k)) ) @@ -707,7 +717,7 @@ DBReleaser db_custom_release(DBRelease which); * @param type Type of database * @param options Options of the database * @param maxlen Maximum length of the string to be used as key in string - * databases + * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public * @see #DBType diff --git a/src/common/ers.h b/src/common/ers.h index 47a076e6e..9e120c313 100644 --- a/src/common/ers.h +++ b/src/common/ers.h @@ -40,9 +40,7 @@ #ifndef _ERS_H_ #define _ERS_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif /*****************************************************************************\ * (1) All public parts of the Entry Reusage System. * diff --git a/src/common/grfio.c b/src/common/grfio.c index e7549ecb4..cb242fe5d 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -1,19 +1,18 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include "grfio.h" - #include "../common/cbasetypes.h" #include "../common/showmsg.h" #include "../common/malloc.h" #include "../common/strlib.h" #include "../common/utils.h" +#include "grfio.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <zlib.h> //---------------------------- // file entry table struct @@ -221,6 +220,23 @@ unsigned long grfio_crc32 (const unsigned char* buf, unsigned int len) return crc32(crc32(0L, Z_NULL, 0), buf, len); } + +/////////////////////////////////////////////////////////////////////////////// +/// Grf data sub : zip decode +int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) +{ + return uncompress(dest, destLen, source, sourceLen); +} + + +/////////////////////////////////////////////////////////////////////////////// +/// Grf data sub : zip encode +int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) +{ + return compress(dest, destLen, source, sourceLen); +} + + /*********************************************************** *** File List Subroutines *** ***********************************************************/ @@ -431,9 +447,9 @@ void* grfio_reads(char* fname, int* size) if (entry->cycle >= 0) decode_des_etc(buf, entry->srclen_aligned, entry->cycle == 0, entry->cycle); len = entry->declen; - uncompress(buf2, &len, buf, entry->srclen); + decode_zip(buf2, &len, buf, entry->srclen); if (len != (uLong)entry->declen) { - ShowError("uncompress size mismatch err: %d != %d\n", (int)len, entry->declen); + ShowError("decode_zip size mismatch err: %d != %d\n", (int)len, entry->declen); aFree(buf); aFree(buf2); return NULL; @@ -580,7 +596,7 @@ static int grfio_entryread(char* grfname, int gentry) grf_filelist = (unsigned char *)aMallocA(eSize); // Get a Extend Size fread(rBuf,1,rSize,fp); fclose(fp); - uncompress(grf_filelist, &eSize, rBuf, rSize); // Decode function + decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function list_size = eSize; aFree(rBuf); diff --git a/src/common/grfio.h b/src/common/grfio.h index d5334ccf3..d0baa6609 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -4,8 +4,6 @@ #ifndef _GRFIO_H_ #define _GRFIO_H_ -#include <zlib.h> - void grfio_init(char*); // GRFIO Initialize void grfio_final(void); // GRFIO Finalize void* grfio_reads(char*,int*); // GRFIO data file read & size get @@ -16,4 +14,7 @@ char *grfio_find_file(char *fname); int grfio_size(char*); // GRFIO data file size get unsigned long grfio_crc32(const unsigned char *buf, unsigned int len); +int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); + #endif /* _GRFIO_H_ */ diff --git a/src/common/malloc.c b/src/common/malloc.c index b566e689f..f80d11fb4 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -222,7 +222,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) if (((long) size) < 0) { ShowError("_mmalloc: %d\n", size); - return 0; + return NULL; } if(size == 0) { @@ -380,7 +380,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) { ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); } else { - head->size = -1; + head->size = 0xFFFF; if(head_large->prev) { head_large->prev->next = head_large->next; } else { @@ -428,7 +428,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) hash_unfill[ block->unit_hash ] = block; } head->size = block->unit_unfill; - block->unit_unfill = (unsigned short)(((uintptr)head - (uintptr)block->data) / block->unit_size); + block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size); } } } @@ -636,7 +636,6 @@ static void memmgr_final (void) fclose(log_fp); } #endif /* LOG_MEMMGR */ - return; } static void memmgr_init (void) @@ -646,7 +645,6 @@ static void memmgr_init (void) ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); memset(hash_unfill, 0, sizeof(hash_unfill)); #endif /* LOG_MEMMGR */ - return; } #endif /* USE_MEMMGR */ @@ -679,7 +677,6 @@ void malloc_final (void) #ifdef USE_MEMMGR memmgr_final (); #endif - return; } void malloc_init (void) @@ -687,5 +684,4 @@ void malloc_init (void) #ifdef USE_MEMMGR memmgr_init (); #endif - return; } diff --git a/src/common/mmo.h b/src/common/mmo.h index 0bc30ea47..f9037e913 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -207,8 +207,19 @@ struct point { short x,y; }; +enum e_skill_flag +{ + SKILL_FLAG_PERMANENT, + SKILL_FLAG_TEMPORARY, + SKILL_FLAG_PLAGIARIZED, + SKILL_FLAG_REPLACED_LV_0, // temporary skill overshadowing permanent skill of level 'N - SKILL_FLAG_REPLACED_LV_0' + //... +}; + struct s_skill { - unsigned short id,lv,flag; + unsigned short id; + unsigned short lv; + unsigned short flag; // see enum e_skill_flag }; struct global_reg { @@ -508,12 +519,6 @@ struct guild_castle { int temp_guardians_max; }; -// for Brandish Spear calculations -struct square { - int val1[5]; - int val2[5]; -}; - struct fame_list { int id; int fame; diff --git a/src/common/plugin.h b/src/common/plugin.h index fd01be762..a367d2537 100644 --- a/src/common/plugin.h +++ b/src/common/plugin.h @@ -4,9 +4,7 @@ #ifndef _PLUGIN_H_ #define _PLUGIN_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif ////// Plugin functions /////////////// diff --git a/src/common/plugins.h b/src/common/plugins.h index e71a4e8c5..c1cf17afd 100644 --- a/src/common/plugins.h +++ b/src/common/plugins.h @@ -4,10 +4,7 @@ #ifndef _PLUGINS_H_ #define _PLUGINS_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif - #include "../common/plugin.h" ////// Dynamic Link Library functions /////////////// diff --git a/src/common/random.c b/src/common/random.c new file mode 100644 index 000000000..b7f2c080c --- /dev/null +++ b/src/common/random.c @@ -0,0 +1,83 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/timer.h" // gettick +#include "random.h" +#if defined(WIN32) + #define WIN32_LEAN_AND_MEAN + #include <windows.h> +#elif defined(HAVE_GETPID) || defined(HAVE_GETTID) + #include <sys/types.h> + #include <unistd.h> +#endif +#include <time.h> // time +#include <mt19937ar.h> // init_genrand, genrand_int32, genrand_res53 + + +/// Initializes the random number generator with an appropriate seed. +void rnd_init(void) +{ + uint32 seed = gettick(); + seed += (uint32)time(NULL); +#if defined(WIN32) + seed += GetCurrentProcessId(); + seed += GetCurrentThreadId(); +#else +#if defined(HAVE_GETPID) + seed += (uint32)getpid(); +#endif // HAVE_GETPID +#if defined(HAVE_GETTID) + seed += (uint32)gettid(); +#endif // HAVE_GETTID +#endif + init_genrand(seed); +} + + +/// Initializes the random number generator. +void rnd_seed(uint32 seed) +{ + init_genrand(seed); +} + + +/// Generates a random number in the interval [0, UINT32_MAX] +uint32 rnd(void) +{ + return (uint32)genrand_int32(); +} + + +/// Generates a random number in the interval [0, dice_faces) +/// NOTE: interval is open ended, so dice_faces is excluded (unless it's 0) +uint32 rnd_roll(uint32 dice_faces) +{ + return (uint32)(rnd_uniform()*dice_faces); +} + + +/// Generates a random number in the interval [min, max] +/// Returns min if range is invalid. +int32 rnd_value(int32 min, int32 max) +{ + if( min >= max ) + return min; + return min + (int32)(rnd_uniform()*(max-min+1)); +} + + +/// Generates a random number in the interval [0.0, 1.0) +/// NOTE: interval is open ended, so 1.0 is excluded +double rnd_uniform(void) +{ + return ((uint32)genrand_int32())*(1.0/4294967296.0);// divided by 2^32 +} + + +/// Generates a random number in the interval [0.0, 1.0) with 53-bit resolution +/// NOTE: interval is open ended, so 1.0 is excluded +/// NOTE: 53 bits is the maximum precision of a double +double rnd_uniform53(void) +{ + return genrand_res53(); +} diff --git a/src/common/random.h b/src/common/random.h new file mode 100644 index 000000000..59b609464 --- /dev/null +++ b/src/common/random.h @@ -0,0 +1,18 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _RANDOM_H_ +#define _RANDOM_H_ + +#include "../common/cbasetypes.h" + +void rnd_init(void); +void rnd_seed(uint32); + +uint32 rnd(void);// [0, UINT32_MAX] +uint32 rnd_roll(uint32 dice_faces);// [0, dice_faces) +int32 rnd_value(int32 min, int32 max);// [min, max] +double rnd_uniform(void);// [0.0, 1.0) +double rnd_uniform53(void);// [0.0, 1.0) + +#endif /* _RANDOM_H_ */ diff --git a/src/common/socket.c b/src/common/socket.c index 262351dcf..81ea19468 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -938,7 +938,7 @@ static int connect_check_(uint32 ip) /// Timer function. /// Deletes old connection history records. -static int connect_check_clear(int tid, unsigned int tick, int id, intptr data) +static int connect_check_clear(int tid, unsigned int tick, int id, intptr_t data) { int i; int clear = 0; @@ -1118,6 +1118,9 @@ void socket_final(void) /// Closes a socket. void do_close(int fd) { + if( fd <= 0 ||fd >= FD_SETSIZE ) + return;// invalid + flush_fifo(fd); // Try to send what's left (although it might not succeed since it's a nonblocking socket) sFD_CLR(fd, &readfds);// this needs to be done before closing the socket sShutdown(fd, SHUT_RDWR); // Disallow further reads/writes diff --git a/src/common/socket.h b/src/common/socket.h index 2f0ec6081..a5d519d0e 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -4,9 +4,7 @@ #ifndef _SOCKET_H_ #define _SOCKET_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #ifdef WIN32 #define WIN32_LEAN_AND_MEAN // otherwise winsock2.h includes full windows.h diff --git a/src/common/sql.c b/src/common/sql.c index d8e397e8d..edac5a297 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -182,7 +182,7 @@ int Sql_Ping(Sql* self) /// Wrapper function for Sql_Ping. /// /// @private -static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr data) +static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr_t data) { Sql* self = (Sql*)data; ShowInfo("Pinging SQL server to keep connection alive...\n"); @@ -212,7 +212,7 @@ static int Sql_P_Keepalive(Sql* self) // establish keepalive ping_interval = timeout - 30; // 30-second reserve //add_timer_func_list(Sql_P_KeepaliveTimer, "Sql_P_KeepaliveTimer"); - return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr)self, ping_interval*1000); + return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr_t)self, ping_interval*1000); } diff --git a/src/common/sql.h b/src/common/sql.h index ef76b2ec5..5b318ab4d 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -4,9 +4,7 @@ #ifndef _COMMON_SQL_H_ #define _COMMON_SQL_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #include <stdarg.h>// va_list diff --git a/src/common/strlib.c b/src/common/strlib.c index 66f281ffc..097f499e6 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -441,30 +441,13 @@ bool bin2hex(char* output, unsigned char* input, size_t count) ///////////////////////////////////////////////////////////////////// -/// Parses a delim-separated string. -/// Starts parsing at startoff and fills the pos array with position pairs. -/// out_pos[0] and out_pos[1] are the start and end of line. -/// Other position pairs are the start and end of fields. -/// Returns the number of fields found or -1 if an error occurs. -/// -/// out_pos can be NULL. -/// If a line terminator is found, the end position is placed there. -/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] -/// for the seconds field and so on. -/// Unfilled positions are set to -1. -/// -/// @param str String to parse -/// @param len Length of the string -/// @param startoff Where to start parsing -/// @param delim Field delimiter -/// @param out_pos Array of resulting positions -/// @param npos Size of the pos array -/// @param opt Options that determine the parsing behaviour -/// @return Number of fields found in the string or -1 if an error occured -int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) +/// Parses a single field in a delim-separated string. +/// The delimiter after the field is skipped. +/// +/// @param sv Parse state +/// @return 1 if a field was parsed, 0 if already done, -1 on error. +int sv_parse_next(struct s_svstate* sv) { - int i; - int count; enum { START_OF_FIELD, PARSING_FIELD, @@ -473,27 +456,37 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i TERMINATE, END } state; + const char* str; + int len; + enum e_svopt opt; + char delim; + int i; - // check pos/npos - if( out_pos == NULL ) npos = 0; - for( i = 0; i < npos; ++i ) - out_pos[i] = -1; + if( sv == NULL ) + return -1;// error + + str = sv->str; + len = sv->len; + opt = sv->opt; + delim = sv->delim; // check opt if( delim == '\n' && (opt&(SV_TERMINATE_CRLF|SV_TERMINATE_LF)) ) { - ShowError("sv_parse: delimiter '\\n' is not compatible with options SV_TERMINATE_LF or SV_TERMINATE_CRLF.\n"); + ShowError("sv_parse_next: delimiter '\\n' is not compatible with options SV_TERMINATE_LF or SV_TERMINATE_CRLF.\n"); return -1;// error } if( delim == '\r' && (opt&(SV_TERMINATE_CRLF|SV_TERMINATE_CR)) ) { - ShowError("sv_parse: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n"); + ShowError("sv_parse_next: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n"); return -1;// error } - // check str - if( str == NULL ) + if( sv->done || str == NULL ) + { + sv->done = true; return 0;// nothing to parse + } #define IS_END() ( i >= len ) #define IS_DELIM() ( str[i] == delim ) @@ -502,16 +495,13 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i ((opt&SV_TERMINATE_CR) && str[i] == '\r') || \ ((opt&SV_TERMINATE_CRLF) && i+1 < len && str[i] == '\r' && str[i+1] == '\n') ) #define IS_C_ESCAPE() ( (opt&SV_ESCAPE_C) && str[i] == '\\' ) -#define SET_FIELD_START() if( npos > count*2+2 ) out_pos[count*2+2] = i -#define SET_FIELD_END() if( npos > count*2+3 ) out_pos[count*2+3] = i; ++count +#define SET_FIELD_START() sv->start = i +#define SET_FIELD_END() sv->end = i - i = startoff; - count = 0; + i = sv->off; state = START_OF_FIELD; - if( npos > 0 ) out_pos[0] = startoff;// start while( state != END ) { - if( npos > 1 ) out_pos[1] = i;// end switch( state ) { case START_OF_FIELD:// record start of field and start parsing it @@ -533,7 +523,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i ++i;// '\\' if( IS_END() ) { - ShowError("sv_parse: empty escape sequence\n"); + ShowError("sv_parse_next: empty escape sequence\n"); return -1; } if( str[i] == 'x' ) @@ -541,7 +531,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i ++i;// 'x' if( IS_END() || !ISXDIGIT(str[i]) ) { - ShowError("sv_parse: \\x with no following hex digits\n"); + ShowError("sv_parse_next: \\x with no following hex digits\n"); return -1; } do{ @@ -562,26 +552,22 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i } else { - ShowError("sv_parse: unknown escape sequence \\%c\n", str[i]); + ShowError("sv_parse_next: unknown escape sequence \\%c\n", str[i]); return -1; } state = PARSING_FIELD; break; } - case END_OF_FIELD:// record end of field and continue + case END_OF_FIELD:// record end of field and stop SET_FIELD_END(); + state = END; if( IS_END() ) - state = END; + ;// nothing else else if( IS_DELIM() ) - { ++i;// delim - state = START_OF_FIELD; - } else if( IS_TERMINATOR() ) state = TERMINATE; - else - state = START_OF_FIELD; break; case TERMINATE: @@ -592,10 +578,14 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i else ++i;// CR or LF #endif + sv->done = true; state = END; break; } } + if( IS_END() ) + sv->done = true; + sv->off = i; #undef IS_END #undef IS_DELIM @@ -604,6 +594,58 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i #undef SET_FIELD_START #undef SET_FIELD_END + return 1; +} + + +/// Parses a delim-separated string. +/// Starts parsing at startoff and fills the pos array with position pairs. +/// out_pos[0] and out_pos[1] are the start and end of line. +/// Other position pairs are the start and end of fields. +/// Returns the number of fields found or -1 if an error occurs. +/// +/// out_pos can be NULL. +/// If a line terminator is found, the end position is placed there. +/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] +/// for the seconds field and so on. +/// Unfilled positions are set to -1. +/// +/// @param str String to parse +/// @param len Length of the string +/// @param startoff Where to start parsing +/// @param delim Field delimiter +/// @param out_pos Array of resulting positions +/// @param npos Size of the pos array +/// @param opt Options that determine the parsing behaviour +/// @return Number of fields found in the string or -1 if an error occured +int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) +{ + struct s_svstate sv; + int count; + + // initialize + if( out_pos == NULL ) npos = 0; + for( count = 0; count < npos; ++count ) + out_pos[count] = -1; + sv.str = str; + sv.len = len; + sv.off = startoff; + sv.opt = opt; + sv.delim = delim; + sv.done = false; + + // parse + count = 0; + if( npos > 0 ) out_pos[0] = startoff; + while( !sv.done ) + { + ++count; + if( sv_parse_next(&sv) <= 0 ) + return -1;// error + if( npos > count*2 ) out_pos[count*2] = sv.start; + if( npos > count*2+1 ) out_pos[count*2+1] = sv.end; + } + if( npos > 1 ) out_pos[1] = sv.off; return count; } diff --git a/src/common/strlib.h b/src/common/strlib.h index 3f4f984cf..bbc2c6105 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -4,9 +4,7 @@ #ifndef _STRLIB_H_ #define _STRLIB_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #include <stdarg.h> #define __USE_GNU // required to enable strnlen on some platforms @@ -78,6 +76,27 @@ typedef enum e_svopt /// Other escape sequences supported by the C compiler. #define SV_ESCAPE_C_SUPPORTED "abtnvfr\?\"'\\" +/// Parse state. +/// The field is [start,end[ +struct s_svstate +{ + const char* str; //< string to parse + int len; //< string length + int off; //< current offset in the string + int start; //< where the field starts + int end; //< where the field ends + enum e_svopt opt; //< parse options + char delim; //< field delimiter + bool done; //< if all the text has been parsed +}; + +/// Parses a single field in a delim-separated string. +/// The delimiter after the field is skipped. +/// +/// @param sv Parse state +/// @return 1 if a field was parsed, 0 if done, -1 on error. +int sv_parse_next(struct s_svstate* sv); + /// Parses a delim-separated string. /// Starts parsing at startoff and fills the pos array with position pairs. /// out_pos[0] and out_pos[1] are the start and end of line. diff --git a/src/common/timer.c b/src/common/timer.c index 86e148ee3..05c53b8a3 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -241,7 +241,7 @@ static int acquire_timer(void) /// Starts a new timer that is deleted once it expires (single-use). /// Returns the timer's id. -int add_timer(unsigned int tick, TimerFunc func, int id, intptr data) +int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data) { int tid; @@ -259,7 +259,7 @@ int add_timer(unsigned int tick, TimerFunc func, int id, intptr data) /// Starts a new timer that automatically restarts itself (infinite loop until manually removed). /// Returns the timer's id, or INVALID_TIMER if it fails. -int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, int interval) +int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval) { int tid; diff --git a/src/common/timer.h b/src/common/timer.h index 354a71113..a615a5874 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -4,9 +4,7 @@ #ifndef _TIMER_H_ #define _TIMER_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #define DIFF_TICK(a,b) ((int)((a)-(b))) @@ -19,7 +17,7 @@ // Struct declaration -typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr data); +typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data); struct TimerData { unsigned int tick; @@ -30,7 +28,7 @@ struct TimerData { // general-purpose storage int id; - intptr data; + intptr_t data; }; // Function prototype declaration @@ -38,8 +36,8 @@ struct TimerData { unsigned int gettick(void); unsigned int gettick_nocache(void); -int add_timer(unsigned int tick, TimerFunc func, int id, intptr data); -int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, int interval); +int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data); +int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); const struct TimerData* get_timer(int tid); int delete_timer(int tid, TimerFunc func); diff --git a/src/common/utils.h b/src/common/utils.h index 2fe078615..8e39f2655 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -4,10 +4,7 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif - #include <stdio.h> // FILE* // generate a hex dump of the first 'length' bytes of 'buffer' |