summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt144
-rw-r--r--src/common/Makefile.in25
-rw-r--r--src/common/cbasetypes.h111
-rw-r--r--src/common/core.c14
-rw-r--r--src/common/core.h13
-rw-r--r--src/common/db.c91
-rw-r--r--src/common/db.h20
-rw-r--r--src/common/ers.h2
-rw-r--r--src/common/grfio.c36
-rw-r--r--src/common/grfio.h5
-rw-r--r--src/common/malloc.c10
-rw-r--r--src/common/mmo.h19
-rw-r--r--src/common/plugin.h2
-rw-r--r--src/common/plugins.h3
-rw-r--r--src/common/random.c83
-rw-r--r--src/common/random.h18
-rw-r--r--src/common/socket.c5
-rw-r--r--src/common/socket.h2
-rw-r--r--src/common/sql.c4
-rw-r--r--src/common/sql.h2
-rw-r--r--src/common/strlib.c136
-rw-r--r--src/common/strlib.h23
-rw-r--r--src/common/timer.c4
-rw-r--r--src/common/timer.h10
-rw-r--r--src/common/utils.h3
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'