summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/atomic.h139
-rw-r--r--src/common/cbasetypes.h147
-rw-r--r--src/common/conf.c147
-rw-r--r--src/common/core.c447
-rw-r--r--src/common/core.h29
-rw-r--r--src/common/db.c3246
-rw-r--r--src/common/db.h1041
-rw-r--r--src/common/des.c316
-rw-r--r--src/common/des.h12
-rw-r--r--src/common/ers.c316
-rw-r--r--src/common/ers.h106
-rw-r--r--src/common/evdp.h130
-rw-r--r--src/common/evdp_epoll.c356
-rw-r--r--src/common/grfio.c1205
-rw-r--r--src/common/grfio.h14
-rw-r--r--src/common/malloc.c1006
-rw-r--r--src/common/malloc.h58
-rw-r--r--src/common/mapindex.c251
-rw-r--r--src/common/mapindex.h10
-rw-r--r--src/common/md5calc.c362
-rw-r--r--src/common/md5calc.h6
-rw-r--r--src/common/mempool.c899
-rw-r--r--src/common/mempool.h62
-rw-r--r--src/common/mmo.h929
-rw-r--r--src/common/mutex.c256
-rw-r--r--src/common/mutex.h50
-rw-r--r--src/common/netbuffer.c349
-rw-r--r--src/common/netbuffer.h78
-rw-r--r--src/common/network.c1809
-rw-r--r--src/common/network.h220
-rw-r--r--src/common/nullpo.c96
-rw-r--r--src/common/nullpo.h30
-rw-r--r--src/common/raconf.c1037
-rw-r--r--src/common/raconf.h34
-rw-r--r--src/common/random.c36
-rw-r--r--src/common/showmsg.c1351
-rw-r--r--src/common/showmsg.h104
-rw-r--r--src/common/socket.c1983
-rw-r--r--src/common/socket.h75
-rw-r--r--src/common/spinlock.h108
-rw-r--r--src/common/sql.c1216
-rw-r--r--src/common/sql.h139
-rw-r--r--src/common/strlib.c1729
-rw-r--r--src/common/strlib.h119
-rw-r--r--src/common/thread.c384
-rw-r--r--src/common/thread.h62
-rw-r--r--src/common/timer.c479
-rw-r--r--src/common/timer.h32
-rw-r--r--src/common/utils.c403
-rw-r--r--src/common/utils.h8
-rw-r--r--src/common/winapi.h6
51 files changed, 11716 insertions, 11711 deletions
diff --git a/src/common/atomic.h b/src/common/atomic.h
index b1a4bda92..a7e953db2 100644
--- a/src/common/atomic.h
+++ b/src/common/atomic.h
@@ -4,16 +4,16 @@
#ifndef _rA_ATOMIC_H_
#define _rA_ATOMIC_H_
-// Atomic Operations
+// Atomic Operations
// (Interlocked CompareExchange, Add .. and so on ..)
-//
+//
// Implementation varies / depends on:
-// - Architecture
-// - Compiler
-// - Operating System
+// - Architecture
+// - Compiler
+// - Operating System
//
// our Abstraction is fully API-Compatible to Microsofts implementation @ NT5.0+
-//
+//
#include "../common/cbasetypes.h"
#if defined(_MSC_VER)
@@ -22,60 +22,65 @@
#if !defined(_M_X64)
// When compiling for windows 32bit, the 8byte interlocked operations are not provided by microsoft
// (because they need at least i586 so its not generic enough.. ... )
-forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 _cmp){
- _asm{
- lea esi,_cmp;
- lea edi,exch;
-
- mov eax,[esi];
- mov edx,4[esi];
- mov ebx,[edi];
- mov ecx,4[edi];
- mov esi,dest;
-
- lock CMPXCHG8B [esi];
- }
+forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 _cmp)
+{
+ _asm {
+ lea esi,_cmp;
+ lea edi,exch;
+
+ mov eax,[esi];
+ mov edx,4[esi];
+ mov ebx,[edi];
+ mov ecx,4[edi];
+ mov esi,dest;
+
+ lock CMPXCHG8B [esi];
+ }
}
-forceinline volatile int64 InterlockedIncrement64(volatile int64 *addend){
- __int64 old;
- do{
- old = *addend;
- }while(InterlockedCompareExchange64(addend, (old+1), old) != old);
+forceinline volatile int64 InterlockedIncrement64(volatile int64 *addend)
+{
+ __int64 old;
+ do {
+ old = *addend;
+ } while (InterlockedCompareExchange64(addend, (old+1), old) != old);
- return (old + 1);
+ return (old + 1);
}
-forceinline volatile int64 InterlockedDecrement64(volatile int64 *addend){
- __int64 old;
+forceinline volatile int64 InterlockedDecrement64(volatile int64 *addend)
+{
+ __int64 old;
- do{
- old = *addend;
- }while(InterlockedCompareExchange64(addend, (old-1), old) != old);
+ do {
+ old = *addend;
+ } while (InterlockedCompareExchange64(addend, (old-1), old) != old);
- return (old - 1);
+ return (old - 1);
}
-forceinline volatile int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment){
- __int64 old;
+forceinline volatile int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment)
+{
+ __int64 old;
- do{
- old = *addend;
- }while(InterlockedCompareExchange64(addend, (old + increment), old) != old);
+ do {
+ old = *addend;
+ } while (InterlockedCompareExchange64(addend, (old + increment), old) != old);
- return old;
+ return old;
}
-forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 val){
- __int64 old;
- do{
- old = *target;
- }while(InterlockedCompareExchange64(target, val, old) != old);
+forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 val)
+{
+ __int64 old;
+ do {
+ old = *target;
+ } while (InterlockedCompareExchange64(target, val, old) != old);
- return old;
+ return old;
}
#endif //endif 32bit windows
@@ -86,52 +91,62 @@ forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 v
#error Your Target Platfrom is not supported
#endif
-static forceinline int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment){
- return __sync_fetch_and_add(addend, increment);
+static forceinline int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment)
+{
+ return __sync_fetch_and_add(addend, increment);
}//end: InterlockedExchangeAdd64()
-static forceinline int32 InterlockedExchangeAdd(volatile int32 *addend, int32 increment){
- return __sync_fetch_and_add(addend, increment);
+static forceinline int32 InterlockedExchangeAdd(volatile int32 *addend, int32 increment)
+{
+ return __sync_fetch_and_add(addend, increment);
}//end: InterlockedExchangeAdd()
-static forceinline int64 InterlockedIncrement64(volatile int64 *addend){
- return __sync_add_and_fetch(addend, 1);
+static forceinline int64 InterlockedIncrement64(volatile int64 *addend)
+{
+ return __sync_add_and_fetch(addend, 1);
}//end: InterlockedIncrement64()
-static forceinline int32 InterlockedIncrement(volatile int32 *addend){
- return __sync_add_and_fetch(addend, 1);
+static forceinline int32 InterlockedIncrement(volatile int32 *addend)
+{
+ return __sync_add_and_fetch(addend, 1);
}//end: InterlockedIncrement()
-static forceinline int64 InterlockedDecrement64(volatile int64 *addend){
- return __sync_sub_and_fetch(addend, 1);
+static forceinline int64 InterlockedDecrement64(volatile int64 *addend)
+{
+ return __sync_sub_and_fetch(addend, 1);
}//end: InterlockedDecrement64()
-static forceinline int32 InterlockedDecrement(volatile int32 *addend){
- return __sync_sub_and_fetch(addend, 1);
+static forceinline int32 InterlockedDecrement(volatile int32 *addend)
+{
+ return __sync_sub_and_fetch(addend, 1);
}//end: InterlockedDecrement()
-static forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 cmp){
- return __sync_val_compare_and_swap(dest, cmp, exch);
+static forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 cmp)
+{
+ return __sync_val_compare_and_swap(dest, cmp, exch);
}//end: InterlockedCompareExchange64()
-static forceinline int32 InterlockedCompareExchange(volatile int32 *dest, int32 exch, int32 cmp){
- return __sync_val_compare_and_swap(dest, cmp, exch);
+static forceinline int32 InterlockedCompareExchange(volatile int32 *dest, int32 exch, int32 cmp)
+{
+ return __sync_val_compare_and_swap(dest, cmp, exch);
}//end: InterlockedCompareExchnage()
-static forceinline int64 InterlockedExchange64(volatile int64 *target, int64 val){
- return __sync_lock_test_and_set(target, val);
+static forceinline int64 InterlockedExchange64(volatile int64 *target, int64 val)
+{
+ return __sync_lock_test_and_set(target, val);
}//end: InterlockedExchange64()
-static forceinline int32 InterlockedExchange(volatile int32 *target, int32 val){
+static forceinline int32 InterlockedExchange(volatile int32 *target, int32 val)
+{
return __sync_lock_test_and_set(target, val);
}//end: InterlockedExchange()
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h
index 731a8b578..a47a7434f 100644
--- a/src/common/cbasetypes.h
+++ b/src/common/cbasetypes.h
@@ -59,11 +59,11 @@
// debug function name
#ifndef __NETBSD__
#if __STDC_VERSION__ < 199901L
-# if __GNUC__ >= 2
-# define __func__ __FUNCTION__
-# else
-# define __func__ ""
-# endif
+# if __GNUC__ >= 2
+# define __func__ __FUNCTION__
+# else
+# define __func__ ""
+# endif
#endif
#endif
@@ -106,56 +106,56 @@
// Integers with guaranteed _exact_ size.
//////////////////////////////////////////////////////////////////////////
-typedef int8_t int8;
-typedef int16_t int16;
-typedef int32_t int32;
-typedef int64_t int64;
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
-typedef int8_t sint8;
-typedef int16_t sint16;
-typedef int32_t sint32;
-typedef int64_t sint64;
+typedef int8_t sint8;
+typedef int16_t sint16;
+typedef int32_t sint32;
+typedef int64_t sint64;
-typedef uint8_t uint8;
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-typedef uint64_t uint64;
+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
#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))
+#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
#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))
+#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
#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))
+#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
#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))
+#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.
@@ -180,10 +180,10 @@ typedef unsigned long int ppuint32;
#if defined(WIN32) && !defined(MINGW) // does not have a signed size_t
//////////////////////////////
-#if defined(_WIN64) // naive 64bit windows platform
-typedef __int64 ssize_t;
+#if defined(_WIN64) // naive 64bit windows platform
+typedef __int64 ssize_t;
#else
-typedef int ssize_t;
+typedef int ssize_t;
#endif
//////////////////////////////
#endif
@@ -201,23 +201,23 @@ typedef uintptr_t uintptr;
// Add a 'sysint' Type which has the width of the platform we're compiled for.
//////////////////////////////////////////////////////////////////////////
#if defined(__GNUC__)
- #if defined(__x86_64__)
- typedef int64 sysint;
- typedef uint64 usysint;
- #else
- typedef int32 sysint;
- typedef uint32 usysint;
- #endif
+#if defined(__x86_64__)
+typedef int64 sysint;
+typedef uint64 usysint;
+#else
+typedef int32 sysint;
+typedef uint32 usysint;
+#endif
#elif defined(_MSC_VER)
- #if defined(_M_X64)
- typedef int64 sysint;
- typedef uint64 usysint;
- #else
- typedef int32 sysint;
- typedef uint32 usysint;
- #endif
+#if defined(_M_X64)
+typedef int64 sysint;
+typedef uint64 usysint;
+#else
+typedef int32 sysint;
+typedef uint32 usysint;
+#endif
#else
- #error Compiler / Platform is unsupported.
+#error Compiler / Platform is unsupported.
#endif
@@ -225,21 +225,21 @@ typedef uintptr_t uintptr;
// some redefine of function redefines for some Compilers
//////////////////////////////////////////////////////////////////////////
#if defined(_MSC_VER) || defined(__BORLANDC__)
-#define strcasecmp stricmp
-#define strncasecmp strnicmp
-#define strncmpi strnicmp
-#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#define strncmpi strnicmp
+#define snprintf _snprintf
#if defined(_MSC_VER) && _MSC_VER < 1400
-#define vsnprintf _vsnprintf
+#define vsnprintf _vsnprintf
#endif
#else
-#define strcmpi strcasecmp
-#define stricmp strcasecmp
-#define strncmpi strncasecmp
-#define strnicmp strncasecmp
+#define strcmpi strcasecmp
+#define stricmp strcasecmp
+#define strncmpi strncasecmp
+#define strnicmp strncasecmp
#endif
#if defined(_MSC_VER) && _MSC_VER > 1200
-#define strtoull _strtoui64
+#define strtoull _strtoui64
#endif
// keyword replacement
@@ -262,8 +262,8 @@ typedef uintptr_t uintptr;
// boolean types for C
typedef char bool;
-#define false (1==0)
-#define true (1==1)
+#define false (1==0)
+#define true (1==1)
//////////////////////////////
#endif // not __cplusplus
@@ -276,7 +276,7 @@ typedef char bool;
#undef swap
#endif
// hmm only ints?
-//#define swap(a,b) { int temp=a; a=b; b=temp;}
+//#define swap(a,b) { int temp=a; a=b; b=temp;}
// if using macros then something that is type independent
//#define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b)))
// Avoid "value computed is not used" warning and generates the same assembly code
@@ -299,7 +299,7 @@ typedef char bool;
//////////////////////////////////////////////////////////////////////////
// number of bits in a byte
#ifndef NBBY
-#define NBBY 8
+#define NBBY 8
#endif
//////////////////////////////////////////////////////////////////////////
@@ -383,17 +383,20 @@ typedef char bool;
// Set a pointer variable to a pointer value.
#ifdef __cplusplus
template <typename T1, typename T2>
-void SET_POINTER(T1*&var, T2* p)
+void SET_POINTER(T1 *&var, T2 *p)
{
- var = static_cast<T1*>(p);
+ var = static_cast<T1 *>(p);
}
template <typename T1, typename T2>
-void SET_FUNCPOINTER(T1& var, T2 p)
+void SET_FUNCPOINTER(T1 &var, T2 p)
{
- char ASSERT_POINTERSIZE[sizeof(T1) == sizeof(void*) && sizeof(T2) == sizeof(void*)?1:-1];// 1 if true, -1 if false
- union{ T1 out; T2 in; } tmp;// /!\ WARNING casting a pointer to a function pointer is against the C++ standard
- tmp.in = p;
- var = tmp.out;
+ char ASSERT_POINTERSIZE[sizeof(T1) == sizeof(void *) && sizeof(T2) == sizeof(void *)?1:-1]; // 1 if true, -1 if false
+ union {
+ T1 out;
+ T2 in;
+ } tmp;// /!\ WARNING casting a pointer to a function pointer is against the C++ standard
+ tmp.in = p;
+ var = tmp.out;
}
#else
#define SET_POINTER(var,p) (var) = (p)
diff --git a/src/common/conf.c b/src/common/conf.c
index 3057bd4dc..2027b4b09 100644
--- a/src/common/conf.c
+++ b/src/common/conf.c
@@ -8,14 +8,14 @@
int conf_read_file(config_t *config, const char *config_filename)
{
- config_init(config);
- if (!config_read_file(config, config_filename)) {
- ShowError("%s:%d - %s\n", config_error_file(config),
- config_error_line(config), config_error_text(config));
- config_destroy(config);
- return 1;
- }
- return 0;
+ config_init(config);
+ if (!config_read_file(config, config_filename)) {
+ ShowError("%s:%d - %s\n", config_error_file(config),
+ config_error_line(config), config_error_text(config));
+ config_destroy(config);
+ return 1;
+ }
+ return 0;
}
//
@@ -28,82 +28,81 @@ int config_setting_copy(config_setting_t *parent, const config_setting_t *src);
void config_setting_copy_simple(config_setting_t *parent, const config_setting_t *src)
{
- if (config_setting_is_aggregate(src)) {
- config_setting_copy_aggregate(parent, src);
- }
- else {
- config_setting_t *set = config_setting_add(parent, config_setting_name(src), config_setting_type(src));
-
- if (set == NULL)
- return;
-
- if (CONFIG_TYPE_INT == config_setting_type(src)) {
- config_setting_set_int(set, config_setting_get_int(src));
- config_setting_set_format(set, src->format);
- } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) {
- config_setting_set_int64(set, config_setting_get_int64(src));
- config_setting_set_format(set, src->format);
- } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) {
- config_setting_set_float(set, config_setting_get_float(src));
- } else if (CONFIG_TYPE_STRING == config_setting_type(src)) {
- config_setting_set_string(set, config_setting_get_string(src));
- } else if (CONFIG_TYPE_BOOL == config_setting_type(src)) {
- config_setting_set_bool(set, config_setting_get_bool(src));
- }
- }
+ if (config_setting_is_aggregate(src)) {
+ config_setting_copy_aggregate(parent, src);
+ } else {
+ config_setting_t *set = config_setting_add(parent, config_setting_name(src), config_setting_type(src));
+
+ if (set == NULL)
+ return;
+
+ if (CONFIG_TYPE_INT == config_setting_type(src)) {
+ config_setting_set_int(set, config_setting_get_int(src));
+ config_setting_set_format(set, src->format);
+ } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) {
+ config_setting_set_int64(set, config_setting_get_int64(src));
+ config_setting_set_format(set, src->format);
+ } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) {
+ config_setting_set_float(set, config_setting_get_float(src));
+ } else if (CONFIG_TYPE_STRING == config_setting_type(src)) {
+ config_setting_set_string(set, config_setting_get_string(src));
+ } else if (CONFIG_TYPE_BOOL == config_setting_type(src)) {
+ config_setting_set_bool(set, config_setting_get_bool(src));
+ }
+ }
}
void config_setting_copy_elem(config_setting_t *parent, const config_setting_t *src)
{
- config_setting_t *set = NULL;
-
- if (config_setting_is_aggregate(src))
- config_setting_copy_aggregate(parent, src);
- else if (CONFIG_TYPE_INT == config_setting_type(src)) {
- set = config_setting_set_int_elem(parent, -1, config_setting_get_int(src));
- config_setting_set_format(set, src->format);
- } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) {
- set = config_setting_set_int64_elem(parent, -1, config_setting_get_int64(src));
- config_setting_set_format(set, src->format);
- } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) {
- config_setting_set_float_elem(parent, -1, config_setting_get_float(src));
- } else if (CONFIG_TYPE_STRING == config_setting_type(src)) {
- config_setting_set_string_elem(parent, -1, config_setting_get_string(src));
- } else if (CONFIG_TYPE_BOOL == config_setting_type(src)) {
- config_setting_set_bool_elem(parent, -1, config_setting_get_bool(src));
- }
+ config_setting_t *set = NULL;
+
+ if (config_setting_is_aggregate(src))
+ config_setting_copy_aggregate(parent, src);
+ else if (CONFIG_TYPE_INT == config_setting_type(src)) {
+ set = config_setting_set_int_elem(parent, -1, config_setting_get_int(src));
+ config_setting_set_format(set, src->format);
+ } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) {
+ set = config_setting_set_int64_elem(parent, -1, config_setting_get_int64(src));
+ config_setting_set_format(set, src->format);
+ } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) {
+ config_setting_set_float_elem(parent, -1, config_setting_get_float(src));
+ } else if (CONFIG_TYPE_STRING == config_setting_type(src)) {
+ config_setting_set_string_elem(parent, -1, config_setting_get_string(src));
+ } else if (CONFIG_TYPE_BOOL == config_setting_type(src)) {
+ config_setting_set_bool_elem(parent, -1, config_setting_get_bool(src));
+ }
}
void config_setting_copy_aggregate(config_setting_t *parent, const config_setting_t *src)
{
- config_setting_t *newAgg;
- int i, n;
-
- newAgg = config_setting_add(parent, config_setting_name(src), config_setting_type(src));
-
- if (newAgg == NULL)
- return;
-
- n = config_setting_length(src);
-
- for (i = 0; i < n; i++) {
- if (config_setting_is_group(src)) {
- config_setting_copy_simple(newAgg, config_setting_get_elem(src, i));
- } else {
- config_setting_copy_elem(newAgg, config_setting_get_elem(src, i));
- }
- }
+ config_setting_t *newAgg;
+ int i, n;
+
+ newAgg = config_setting_add(parent, config_setting_name(src), config_setting_type(src));
+
+ if (newAgg == NULL)
+ return;
+
+ n = config_setting_length(src);
+
+ for (i = 0; i < n; i++) {
+ if (config_setting_is_group(src)) {
+ config_setting_copy_simple(newAgg, config_setting_get_elem(src, i));
+ } else {
+ config_setting_copy_elem(newAgg, config_setting_get_elem(src, i));
+ }
+ }
}
int config_setting_copy(config_setting_t *parent, const config_setting_t *src)
{
- if (!config_setting_is_group(parent) && !config_setting_is_list(parent))
- return CONFIG_FALSE;
-
- if (config_setting_is_aggregate(src)) {
- config_setting_copy_aggregate(parent, src);
- } else {
- config_setting_copy_simple(parent, src);
- }
- return CONFIG_TRUE;
+ if (!config_setting_is_group(parent) && !config_setting_is_list(parent))
+ return CONFIG_FALSE;
+
+ if (config_setting_is_aggregate(src)) {
+ config_setting_copy_aggregate(parent, src);
+ } else {
+ config_setting_copy_simple(parent, src);
+ }
+ return CONFIG_TRUE;
}
diff --git a/src/common/core.c b/src/common/core.c
index e1f99885b..efab15dcb 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -28,7 +28,7 @@
void (*shutdown_callback)(void) = NULL;
#if defined(BUILDBOT)
- int buildbotflag = 0;
+int buildbotflag = 0;
#endif
int runflag = CORE_ST_RUN;
@@ -38,14 +38,14 @@ char **arg_v = NULL;
char *SERVER_NAME = NULL;
char SERVER_TYPE = ATHENA_SERVER_NONE;
-#ifndef MINICORE // minimalist Core
+#ifndef MINICORE // minimalist Core
// Added by Gabuzomeu
//
// This is an implementation of signal() using sigaction() for portability.
// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced
// Programming in the UNIX Environment_.
//
-#ifdef WIN32 // windows don't have SIGPIPE
+#ifdef WIN32 // windows don't have SIGPIPE
#define SIGPIPE SIGINT
#endif
@@ -54,229 +54,225 @@ char SERVER_TYPE = ATHENA_SERVER_NONE;
#else
sigfunc *compat_signal(int signo, sigfunc *func)
{
- struct sigaction sact, oact;
+ struct sigaction sact, oact;
- sact.sa_handler = func;
- sigemptyset(&sact.sa_mask);
- sact.sa_flags = 0;
+ sact.sa_handler = func;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = 0;
#ifdef SA_INTERRUPT
- sact.sa_flags |= SA_INTERRUPT; /* SunOS */
+ sact.sa_flags |= SA_INTERRUPT; /* SunOS */
#endif
- if (sigaction(signo, &sact, &oact) < 0)
- return (SIG_ERR);
+ if (sigaction(signo, &sact, &oact) < 0)
+ return (SIG_ERR);
- return (oact.sa_handler);
+ return (oact.sa_handler);
}
#endif
/*======================================
- * CORE : Console events for Windows
+ * CORE : Console events for Windows
*--------------------------------------*/
#ifdef _WIN32
static BOOL WINAPI console_handler(DWORD c_event)
{
- switch(c_event)
- {
- case CTRL_CLOSE_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- if( shutdown_callback != NULL )
- shutdown_callback();
- else
- runflag = CORE_ST_STOP;// auto-shutdown
- break;
- default:
- return FALSE;
+ switch (c_event) {
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ if (shutdown_callback != NULL)
+ shutdown_callback();
+ else
+ runflag = CORE_ST_STOP;// auto-shutdown
+ break;
+ default:
+ return FALSE;
}
return TRUE;
}
static void cevents_init()
{
- if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE)
- ShowWarning ("Unable to install the console handler!\n");
+ if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE)
+ ShowWarning("Unable to install the console handler!\n");
}
#endif
/*======================================
- * CORE : Signal Sub Function
+ * CORE : Signal Sub Function
*--------------------------------------*/
static void sig_proc(int sn)
{
- static int is_called = 0;
-
- switch (sn) {
- case SIGINT:
- case SIGTERM:
- if (++is_called > 3)
- exit(EXIT_SUCCESS);
- if( shutdown_callback != NULL )
- shutdown_callback();
- else
- runflag = CORE_ST_STOP;// auto-shutdown
- break;
- case SIGSEGV:
- case SIGFPE:
- do_abort();
- // Pass the signal to the system's default handler
- compat_signal(sn, SIG_DFL);
- raise(sn);
- break;
+ static int is_called = 0;
+
+ switch (sn) {
+ case SIGINT:
+ case SIGTERM:
+ if (++is_called > 3)
+ exit(EXIT_SUCCESS);
+ if (shutdown_callback != NULL)
+ shutdown_callback();
+ else
+ runflag = CORE_ST_STOP;// auto-shutdown
+ break;
+ case SIGSEGV:
+ case SIGFPE:
+ do_abort();
+ // Pass the signal to the system's default handler
+ compat_signal(sn, SIG_DFL);
+ raise(sn);
+ break;
#ifndef _WIN32
- case SIGXFSZ:
- // ignore and allow it to set errno to EFBIG
- ShowWarning ("Max file size reached!\n");
- //run_flag = 0; // should we quit?
- break;
- case SIGPIPE:
- //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c
- break; // does nothing here
+ case SIGXFSZ:
+ // ignore and allow it to set errno to EFBIG
+ ShowWarning("Max file size reached!\n");
+ //run_flag = 0; // should we quit?
+ break;
+ case SIGPIPE:
+ //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c
+ break; // does nothing here
#endif
- }
+ }
}
-void signals_init (void)
+void signals_init(void)
{
- compat_signal(SIGTERM, sig_proc);
- compat_signal(SIGINT, sig_proc);
+ compat_signal(SIGTERM, sig_proc);
+ compat_signal(SIGINT, sig_proc);
#ifndef _DEBUG // need unhandled exceptions to debug on Windows
- compat_signal(SIGSEGV, sig_proc);
- compat_signal(SIGFPE, sig_proc);
+ compat_signal(SIGSEGV, sig_proc);
+ compat_signal(SIGFPE, sig_proc);
#endif
#ifndef _WIN32
- compat_signal(SIGILL, SIG_DFL);
- compat_signal(SIGXFSZ, sig_proc);
- compat_signal(SIGPIPE, sig_proc);
- compat_signal(SIGBUS, SIG_DFL);
- compat_signal(SIGTRAP, SIG_DFL);
+ compat_signal(SIGILL, SIG_DFL);
+ compat_signal(SIGXFSZ, sig_proc);
+ compat_signal(SIGPIPE, sig_proc);
+ compat_signal(SIGBUS, SIG_DFL);
+ compat_signal(SIGTRAP, SIG_DFL);
#endif
}
#endif
#ifdef SVNVERSION
- const char *get_svn_revision(void)
- {
- return EXPAND_AND_QUOTE(SVNVERSION);
- }
+const char *get_svn_revision(void)
+{
+ return EXPAND_AND_QUOTE(SVNVERSION);
+}
#else// not SVNVERSION
-const char* get_svn_revision(void)
+const char *get_svn_revision(void)
{
- static char svn_version_buffer[16] = "";
- FILE *fp;
-
- if( svn_version_buffer[0] != '\0' )
- return svn_version_buffer;
-
- // subversion 1.7 uses a sqlite3 database
- // FIXME this is hackish at best...
- // - ignores database file structure
- // - assumes the data in NODES.dav_cache column ends with "!svn/ver/<revision>/<path>)"
- // - since it's a cache column, the data might not even exist
- if( (fp = fopen(".svn"PATHSEP_STR"wc.db", "rb")) != NULL || (fp = fopen(".."PATHSEP_STR".svn"PATHSEP_STR"wc.db", "rb")) != NULL )
- {
- #ifndef SVNNODEPATH
- //not sure how to handle branches, so i'll leave this overridable define until a better solution comes up
- #define SVNNODEPATH trunk
- #endif
- const char* prefix = "!svn/ver/";
- const char* postfix = "/"EXPAND_AND_QUOTE(SVNNODEPATH)")"; // there should exist only 1 entry like this
- size_t prefix_len = strlen(prefix);
- size_t postfix_len = strlen(postfix);
- size_t i,j,len;
- char* buffer;
-
- // read file to buffer
- fseek(fp, 0, SEEK_END);
- len = ftell(fp);
- buffer = (char*)aMalloc(len + 1);
- fseek(fp, 0, SEEK_SET);
- len = fread(buffer, 1, len, fp);
- buffer[len] = '\0';
- fclose(fp);
-
- // parse buffer
- for( i = prefix_len + 1; i + postfix_len <= len; ++i )
- {
- if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 )
- continue; // postfix missmatch
- for( j = i; j > 0; --j )
- {// skip digits
- if( !ISDIGIT(buffer[j - 1]) )
- break;
- }
- if( memcmp(buffer + j - prefix_len, prefix, prefix_len) != 0 )
- continue; // prefix missmatch
- // done
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(buffer + j));
- break;
- }
- aFree(buffer);
-
- if( svn_version_buffer[0] != '\0' )
- return svn_version_buffer;
- }
-
- // subversion 1.6 and older?
- if ((fp = fopen(".svn/entries", "r")) != NULL)
- {
- char line[1024];
- int rev;
- // Check the version
- if (fgets(line, sizeof(line), fp))
- {
- if(!ISDIGIT(line[0]))
- {
- // XML File format
- while (fgets(line,sizeof(line),fp))
- if (strstr(line,"revision=")) break;
- if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) {
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", rev);
- }
- }
- else
- {
- // Bin File format
- if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get bin name\n"); } // Get the name
- if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get entries kind\n"); } // Get the entries kind
- if(fgets(line, sizeof(line), fp)) // Get the rev numver
- {
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(line));
- }
- }
- }
- fclose(fp);
-
- if( svn_version_buffer[0] != '\0' )
- return svn_version_buffer;
- }
-
- // fallback
- snprintf(svn_version_buffer, sizeof(svn_version_buffer), "Unknown");
- return svn_version_buffer;
+ static char svn_version_buffer[16] = "";
+ FILE *fp;
+
+ if (svn_version_buffer[0] != '\0')
+ return svn_version_buffer;
+
+ // subversion 1.7 uses a sqlite3 database
+ // FIXME this is hackish at best...
+ // - ignores database file structure
+ // - assumes the data in NODES.dav_cache column ends with "!svn/ver/<revision>/<path>)"
+ // - since it's a cache column, the data might not even exist
+ if ((fp = fopen(".svn"PATHSEP_STR"wc.db", "rb")) != NULL || (fp = fopen(".."PATHSEP_STR".svn"PATHSEP_STR"wc.db", "rb")) != NULL) {
+#ifndef SVNNODEPATH
+ //not sure how to handle branches, so i'll leave this overridable define until a better solution comes up
+#define SVNNODEPATH trunk
+#endif
+ const char *prefix = "!svn/ver/";
+ const char *postfix = "/"EXPAND_AND_QUOTE(SVNNODEPATH)")"; // there should exist only 1 entry like this
+ size_t prefix_len = strlen(prefix);
+ size_t postfix_len = strlen(postfix);
+ size_t i,j,len;
+ char *buffer;
+
+ // read file to buffer
+ fseek(fp, 0, SEEK_END);
+ len = ftell(fp);
+ buffer = (char *)aMalloc(len + 1);
+ fseek(fp, 0, SEEK_SET);
+ len = fread(buffer, 1, len, fp);
+ buffer[len] = '\0';
+ fclose(fp);
+
+ // parse buffer
+ for (i = prefix_len + 1; i + postfix_len <= len; ++i) {
+ if (buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0)
+ continue; // postfix missmatch
+ for (j = i; j > 0; --j) {
+ // skip digits
+ if (!ISDIGIT(buffer[j - 1]))
+ break;
+ }
+ if (memcmp(buffer + j - prefix_len, prefix, prefix_len) != 0)
+ continue; // prefix missmatch
+ // done
+ snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(buffer + j));
+ break;
+ }
+ aFree(buffer);
+
+ if (svn_version_buffer[0] != '\0')
+ return svn_version_buffer;
+ }
+
+ // subversion 1.6 and older?
+ if ((fp = fopen(".svn/entries", "r")) != NULL) {
+ char line[1024];
+ int rev;
+ // Check the version
+ if (fgets(line, sizeof(line), fp)) {
+ if (!ISDIGIT(line[0])) {
+ // XML File format
+ while (fgets(line,sizeof(line),fp))
+ if (strstr(line,"revision=")) break;
+ if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) {
+ snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", rev);
+ }
+ } else {
+ // Bin File format
+ if (fgets(line, sizeof(line), fp) == NULL) {
+ printf("Can't get bin name\n"); // Get the name
+ }
+ if (fgets(line, sizeof(line), fp) == NULL) {
+ printf("Can't get entries kind\n"); // Get the entries kind
+ }
+ if (fgets(line, sizeof(line), fp)) { // Get the rev numver
+ snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(line));
+ }
+ }
+ }
+ fclose(fp);
+
+ if (svn_version_buffer[0] != '\0')
+ return svn_version_buffer;
+ }
+
+ // fallback
+ snprintf(svn_version_buffer, sizeof(svn_version_buffer), "Unknown");
+ return svn_version_buffer;
}
#endif
/*======================================
- * CORE : Display title
+ * CORE : Display title
* ASCII By CalciumKid 1/12/2011
*--------------------------------------*/
-static void display_title(void) {
- //ClearScreen(); // clear screen and go up/left (0, 0 position in text)
-
- ShowMessage("\n");
- ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BT_WHITE" rAthena Development Team presents "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" ___ __ __ "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" _____/ | / /_/ /_ ___ ____ ____ _ "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" / ___/ /| |/ __/ __ \\/ _ \\/ __ \\/ __ `/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" / / / ___ / /_/ / / / __/ / / / /_/ / "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" /_/ /_/ |_\\__/_/ /_/\\___/_/ /_/\\__,_/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_GREEN" http://rathena.org/board/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
- ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
-
- ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'.\n", get_svn_revision());
+static void display_title(void)
+{
+ //ClearScreen(); // clear screen and go up/left (0, 0 position in text)
+
+ ShowMessage("\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BT_WHITE" rAthena Development Team presents "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" ___ __ __ "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" _____/ | / /_/ /_ ___ ____ ____ _ "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" / ___/ /| |/ __/ __ \\/ _ \\/ __ \\/ __ `/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" / / / ___ / /_/ / / / __/ / / / /_/ / "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" /_/ /_/ |_\\__/_/ /_/\\___/_/ /_/\\__,_/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_GREEN" http://rathena.org/board/ "CL_PASS""CL_CLL""CL_NORMAL"\n");
+ ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n");
+
+ ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'.\n", get_svn_revision());
}
// Warning if executed as superuser (root)
@@ -284,72 +280,73 @@ void usercheck(void)
{
#ifndef _WIN32
if (geteuid() == 0) {
- ShowWarning ("You are running rAthena with root privileges, it is not necessary.\n");
+ ShowWarning("You are running rAthena with root privileges, it is not necessary.\n");
}
#endif
}
/*======================================
- * CORE : MAINROUTINE
+ * CORE : MAINROUTINE
*--------------------------------------*/
-int main (int argc, char **argv)
+int main(int argc, char **argv)
{
- {// initialize program arguments
- char *p1 = SERVER_NAME = argv[0];
- char *p2 = p1;
- while ((p1 = strchr(p2, '/')) != NULL || (p1 = strchr(p2, '\\')) != NULL)
- {
- SERVER_NAME = ++p1;
- p2 = p1;
- }
- arg_c = argc;
- arg_v = argv;
- }
-
- malloc_init();// needed for Show* in display_title() [FlavioJS]
+ {
+ // initialize program arguments
+ char *p1 = SERVER_NAME = argv[0];
+ char *p2 = p1;
+ while ((p1 = strchr(p2, '/')) != NULL || (p1 = strchr(p2, '\\')) != NULL) {
+ SERVER_NAME = ++p1;
+ p2 = p1;
+ }
+ arg_c = argc;
+ arg_v = argv;
+ }
+
+ malloc_init();// needed for Show* in display_title() [FlavioJS]
#ifdef MINICORE // minimalist Core
- display_title();
- usercheck();
- do_init(argc,argv);
- do_final();
+ display_title();
+ usercheck();
+ do_init(argc,argv);
+ do_final();
#else// not MINICORE
- set_server_type();
- display_title();
- usercheck();
+ set_server_type();
+ display_title();
+ usercheck();
- rathread_init();
- mempool_init();
- db_init();
- signals_init();
+ rathread_init();
+ mempool_init();
+ db_init();
+ signals_init();
#ifdef _WIN32
- cevents_init();
+ cevents_init();
#endif
- timer_init();
- socket_init();
+ timer_init();
+ socket_init();
- do_init(argc,argv);
+ do_init(argc,argv);
- {// Main runtime cycle
- int next;
- while (runflag != CORE_ST_STOP) {
- next = do_timer(gettick_nocache());
- do_sockets(next);
- }
- }
+ {
+ // Main runtime cycle
+ int next;
+ while (runflag != CORE_ST_STOP) {
+ next = do_timer(gettick_nocache());
+ do_sockets(next);
+ }
+ }
- do_final();
+ do_final();
- timer_final();
- socket_final();
- db_final();
- mempool_final();
- rathread_final();
+ timer_final();
+ socket_final();
+ db_final();
+ mempool_final();
+ rathread_final();
#endif
- malloc_final();
+ malloc_final();
- return 0;
+ return 0;
}
diff --git a/src/common/core.h b/src/common/core.h
index d48962c94..d12723445 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -1,14 +1,14 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _CORE_H_
-#define _CORE_H_
+#ifndef _CORE_H_
+#define _CORE_H_
extern int arg_c;
extern char **arg_v;
#if defined(BUILDBOT)
- extern int buildbotflag;
+extern int buildbotflag;
#endif
/// @see E_CORE_ST
@@ -16,28 +16,27 @@ extern int runflag;
extern char *SERVER_NAME;
enum {
- ATHENA_SERVER_NONE = 0, // not defined
- ATHENA_SERVER_LOGIN = 1, // login server
- ATHENA_SERVER_CHAR = 2, // char server
- ATHENA_SERVER_INTER = 4, // inter server
- ATHENA_SERVER_MAP = 8, // map server
+ ATHENA_SERVER_NONE = 0, // not defined
+ ATHENA_SERVER_LOGIN = 1, // login server
+ ATHENA_SERVER_CHAR = 2, // char server
+ ATHENA_SERVER_INTER = 4, // inter server
+ ATHENA_SERVER_MAP = 8, // map server
};
extern char SERVER_TYPE;
-extern int parse_console(const char* buf);
+extern int parse_console(const char *buf);
extern const char *get_svn_revision(void);
-extern int do_init(int,char**);
+extern int do_init(int,char **);
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
+enum E_CORE_ST {
+ CORE_ST_STOP = 0,
+ CORE_ST_RUN,
+ CORE_ST_LAST
};
/// Called when a terminate signal is received. (Ctrl+C pressed)
diff --git a/src/common/db.c b/src/common/db.c
index 204c6d2ea..c5db21a02 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -88,7 +88,7 @@
\*****************************************************************************/
/**
- * If defined statistics about database nodes, database creating/destruction
+ * If defined statistics about database nodes, database creating/destruction
* and function usage are keept and displayed when finalizing the database
* system.
* WARNING: This adds overhead to every database operation (not shure how much).
@@ -112,8 +112,8 @@
* @see struct dbn
*/
typedef enum node_color {
- RED,
- BLACK
+ RED,
+ BLACK
} node_color;
/**
@@ -129,16 +129,16 @@ typedef enum node_color {
* @see DBMap_impl#ht
*/
typedef struct dbn {
- // Tree structure
- struct dbn *parent;
- struct dbn *left;
- struct dbn *right;
- // Node data
- DBKey key;
- DBData data;
- // Other
- node_color color;
- unsigned deleted : 1;
+ // Tree structure
+ struct dbn *parent;
+ struct dbn *left;
+ struct dbn *right;
+ // Node data
+ DBKey key;
+ DBData data;
+ // Other
+ node_color color;
+ unsigned deleted : 1;
} *DBNode;
/**
@@ -149,8 +149,8 @@ typedef struct dbn {
* @see DBMap_impl#free_list
*/
struct db_free {
- DBNode node;
- DBNode *root;
+ DBNode node;
+ DBNode *root;
};
/**
@@ -176,28 +176,28 @@ struct db_free {
* @see #db_alloc(const char*,int,DBType,DBOptions,unsigned short)
*/
typedef struct DBMap_impl {
- // Database interface
- struct DBMap vtable;
- // File and line of allocation
- const char *alloc_file;
- int alloc_line;
- // Lock system
- struct db_free *free_list;
- unsigned int free_count;
- unsigned int free_max;
- unsigned int free_lock;
- // Other
- ERS nodes;
- DBComparator cmp;
- DBHasher hash;
- DBReleaser release;
- DBNode ht[HASH_SIZE];
- DBNode cache;
- DBType type;
- DBOptions options;
- uint32 item_count;
- unsigned short maxlen;
- unsigned global_lock : 1;
+ // Database interface
+ struct DBMap vtable;
+ // File and line of allocation
+ const char *alloc_file;
+ int alloc_line;
+ // Lock system
+ struct db_free *free_list;
+ unsigned int free_count;
+ unsigned int free_max;
+ unsigned int free_lock;
+ // Other
+ ERS nodes;
+ DBComparator cmp;
+ DBHasher hash;
+ DBReleaser release;
+ DBNode ht[HASH_SIZE];
+ DBNode cache;
+ DBType type;
+ DBOptions options;
+ uint32 item_count;
+ unsigned short maxlen;
+ unsigned global_lock : 1;
} DBMap_impl;
/**
@@ -212,11 +212,11 @@ typedef struct DBMap_impl {
* @see #DBNode
*/
typedef struct DBIterator_impl {
- // Iterator interface
- struct DBIterator vtable;
- DBMap_impl* db;
- int ht_index;
- DBNode node;
+ // Iterator interface
+ struct DBIterator vtable;
+ DBMap_impl *db;
+ int ht_index;
+ DBNode node;
} DBIterator_impl;
#if defined(DB_ENABLE_STATS)
@@ -227,92 +227,92 @@ typedef struct DBIterator_impl {
* @see #stats
*/
static struct db_stats {
- // Node alloc/free
- uint32 db_node_alloc;
- uint32 db_node_free;
- // Database creating/destruction counters
- uint32 db_int_alloc;
- uint32 db_uint_alloc;
- uint32 db_string_alloc;
- uint32 db_istring_alloc;
- uint32 db_int_destroy;
- uint32 db_uint_destroy;
- uint32 db_string_destroy;
- uint32 db_istring_destroy;
- // Function usage counters
- uint32 db_rotate_left;
- uint32 db_rotate_right;
- uint32 db_rebalance;
- uint32 db_rebalance_erase;
- uint32 db_is_key_null;
- uint32 db_dup_key;
- uint32 db_dup_key_free;
- uint32 db_free_add;
- uint32 db_free_remove;
- uint32 db_free_lock;
- uint32 db_free_unlock;
- uint32 db_int_cmp;
- uint32 db_uint_cmp;
- uint32 db_string_cmp;
- uint32 db_istring_cmp;
- uint32 db_int_hash;
- uint32 db_uint_hash;
- uint32 db_string_hash;
- uint32 db_istring_hash;
- uint32 db_release_nothing;
- uint32 db_release_key;
- uint32 db_release_data;
- uint32 db_release_both;
- uint32 dbit_first;
- uint32 dbit_last;
- uint32 dbit_next;
- uint32 dbit_prev;
- uint32 dbit_exists;
- uint32 dbit_remove;
- uint32 dbit_destroy;
- uint32 db_iterator;
- uint32 db_exists;
- uint32 db_get;
- uint32 db_getall;
- uint32 db_vgetall;
- uint32 db_ensure;
- uint32 db_vensure;
- uint32 db_put;
- uint32 db_remove;
- uint32 db_foreach;
- uint32 db_vforeach;
- uint32 db_clear;
- uint32 db_vclear;
- uint32 db_destroy;
- uint32 db_vdestroy;
- uint32 db_size;
- uint32 db_type;
- uint32 db_options;
- uint32 db_fix_options;
- uint32 db_default_cmp;
- uint32 db_default_hash;
- uint32 db_default_release;
- uint32 db_custom_release;
- uint32 db_alloc;
- uint32 db_i2key;
- uint32 db_ui2key;
- uint32 db_str2key;
- uint32 db_i2data;
- uint32 db_ui2data;
- uint32 db_ptr2data;
- uint32 db_data2i;
- uint32 db_data2ui;
- uint32 db_data2ptr;
- uint32 db_init;
- uint32 db_final;
+ // Node alloc/free
+ uint32 db_node_alloc;
+ uint32 db_node_free;
+ // Database creating/destruction counters
+ uint32 db_int_alloc;
+ uint32 db_uint_alloc;
+ uint32 db_string_alloc;
+ uint32 db_istring_alloc;
+ uint32 db_int_destroy;
+ uint32 db_uint_destroy;
+ uint32 db_string_destroy;
+ uint32 db_istring_destroy;
+ // Function usage counters
+ uint32 db_rotate_left;
+ uint32 db_rotate_right;
+ uint32 db_rebalance;
+ uint32 db_rebalance_erase;
+ uint32 db_is_key_null;
+ uint32 db_dup_key;
+ uint32 db_dup_key_free;
+ uint32 db_free_add;
+ uint32 db_free_remove;
+ uint32 db_free_lock;
+ uint32 db_free_unlock;
+ uint32 db_int_cmp;
+ uint32 db_uint_cmp;
+ uint32 db_string_cmp;
+ uint32 db_istring_cmp;
+ uint32 db_int_hash;
+ uint32 db_uint_hash;
+ uint32 db_string_hash;
+ uint32 db_istring_hash;
+ uint32 db_release_nothing;
+ uint32 db_release_key;
+ uint32 db_release_data;
+ uint32 db_release_both;
+ uint32 dbit_first;
+ uint32 dbit_last;
+ uint32 dbit_next;
+ uint32 dbit_prev;
+ uint32 dbit_exists;
+ uint32 dbit_remove;
+ uint32 dbit_destroy;
+ uint32 db_iterator;
+ uint32 db_exists;
+ uint32 db_get;
+ uint32 db_getall;
+ uint32 db_vgetall;
+ uint32 db_ensure;
+ uint32 db_vensure;
+ uint32 db_put;
+ uint32 db_remove;
+ uint32 db_foreach;
+ uint32 db_vforeach;
+ uint32 db_clear;
+ uint32 db_vclear;
+ uint32 db_destroy;
+ uint32 db_vdestroy;
+ uint32 db_size;
+ uint32 db_type;
+ uint32 db_options;
+ uint32 db_fix_options;
+ uint32 db_default_cmp;
+ uint32 db_default_hash;
+ uint32 db_default_release;
+ uint32 db_custom_release;
+ uint32 db_alloc;
+ uint32 db_i2key;
+ uint32 db_ui2key;
+ uint32 db_str2key;
+ uint32 db_i2data;
+ uint32 db_ui2data;
+ uint32 db_ptr2data;
+ uint32 db_data2i;
+ uint32 db_data2ui;
+ uint32 db_data2ptr;
+ uint32 db_init;
+ uint32 db_final;
} 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, 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, 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) */
@@ -346,25 +346,25 @@ static struct db_stats {
*/
static void db_rotate_left(DBNode node, DBNode *root)
{
- DBNode y = node->right;
+ DBNode y = node->right;
- DB_COUNTSTAT(db_rotate_left);
- // put the left of y at the right of node
- node->right = y->left;
- if (y->left)
- y->left->parent = node;
- y->parent = node->parent;
- // link y and node's parent
- if (node == *root) {
- *root = y; // node was root
- } else if (node == node->parent->left) {
- node->parent->left = y; // node was at the left
- } else {
- node->parent->right = y; // node was at the right
- }
- // put node at the left of y
- y->left = node;
- node->parent = y;
+ DB_COUNTSTAT(db_rotate_left);
+ // put the left of y at the right of node
+ node->right = y->left;
+ if (y->left)
+ y->left->parent = node;
+ y->parent = node->parent;
+ // link y and node's parent
+ if (node == *root) {
+ *root = y; // node was root
+ } else if (node == node->parent->left) {
+ node->parent->left = y; // node was at the left
+ } else {
+ node->parent->right = y; // node was at the right
+ }
+ // put node at the left of y
+ y->left = node;
+ node->parent = y;
}
/**
@@ -377,25 +377,25 @@ static void db_rotate_left(DBNode node, DBNode *root)
*/
static void db_rotate_right(DBNode node, DBNode *root)
{
- DBNode y = node->left;
+ DBNode y = node->left;
- DB_COUNTSTAT(db_rotate_right);
- // put the right of y at the left of node
- node->left = y->right;
- if (y->right != 0)
- y->right->parent = node;
- y->parent = node->parent;
- // link y and node's parent
- if (node == *root) {
- *root = y; // node was root
- } else if (node == node->parent->right) {
- node->parent->right = y; // node was at the right
- } else {
- node->parent->left = y; // node was at the left
- }
- // put node at the right of y
- y->right = node;
- node->parent = y;
+ DB_COUNTSTAT(db_rotate_right);
+ // put the right of y at the left of node
+ node->left = y->right;
+ if (y->right != 0)
+ y->right->parent = node;
+ y->parent = node->parent;
+ // link y and node's parent
+ if (node == *root) {
+ *root = y; // node was root
+ } else if (node == node->parent->right) {
+ node->parent->right = y; // node was at the right
+ } else {
+ node->parent->left = y; // node was at the left
+ }
+ // put node at the right of y
+ y->right = node;
+ node->parent = y;
}
/**
@@ -410,55 +410,55 @@ static void db_rotate_right(DBNode node, DBNode *root)
*/
static void db_rebalance(DBNode node, DBNode *root)
{
- DBNode y;
-
- DB_COUNTSTAT(db_rebalance);
- // Restore the RED-BLACK properties
- node->color = RED;
- while (node != *root && node->parent->color == RED) {
- if (node->parent == node->parent->parent->left) {
- // If node's parent is a left, y is node's right 'uncle'
- y = node->parent->parent->right;
- if (y && y->color == RED) { // case 1
- // change the colors and move up the tree
- node->parent->color = BLACK;
- y->color = BLACK;
- node->parent->parent->color = RED;
- node = node->parent->parent;
- } else {
- if (node == node->parent->right) { // case 2
- // move up and rotate
- node = node->parent;
- db_rotate_left(node, root);
- }
- // case 3
- node->parent->color = BLACK;
- node->parent->parent->color = RED;
- db_rotate_right(node->parent->parent, root);
- }
- } else {
- // If node's parent is a right, y is node's left 'uncle'
- y = node->parent->parent->left;
- if (y && y->color == RED) { // case 1
- // change the colors and move up the tree
- node->parent->color = BLACK;
- y->color = BLACK;
- node->parent->parent->color = RED;
- node = node->parent->parent;
- } else {
- if (node == node->parent->left) { // case 2
- // move up and rotate
- node = node->parent;
- db_rotate_right(node, root);
- }
- // case 3
- node->parent->color = BLACK;
- node->parent->parent->color = RED;
- db_rotate_left(node->parent->parent, root);
- }
- }
- }
- (*root)->color = BLACK; // the root can and should always be black
+ DBNode y;
+
+ DB_COUNTSTAT(db_rebalance);
+ // Restore the RED-BLACK properties
+ node->color = RED;
+ while (node != *root && node->parent->color == RED) {
+ if (node->parent == node->parent->parent->left) {
+ // If node's parent is a left, y is node's right 'uncle'
+ y = node->parent->parent->right;
+ if (y && y->color == RED) { // case 1
+ // change the colors and move up the tree
+ node->parent->color = BLACK;
+ y->color = BLACK;
+ node->parent->parent->color = RED;
+ node = node->parent->parent;
+ } else {
+ if (node == node->parent->right) { // case 2
+ // move up and rotate
+ node = node->parent;
+ db_rotate_left(node, root);
+ }
+ // case 3
+ node->parent->color = BLACK;
+ node->parent->parent->color = RED;
+ db_rotate_right(node->parent->parent, root);
+ }
+ } else {
+ // If node's parent is a right, y is node's left 'uncle'
+ y = node->parent->parent->left;
+ if (y && y->color == RED) { // case 1
+ // change the colors and move up the tree
+ node->parent->color = BLACK;
+ y->color = BLACK;
+ node->parent->parent->color = RED;
+ node = node->parent->parent;
+ } else {
+ if (node == node->parent->left) { // case 2
+ // move up and rotate
+ node = node->parent;
+ db_rotate_right(node, root);
+ }
+ // case 3
+ node->parent->color = BLACK;
+ node->parent->parent->color = RED;
+ db_rotate_left(node->parent->parent, root);
+ }
+ }
+ }
+ (*root)->color = BLACK; // the root can and should always be black
}
/**
@@ -472,133 +472,133 @@ static void db_rebalance(DBNode node, DBNode *root)
*/
static void db_rebalance_erase(DBNode node, DBNode *root)
{
- DBNode y = node;
- DBNode x = NULL;
- DBNode x_parent = NULL;
- DBNode w;
-
- DB_COUNTSTAT(db_rebalance_erase);
- // Select where to change the tree
- if (y->left == NULL) { // no left
- x = y->right;
- } else if (y->right == NULL) { // no right
- x = y->left;
- } else { // both exist, go to the leftmost node of the right sub-tree
- y = y->right;
- while (y->left != NULL)
- y = y->left;
- x = y->right;
- }
-
- // Remove the node from the tree
- if (y != node) { // both childs existed
- // put the left of 'node' in the left of 'y'
- node->left->parent = y;
- y->left = node->left;
-
- // 'y' is not the direct child of 'node'
- if (y != node->right) {
- // put 'x' in the old position of 'y'
- x_parent = y->parent;
- if (x) x->parent = y->parent;
- y->parent->left = x;
- // put the right of 'node' in 'y'
- y->right = node->right;
- node->right->parent = y;
- // 'y' is a direct child of 'node'
- } else {
- x_parent = y;
- }
-
- // link 'y' and the parent of 'node'
- if (*root == node) {
- *root = y; // 'node' was the root
- } else if (node->parent->left == node) {
- node->parent->left = y; // 'node' was at the left
- } else {
- node->parent->right = y; // 'node' was at the right
- }
- y->parent = node->parent;
- // switch colors
- {
- node_color tmp = y->color;
- y->color = node->color;
- node->color = tmp;
- }
- y = node;
- } else { // one child did not exist
- // put x in node's position
- x_parent = y->parent;
- if (x) x->parent = y->parent;
- // link x and node's parent
- if (*root == node) {
- *root = x; // node was the root
- } else if (node->parent->left == node) {
- node->parent->left = x; // node was at the left
- } else {
- node->parent->right = x; // node was at the right
- }
- }
-
- // Restore the RED-BLACK properties
- if (y->color != RED) {
- while (x != *root && (x == NULL || x->color == BLACK)) {
- if (x == x_parent->left) {
- w = x_parent->right;
- if (w->color == RED) {
- w->color = BLACK;
- x_parent->color = RED;
- db_rotate_left(x_parent, root);
- w = x_parent->right;
- }
- if ((w->left == NULL || w->left->color == BLACK) &&
- (w->right == NULL || w->right->color == BLACK)) {
- w->color = RED;
- x = x_parent;
- x_parent = x_parent->parent;
- } else {
- if (w->right == NULL || w->right->color == BLACK) {
- if (w->left) w->left->color = BLACK;
- w->color = RED;
- db_rotate_right(w, root);
- w = x_parent->right;
- }
- w->color = x_parent->color;
- x_parent->color = BLACK;
- if (w->right) w->right->color = BLACK;
- db_rotate_left(x_parent, root);
- break;
- }
- } else {
- w = x_parent->left;
- if (w->color == RED) {
- w->color = BLACK;
- x_parent->color = RED;
- db_rotate_right(x_parent, root);
- w = x_parent->left;
- }
- if ((w->right == NULL || w->right->color == BLACK) &&
- (w->left == NULL || w->left->color == BLACK)) {
- w->color = RED;
- x = x_parent;
- x_parent = x_parent->parent;
- } else {
- if (w->left == NULL || w->left->color == BLACK) {
- if (w->right) w->right->color = BLACK;
- w->color = RED;
- db_rotate_left(w, root);
- w = x_parent->left;
- }
- w->color = x_parent->color;
- x_parent->color = BLACK;
- if (w->left) w->left->color = BLACK;
- db_rotate_right(x_parent, root);
- break;
- }
- }
- }
- if (x) x->color = BLACK;
- }
+ DBNode y = node;
+ DBNode x = NULL;
+ DBNode x_parent = NULL;
+ DBNode w;
+
+ DB_COUNTSTAT(db_rebalance_erase);
+ // Select where to change the tree
+ if (y->left == NULL) { // no left
+ x = y->right;
+ } else if (y->right == NULL) { // no right
+ x = y->left;
+ } else { // both exist, go to the leftmost node of the right sub-tree
+ y = y->right;
+ while (y->left != NULL)
+ y = y->left;
+ x = y->right;
+ }
+
+ // Remove the node from the tree
+ if (y != node) { // both childs existed
+ // put the left of 'node' in the left of 'y'
+ node->left->parent = y;
+ y->left = node->left;
+
+ // 'y' is not the direct child of 'node'
+ if (y != node->right) {
+ // put 'x' in the old position of 'y'
+ x_parent = y->parent;
+ if (x) x->parent = y->parent;
+ y->parent->left = x;
+ // put the right of 'node' in 'y'
+ y->right = node->right;
+ node->right->parent = y;
+ // 'y' is a direct child of 'node'
+ } else {
+ x_parent = y;
+ }
+
+ // link 'y' and the parent of 'node'
+ if (*root == node) {
+ *root = y; // 'node' was the root
+ } else if (node->parent->left == node) {
+ node->parent->left = y; // 'node' was at the left
+ } else {
+ node->parent->right = y; // 'node' was at the right
+ }
+ y->parent = node->parent;
+ // switch colors
+ {
+ node_color tmp = y->color;
+ y->color = node->color;
+ node->color = tmp;
+ }
+ y = node;
+ } else { // one child did not exist
+ // put x in node's position
+ x_parent = y->parent;
+ if (x) x->parent = y->parent;
+ // link x and node's parent
+ if (*root == node) {
+ *root = x; // node was the root
+ } else if (node->parent->left == node) {
+ node->parent->left = x; // node was at the left
+ } else {
+ node->parent->right = x; // node was at the right
+ }
+ }
+
+ // Restore the RED-BLACK properties
+ if (y->color != RED) {
+ while (x != *root && (x == NULL || x->color == BLACK)) {
+ if (x == x_parent->left) {
+ w = x_parent->right;
+ if (w->color == RED) {
+ w->color = BLACK;
+ x_parent->color = RED;
+ db_rotate_left(x_parent, root);
+ w = x_parent->right;
+ }
+ if ((w->left == NULL || w->left->color == BLACK) &&
+ (w->right == NULL || w->right->color == BLACK)) {
+ w->color = RED;
+ x = x_parent;
+ x_parent = x_parent->parent;
+ } else {
+ if (w->right == NULL || w->right->color == BLACK) {
+ if (w->left) w->left->color = BLACK;
+ w->color = RED;
+ db_rotate_right(w, root);
+ w = x_parent->right;
+ }
+ w->color = x_parent->color;
+ x_parent->color = BLACK;
+ if (w->right) w->right->color = BLACK;
+ db_rotate_left(x_parent, root);
+ break;
+ }
+ } else {
+ w = x_parent->left;
+ if (w->color == RED) {
+ w->color = BLACK;
+ x_parent->color = RED;
+ db_rotate_right(x_parent, root);
+ w = x_parent->left;
+ }
+ if ((w->right == NULL || w->right->color == BLACK) &&
+ (w->left == NULL || w->left->color == BLACK)) {
+ w->color = RED;
+ x = x_parent;
+ x_parent = x_parent->parent;
+ } else {
+ if (w->left == NULL || w->left->color == BLACK) {
+ if (w->right) w->right->color = BLACK;
+ w->color = RED;
+ db_rotate_left(w, root);
+ w = x_parent->left;
+ }
+ w->color = x_parent->color;
+ x_parent->color = BLACK;
+ if (w->left) w->left->color = BLACK;
+ db_rotate_right(x_parent, root);
+ break;
+ }
+ }
+ }
+ if (x) x->color = BLACK;
+ }
}
/**
@@ -613,15 +613,15 @@ static void db_rebalance_erase(DBNode node, DBNode *root)
*/
static int db_is_key_null(DBType type, DBKey key)
{
- DB_COUNTSTAT(db_is_key_null);
- switch (type) {
- case DB_STRING:
- case DB_ISTRING:
- return (key.str == NULL);
+ DB_COUNTSTAT(db_is_key_null);
+ switch (type) {
+ case DB_STRING:
+ case DB_ISTRING:
+ return (key.str == NULL);
- default: // Not a pointer
- return 0;
- }
+ default: // Not a pointer
+ return 0;
+ }
}
/**
@@ -635,25 +635,25 @@ static int db_is_key_null(DBType type, DBKey key)
* @see #db_obj_put(DBMap*,DBKey,void *)
* @see #db_dup_key_free(DBMap_impl*,DBKey)
*/
-static DBKey db_dup_key(DBMap_impl* db, DBKey key)
+static DBKey db_dup_key(DBMap_impl *db, DBKey key)
{
- char *str;
- size_t len;
+ char *str;
+ size_t len;
- DB_COUNTSTAT(db_dup_key);
- switch (db->type) {
- case DB_STRING:
- case DB_ISTRING:
- len = strnlen(key.str, db->maxlen);
- str = (char*)aMalloc(len + 1);
- memcpy(str, key.str, len);
- str[len] = '\0';
- key.str = str;
- return key;
+ DB_COUNTSTAT(db_dup_key);
+ switch (db->type) {
+ case DB_STRING:
+ case DB_ISTRING:
+ 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:
- return key;
- }
+ default:
+ return key;
+ }
}
/**
@@ -663,18 +663,18 @@ static DBKey db_dup_key(DBMap_impl* db, DBKey key)
* @private
* @see #db_dup_key(DBMap_impl*,DBKey)
*/
-static void db_dup_key_free(DBMap_impl* db, DBKey key)
+static void db_dup_key_free(DBMap_impl *db, DBKey key)
{
- DB_COUNTSTAT(db_dup_key_free);
- switch (db->type) {
- case DB_STRING:
- case DB_ISTRING:
- aFree((char*)key.str);
- return;
+ DB_COUNTSTAT(db_dup_key_free);
+ switch (db->type) {
+ case DB_STRING:
+ case DB_ISTRING:
+ aFree((char *)key.str);
+ return;
- default:
- return;
- }
+ default:
+ return;
+ }
}
/**
@@ -692,40 +692,40 @@ static void db_dup_key_free(DBMap_impl* db, DBKey key)
* @see #db_obj_remove(DBMap*,DBKey)
* @see #db_free_remove(DBMap_impl*,DBNode)
*/
-static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root)
-{
- DBKey old_key;
-
- DB_COUNTSTAT(db_free_add);
- if (db->free_lock == (unsigned int)~0) {
- ShowFatalError("db_free_add: free_lock overflow\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- exit(EXIT_FAILURE);
- }
- if (!(db->options&DB_OPT_DUP_KEY)) { // Make sure we have a key until the node is freed
- old_key = node->key;
- node->key = db_dup_key(db, node->key);
- db->release(old_key, node->data, DB_RELEASE_KEY);
- }
- if (db->free_count == db->free_max) { // No more space, expand free_list
- db->free_max = (db->free_max<<2) +3; // = db->free_max*4 +3
- if (db->free_max <= db->free_count) {
- if (db->free_count == (unsigned int)~0) {
- ShowFatalError("db_free_add: free_count overflow\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- exit(EXIT_FAILURE);
- }
- db->free_max = (unsigned int)~0;
- }
- RECREATE(db->free_list, struct db_free, db->free_max);
- }
- node->deleted = 1;
- db->free_list[db->free_count].node = node;
- db->free_list[db->free_count].root = root;
- db->free_count++;
- db->item_count--;
+static void db_free_add(DBMap_impl *db, DBNode node, DBNode *root)
+{
+ DBKey old_key;
+
+ DB_COUNTSTAT(db_free_add);
+ if (db->free_lock == (unsigned int)~0) {
+ ShowFatalError("db_free_add: free_lock overflow\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ exit(EXIT_FAILURE);
+ }
+ if (!(db->options&DB_OPT_DUP_KEY)) { // Make sure we have a key until the node is freed
+ old_key = node->key;
+ node->key = db_dup_key(db, node->key);
+ db->release(old_key, node->data, DB_RELEASE_KEY);
+ }
+ if (db->free_count == db->free_max) { // No more space, expand free_list
+ db->free_max = (db->free_max<<2) +3; // = db->free_max*4 +3
+ if (db->free_max <= db->free_count) {
+ if (db->free_count == (unsigned int)~0) {
+ ShowFatalError("db_free_add: free_count overflow\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ exit(EXIT_FAILURE);
+ }
+ db->free_max = (unsigned int)~0;
+ }
+ RECREATE(db->free_list, struct db_free, db->free_max);
+ }
+ node->deleted = 1;
+ db->free_list[db->free_count].node = node;
+ db->free_list[db->free_count].root = root;
+ db->free_count++;
+ db->item_count--;
}
/**
@@ -741,26 +741,26 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root)
* @see #db_obj_put(DBMap*,DBKey,DBData)
* @see #db_free_add(DBMap_impl*,DBNode*,DBNode)
*/
-static void db_free_remove(DBMap_impl* db, DBNode node)
+static void db_free_remove(DBMap_impl *db, DBNode node)
{
- unsigned int i;
+ unsigned int i;
- DB_COUNTSTAT(db_free_remove);
- for (i = 0; i < db->free_count; i++) {
- if (db->free_list[i].node == node) {
- if (i < db->free_count -1) // copy the last item to where the removed one was
- memcpy(&db->free_list[i], &db->free_list[db->free_count -1], sizeof(struct db_free));
- db_dup_key_free(db, node->key);
- break;
- }
- }
- node->deleted = 0;
- if (i == db->free_count) {
- ShowWarning("db_free_remove: node was not found - database allocated at %s:%d\n", db->alloc_file, db->alloc_line);
- } else {
- db->free_count--;
- }
- db->item_count++;
+ DB_COUNTSTAT(db_free_remove);
+ for (i = 0; i < db->free_count; i++) {
+ if (db->free_list[i].node == node) {
+ if (i < db->free_count -1) // copy the last item to where the removed one was
+ memcpy(&db->free_list[i], &db->free_list[db->free_count -1], sizeof(struct db_free));
+ db_dup_key_free(db, node->key);
+ break;
+ }
+ }
+ node->deleted = 0;
+ if (i == db->free_count) {
+ ShowWarning("db_free_remove: node was not found - database allocated at %s:%d\n", db->alloc_file, db->alloc_line);
+ } else {
+ db->free_count--;
+ }
+ db->item_count++;
}
/**
@@ -770,16 +770,16 @@ static void db_free_remove(DBMap_impl* db, DBNode node)
* @see DBMap_impl#free_lock
* @see #db_unlock(DBMap_impl*)
*/
-static void db_free_lock(DBMap_impl* db)
+static void db_free_lock(DBMap_impl *db)
{
- DB_COUNTSTAT(db_free_lock);
- if (db->free_lock == (unsigned int)~0) {
- ShowFatalError("db_free_lock: free_lock overflow\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- exit(EXIT_FAILURE);
- }
- db->free_lock++;
+ DB_COUNTSTAT(db_free_lock);
+ if (db->free_lock == (unsigned int)~0) {
+ ShowFatalError("db_free_lock: free_lock overflow\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ exit(EXIT_FAILURE);
+ }
+ db->free_lock++;
}
/**
@@ -793,28 +793,28 @@ static void db_free_lock(DBMap_impl* db)
* @see #db_free_dbn(DBNode)
* @see #db_lock(DBMap_impl*)
*/
-static void db_free_unlock(DBMap_impl* db)
+static void db_free_unlock(DBMap_impl *db)
{
- unsigned int i;
+ unsigned int i;
- DB_COUNTSTAT(db_free_unlock);
- if (db->free_lock == 0) {
- ShowWarning("db_free_unlock: free_lock was already 0\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- } else {
- db->free_lock--;
- }
- if (db->free_lock)
- return; // Not last lock
+ DB_COUNTSTAT(db_free_unlock);
+ if (db->free_lock == 0) {
+ ShowWarning("db_free_unlock: free_lock was already 0\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ } else {
+ db->free_lock--;
+ }
+ if (db->free_lock)
+ return; // Not last lock
- for (i = 0; i < db->free_count ; i++) {
- db_rebalance_erase(db->free_list[i].node, db->free_list[i].root);
- db_dup_key_free(db, db->free_list[i].node->key);
- DB_COUNTSTAT(db_node_free);
- ers_free(db->nodes, db->free_list[i].node);
- }
- db->free_count = 0;
+ for (i = 0; i < db->free_count ; i++) {
+ db_rebalance_erase(db->free_list[i].node, db->free_list[i].root);
+ db_dup_key_free(db, db->free_list[i].node->key);
+ DB_COUNTSTAT(db_node_free);
+ ers_free(db->nodes, db->free_list[i].node);
+ }
+ db->free_count = 0;
}
/*****************************************************************************\
@@ -850,11 +850,11 @@ static void db_free_unlock(DBMap_impl* db)
*/
static int db_int_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
{
- (void)maxlen;//not used
- DB_COUNTSTAT(db_int_cmp);
- if (key1.i < key2.i) return -1;
- if (key1.i > key2.i) return 1;
- return 0;
+ (void)maxlen;//not used
+ DB_COUNTSTAT(db_int_cmp);
+ if (key1.i < key2.i) return -1;
+ if (key1.i > key2.i) return 1;
+ return 0;
}
/**
@@ -872,11 +872,11 @@ static int db_int_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
*/
static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
{
- (void)maxlen;//not used
- DB_COUNTSTAT(db_uint_cmp);
- if (key1.ui < key2.ui) return -1;
- if (key1.ui > key2.ui) return 1;
- return 0;
+ (void)maxlen;//not used
+ DB_COUNTSTAT(db_uint_cmp);
+ if (key1.ui < key2.ui) return -1;
+ if (key1.ui > key2.ui) return 1;
+ return 0;
}
/**
@@ -893,8 +893,8 @@ 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);
- return strncmp((const char *)key1.str, (const char *)key2.str, maxlen);
+ DB_COUNTSTAT(db_string_cmp);
+ return strncmp((const char *)key1.str, (const char *)key2.str, maxlen);
}
/**
@@ -911,8 +911,8 @@ 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);
- return strncasecmp((const char *)key1.str, (const char *)key2.str, maxlen);
+ DB_COUNTSTAT(db_istring_cmp);
+ return strncasecmp((const char *)key1.str, (const char *)key2.str, maxlen);
}
/**
@@ -928,9 +928,9 @@ static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
*/
static unsigned int db_int_hash(DBKey key, unsigned short maxlen)
{
- (void)maxlen;//not used
- DB_COUNTSTAT(db_int_hash);
- return (unsigned int)key.i;
+ (void)maxlen;//not used
+ DB_COUNTSTAT(db_int_hash);
+ return (unsigned int)key.i;
}
/**
@@ -946,9 +946,9 @@ static unsigned int db_int_hash(DBKey key, unsigned short maxlen)
*/
static unsigned int db_uint_hash(DBKey key, unsigned short maxlen)
{
- (void)maxlen;//not used
- DB_COUNTSTAT(db_uint_hash);
- return key.ui;
+ (void)maxlen;//not used
+ DB_COUNTSTAT(db_uint_hash);
+ return key.ui;
}
/**
@@ -962,20 +962,20 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen)
*/
static unsigned int db_string_hash(DBKey key, unsigned short maxlen)
{
- const char *k = key.str;
- unsigned int hash = 0;
- unsigned short i;
+ const char *k = key.str;
+ unsigned int hash = 0;
+ unsigned short i;
- DB_COUNTSTAT(db_string_hash);
+ DB_COUNTSTAT(db_string_hash);
- for (i = 0; *k; ++i) {
- hash = (hash*33 + ((unsigned char)*k))^(hash>>24);
- k++;
- if (i == maxlen)
- break;
- }
+ for (i = 0; *k; ++i) {
+ hash = (hash*33 + ((unsigned char)*k))^(hash>>24);
+ k++;
+ if (i == maxlen)
+ break;
+ }
- return hash;
+ return hash;
}
/**
@@ -988,20 +988,20 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen)
*/
static unsigned int db_istring_hash(DBKey key, unsigned short maxlen)
{
- const char *k = key.str;
- unsigned int hash = 0;
- unsigned short i;
+ const char *k = key.str;
+ unsigned int hash = 0;
+ unsigned short i;
- DB_COUNTSTAT(db_istring_hash);
+ DB_COUNTSTAT(db_istring_hash);
- for (i = 0; *k; i++) {
- hash = (hash*33 + ((unsigned char)TOLOWER(*k)))^(hash>>24);
- k++;
- if (i == maxlen)
- break;
- }
+ for (i = 0; *k; i++) {
+ hash = (hash*33 + ((unsigned char)TOLOWER(*k)))^(hash>>24);
+ k++;
+ if (i == maxlen)
+ break;
+ }
- return hash;
+ return hash;
}
/**
@@ -1015,8 +1015,10 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen)
*/
static void db_release_nothing(DBKey key, DBData data, DBRelease which)
{
- (void)key;(void)data;(void)which;//not used
- DB_COUNTSTAT(db_release_nothing);
+ (void)key;
+ (void)data;
+ (void)which;//not used
+ DB_COUNTSTAT(db_release_nothing);
}
/**
@@ -1030,9 +1032,9 @@ static void db_release_nothing(DBKey key, DBData data, DBRelease which)
*/
static void db_release_key(DBKey key, DBData data, DBRelease which)
{
- (void)data;//not used
- DB_COUNTSTAT(db_release_key);
- if (which&DB_RELEASE_KEY) aFree((char*)key.str); // needs to be a pointer
+ (void)data;//not used
+ DB_COUNTSTAT(db_release_key);
+ if (which&DB_RELEASE_KEY) aFree((char *)key.str); // needs to be a pointer
}
/**
@@ -1048,9 +1050,9 @@ static void db_release_key(DBKey key, DBData data, DBRelease which)
*/
static void db_release_data(DBKey key, DBData data, DBRelease which)
{
- (void)key;//not used
- DB_COUNTSTAT(db_release_data);
- if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr);
+ (void)key;//not used
+ DB_COUNTSTAT(db_release_data);
+ if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr);
}
/**
@@ -1067,9 +1069,9 @@ static void db_release_data(DBKey key, DBData data, DBRelease which)
*/
static void db_release_both(DBKey key, DBData data, DBRelease which)
{
- DB_COUNTSTAT(db_release_both);
- if (which&DB_RELEASE_KEY) aFree((char*)key.str); // needs to be a pointer
- if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr);
+ DB_COUNTSTAT(db_release_both);
+ if (which&DB_RELEASE_KEY) aFree((char *)key.str); // needs to be a pointer
+ if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr);
}
/*****************************************************************************\
@@ -1115,16 +1117,16 @@ static void db_release_both(DBKey key, DBData data, DBRelease which)
* @protected
* @see DBIterator#first
*/
-DBData* dbit_obj_first(DBIterator* self, DBKey* out_key)
+DBData *dbit_obj_first(DBIterator *self, DBKey *out_key)
{
- DBIterator_impl* it = (DBIterator_impl*)self;
-
- DB_COUNTSTAT(dbit_first);
- // position before the first entry
- it->ht_index = -1;
- it->node = NULL;
- // get next entry
- return self->next(self, out_key);
+ DBIterator_impl *it = (DBIterator_impl *)self;
+
+ DB_COUNTSTAT(dbit_first);
+ // position before the first entry
+ it->ht_index = -1;
+ it->node = NULL;
+ // get next entry
+ return self->next(self, out_key);
}
/**
@@ -1137,16 +1139,16 @@ DBData* dbit_obj_first(DBIterator* self, DBKey* out_key)
* @protected
* @see DBIterator#last
*/
-DBData* dbit_obj_last(DBIterator* self, DBKey* out_key)
+DBData *dbit_obj_last(DBIterator *self, DBKey *out_key)
{
- DBIterator_impl* it = (DBIterator_impl*)self;
-
- DB_COUNTSTAT(dbit_last);
- // position after the last entry
- it->ht_index = HASH_SIZE;
- it->node = NULL;
- // get previous entry
- return self->prev(self, out_key);
+ DBIterator_impl *it = (DBIterator_impl *)self;
+
+ DB_COUNTSTAT(dbit_last);
+ // position after the last entry
+ it->ht_index = HASH_SIZE;
+ it->node = NULL;
+ // get previous entry
+ return self->prev(self, out_key);
}
/**
@@ -1159,70 +1161,67 @@ DBData* dbit_obj_last(DBIterator* self, DBKey* out_key)
* @protected
* @see DBIterator#next
*/
-DBData* dbit_obj_next(DBIterator* self, DBKey* out_key)
-{
- DBIterator_impl* it = (DBIterator_impl*)self;
- DBNode node;
- DBNode parent;
- struct dbn fake;
-
- DB_COUNTSTAT(dbit_next);
- if( it->ht_index < 0 )
- {// get first node
- it->ht_index = 0;
- it->node = NULL;
- }
- node = it->node;
- memset(&fake, 0, sizeof(fake));
- for( ; it->ht_index < HASH_SIZE; ++(it->ht_index) )
- {
- // Iterate in the order: left tree, current node, right tree
- if( node == NULL )
- {// prepare initial node of this hash
- node = it->db->ht[it->ht_index];
- if( node == NULL )
- continue;// next hash
- fake.right = node;
- node = &fake;
- }
-
- while( node )
- {// next node
- if( node->right )
- {// continue in the right subtree
- node = node->right;
- while( node->left )
- node = node->left;// get leftmost node
- }
- else
- {// continue to the next parent (recursive)
- parent = node->parent;
- while( parent )
- {
- if( parent->right != node )
- break;
- node = parent;
- parent = node->parent;
- }
- if( parent == NULL )
- {// next hash
- node = NULL;
- break;
- }
- node = parent;
- }
-
- if( !node->deleted )
- {// found next entry
- it->node = node;
- if( out_key )
- memcpy(out_key, &node->key, sizeof(DBKey));
- return &node->data;
- }
- }
- }
- it->node = NULL;
- return NULL;// not found
+DBData *dbit_obj_next(DBIterator *self, DBKey *out_key)
+{
+ DBIterator_impl *it = (DBIterator_impl *)self;
+ DBNode node;
+ DBNode parent;
+ struct dbn fake;
+
+ DB_COUNTSTAT(dbit_next);
+ if (it->ht_index < 0) {
+ // get first node
+ it->ht_index = 0;
+ it->node = NULL;
+ }
+ node = it->node;
+ memset(&fake, 0, sizeof(fake));
+ for (; it->ht_index < HASH_SIZE; ++(it->ht_index)) {
+ // Iterate in the order: left tree, current node, right tree
+ if (node == NULL) {
+ // prepare initial node of this hash
+ node = it->db->ht[it->ht_index];
+ if (node == NULL)
+ continue;// next hash
+ fake.right = node;
+ node = &fake;
+ }
+
+ while (node) {
+ // next node
+ if (node->right) {
+ // continue in the right subtree
+ node = node->right;
+ while (node->left)
+ node = node->left;// get leftmost node
+ } else {
+ // continue to the next parent (recursive)
+ parent = node->parent;
+ while (parent) {
+ if (parent->right != node)
+ break;
+ node = parent;
+ parent = node->parent;
+ }
+ if (parent == NULL) {
+ // next hash
+ node = NULL;
+ break;
+ }
+ node = parent;
+ }
+
+ if (!node->deleted) {
+ // found next entry
+ it->node = node;
+ if (out_key)
+ memcpy(out_key, &node->key, sizeof(DBKey));
+ return &node->data;
+ }
+ }
+ }
+ it->node = NULL;
+ return NULL;// not found
}
/**
@@ -1235,93 +1234,90 @@ DBData* dbit_obj_next(DBIterator* self, DBKey* out_key)
* @protected
* @see DBIterator#prev
*/
-DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key)
-{
- DBIterator_impl* it = (DBIterator_impl*)self;
- DBNode node;
- DBNode parent;
- struct dbn fake;
-
- DB_COUNTSTAT(dbit_prev);
- if( it->ht_index >= HASH_SIZE )
- {// get last node
- it->ht_index = HASH_SIZE-1;
- it->node = NULL;
- }
- node = it->node;
- memset(&fake, 0, sizeof(fake));
- for( ; it->ht_index >= 0; --(it->ht_index) )
- {
- // Iterate in the order: right tree, current node, left tree
- if( node == NULL )
- {// prepare initial node of this hash
- node = it->db->ht[it->ht_index];
- if( node == NULL )
- continue;// next hash
- fake.left = node;
- node = &fake;
- }
-
-
- while( node )
- {// next node
- if( node->left )
- {// continue in the left subtree
- node = node->left;
- while( node->right )
- node = node->right;// get rightmost node
- }
- else
- {// continue to the next parent (recursive)
- parent = node->parent;
- while( parent )
- {
- if( parent->left != node )
- break;
- node = parent;
- parent = node->parent;
- }
- if( parent == NULL )
- {// next hash
- node = NULL;
- break;
- }
- node = parent;
- }
-
- if( !node->deleted )
- {// found previous entry
- it->node = node;
- if( out_key )
- memcpy(out_key, &node->key, sizeof(DBKey));
- return &node->data;
- }
- }
- }
- it->node = NULL;
- return NULL;// not found
+DBData *dbit_obj_prev(DBIterator *self, DBKey *out_key)
+{
+ DBIterator_impl *it = (DBIterator_impl *)self;
+ DBNode node;
+ DBNode parent;
+ struct dbn fake;
+
+ DB_COUNTSTAT(dbit_prev);
+ if (it->ht_index >= HASH_SIZE) {
+ // get last node
+ it->ht_index = HASH_SIZE-1;
+ it->node = NULL;
+ }
+ node = it->node;
+ memset(&fake, 0, sizeof(fake));
+ for (; it->ht_index >= 0; --(it->ht_index)) {
+ // Iterate in the order: right tree, current node, left tree
+ if (node == NULL) {
+ // prepare initial node of this hash
+ node = it->db->ht[it->ht_index];
+ if (node == NULL)
+ continue;// next hash
+ fake.left = node;
+ node = &fake;
+ }
+
+
+ while (node) {
+ // next node
+ if (node->left) {
+ // continue in the left subtree
+ node = node->left;
+ while (node->right)
+ node = node->right;// get rightmost node
+ } else {
+ // continue to the next parent (recursive)
+ parent = node->parent;
+ while (parent) {
+ if (parent->left != node)
+ break;
+ node = parent;
+ parent = node->parent;
+ }
+ if (parent == NULL) {
+ // next hash
+ node = NULL;
+ break;
+ }
+ node = parent;
+ }
+
+ if (!node->deleted) {
+ // found previous entry
+ it->node = node;
+ if (out_key)
+ memcpy(out_key, &node->key, sizeof(DBKey));
+ return &node->data;
+ }
+ }
+ }
+ it->node = NULL;
+ return NULL;// not found
}
/**
* Returns true if the fetched entry exists.
- * The databases entries might have NULL data, so use this to to test if
+ * The databases entries might have NULL data, so use this to to test if
* the iterator is done.
* @param self Iterator
* @return true if the entry exists
* @protected
* @see DBIterator#exists
*/
-bool dbit_obj_exists(DBIterator* self)
+bool dbit_obj_exists(DBIterator *self)
{
- DBIterator_impl* it = (DBIterator_impl*)self;
+ DBIterator_impl *it = (DBIterator_impl *)self;
- DB_COUNTSTAT(dbit_exists);
- return (it->node && !it->node->deleted);
+ DB_COUNTSTAT(dbit_exists);
+ return (it->node && !it->node->deleted);
}
/**
* Removes the current entry from the database.
- * NOTE: {@link DBIterator#exists} will return false until another entry
+ * NOTE: {@link DBIterator#exists} will return false until another entry
* is fetched
* Puts data of the removed entry in out_data, if out_data is not NULL.
* @param self Iterator
@@ -1331,26 +1327,25 @@ bool dbit_obj_exists(DBIterator* self)
* @see DBMap#remove
* @see DBIterator#remove
*/
-int dbit_obj_remove(DBIterator* self, DBData *out_data)
+int dbit_obj_remove(DBIterator *self, DBData *out_data)
{
- DBIterator_impl* it = (DBIterator_impl*)self;
- DBNode node;
- int retval = 0;
+ DBIterator_impl *it = (DBIterator_impl *)self;
+ DBNode node;
+ int retval = 0;
- DB_COUNTSTAT(dbit_remove);
- node = it->node;
- if( node && !node->deleted )
- {
- DBMap_impl* db = it->db;
- if( db->cache == node )
- db->cache = NULL;
- if( out_data )
- memcpy(out_data, &node->data, sizeof(DBData));
- retval = 1;
- db->release(node->key, node->data, DB_RELEASE_DATA);
- db_free_add(db, node, &db->ht[it->ht_index]);
- }
- return retval;
+ DB_COUNTSTAT(dbit_remove);
+ node = it->node;
+ if (node && !node->deleted) {
+ DBMap_impl *db = it->db;
+ if (db->cache == node)
+ db->cache = NULL;
+ if (out_data)
+ memcpy(out_data, &node->data, sizeof(DBData));
+ retval = 1;
+ db->release(node->key, node->data, DB_RELEASE_DATA);
+ db_free_add(db, node, &db->ht[it->ht_index]);
+ }
+ return retval;
}
/**
@@ -1358,48 +1353,48 @@ int dbit_obj_remove(DBIterator* self, DBData *out_data)
* @param self Iterator
* @protected
*/
-void dbit_obj_destroy(DBIterator* self)
+void dbit_obj_destroy(DBIterator *self)
{
- DBIterator_impl* it = (DBIterator_impl*)self;
+ DBIterator_impl *it = (DBIterator_impl *)self;
- DB_COUNTSTAT(dbit_destroy);
- // unlock the database
- db_free_unlock(it->db);
- // free iterator
- aFree(self);
+ DB_COUNTSTAT(dbit_destroy);
+ // unlock the database
+ db_free_unlock(it->db);
+ // free iterator
+ aFree(self);
}
/**
* Returns a new iterator for this database.
* The iterator keeps the database locked until it is destroyed.
- * The database will keep functioning normally but will only free internal
+ * The database will keep functioning normally but will only free internal
* memory when unlocked, so destroy the iterator as soon as possible.
* @param self Database
* @return New iterator
* @protected
*/
-static DBIterator* db_obj_iterator(DBMap* self)
+static DBIterator *db_obj_iterator(DBMap *self)
{
- DBMap_impl* db = (DBMap_impl*)self;
- DBIterator_impl* it;
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBIterator_impl *it;
- DB_COUNTSTAT(db_iterator);
- CREATE(it, struct DBIterator_impl, 1);
- /* Interface of the iterator **/
- it->vtable.first = dbit_obj_first;
- it->vtable.last = dbit_obj_last;
- it->vtable.next = dbit_obj_next;
- it->vtable.prev = dbit_obj_prev;
- it->vtable.exists = dbit_obj_exists;
- it->vtable.remove = dbit_obj_remove;
- it->vtable.destroy = dbit_obj_destroy;
- /* Initial state (before the first entry) */
- it->db = db;
- it->ht_index = -1;
- it->node = NULL;
- /* Lock the database */
- db_free_lock(db);
- return &it->vtable;
+ DB_COUNTSTAT(db_iterator);
+ CREATE(it, struct DBIterator_impl, 1);
+ /* Interface of the iterator **/
+ it->vtable.first = dbit_obj_first;
+ it->vtable.last = dbit_obj_last;
+ it->vtable.next = dbit_obj_next;
+ it->vtable.prev = dbit_obj_prev;
+ it->vtable.exists = dbit_obj_exists;
+ it->vtable.remove = dbit_obj_remove;
+ it->vtable.destroy = dbit_obj_destroy;
+ /* Initial state (before the first entry) */
+ it->db = db;
+ it->ht_index = -1;
+ it->node = NULL;
+ /* Lock the database */
+ db_free_lock(db);
+ return &it->vtable;
}
/**
@@ -1410,47 +1405,47 @@ static DBIterator* db_obj_iterator(DBMap* self)
* @protected
* @see DBMap#exists
*/
-static bool db_obj_exists(DBMap* self, DBKey key)
+static bool db_obj_exists(DBMap *self, DBKey key)
{
- DBMap_impl* db = (DBMap_impl*)self;
- DBNode node;
- int c;
- bool found = false;
+ 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
- }
+ 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 (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;
- }
+ 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;
+ 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;
}
/**
@@ -1461,48 +1456,48 @@ static bool db_obj_exists(DBMap* self, DBKey key)
* @protected
* @see DBMap#get
*/
-static DBData* db_obj_get(DBMap* self, DBKey key)
+static DBData *db_obj_get(DBMap *self, DBKey key)
{
- DBMap_impl* db = (DBMap_impl*)self;
- DBNode node;
- int c;
- DBData *data = NULL;
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBNode node;
+ int c;
+ DBData *data = NULL;
- DB_COUNTSTAT(db_get);
- if (db == NULL) return NULL; // nullpo candidate
- if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
- ShowError("db_get: Attempted to retrieve non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return NULL; // nullpo candidate
- }
+ DB_COUNTSTAT(db_get);
+ if (db == NULL) return NULL; // nullpo candidate
+ if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
+ ShowError("db_get: Attempted to retrieve non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return NULL; // nullpo candidate
+ }
- if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) {
+ if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) {
#if defined(DEBUG)
- if (db->cache->deleted) {
- ShowDebug("db_get: Cache contains a deleted node. Please report this!!!\n");
- return NULL;
- }
+ if (db->cache->deleted) {
+ ShowDebug("db_get: Cache contains a deleted node. Please report this!!!\n");
+ return NULL;
+ }
#endif
- return &db->cache->data; // 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)) {
- data = &node->data;
- db->cache = node;
- }
- break;
- }
- if (c < 0)
- node = node->left;
- else
- node = node->right;
- }
- db_free_unlock(db);
- return data;
+ return &db->cache->data; // 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)) {
+ data = &node->data;
+ db->cache = node;
+ }
+ break;
+ }
+ if (c < 0)
+ node = node->left;
+ else
+ node = node->right;
+ }
+ db_free_unlock(db);
+ return data;
}
/**
@@ -1510,7 +1505,7 @@ static DBData* db_obj_get(DBMap* self, DBKey key)
* It puts a maximum of <code>max</code> entries into <code>buf</code>.
* If <code>buf</code> is NULL, it only counts the matches.
* Returns the number of entries that matched.
- * NOTE: if the value returned is greater than <code>max</code>, only the
+ * NOTE: if the value returned is greater than <code>max</code>, only the
* first <code>max</code> entries found are put into the buffer.
* @param self Interface of the database
* @param buf Buffer to put the data of the matched entries
@@ -1521,58 +1516,58 @@ static DBData* db_obj_get(DBMap* self, DBKey key)
* @protected
* @see DBMap#vgetall
*/
-static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, DBMatcher match, va_list args)
-{
- DBMap_impl* db = (DBMap_impl*)self;
- unsigned int i;
- DBNode node;
- DBNode parent;
- unsigned int ret = 0;
-
- DB_COUNTSTAT(db_vgetall);
- if (db == NULL) return 0; // nullpo candidate
- if (match == NULL) return 0; // nullpo candidate
-
- db_free_lock(db);
- for (i = 0; i < HASH_SIZE; i++) {
- // Match in the order: current node, left tree, right tree
- node = db->ht[i];
- while (node) {
-
- if (!(node->deleted)) {
- va_list argscopy;
- va_copy(argscopy, args);
- if (match(node->key, node->data, argscopy) == 0) {
- if (buf && ret < max)
- buf[ret] = &node->data;
- ret++;
- }
- va_end(argscopy);
- }
-
- if (node->left) {
- node = node->left;
- continue;
- }
-
- if (node->right) {
- node = node->right;
- continue;
- }
-
- while (node) {
- parent = node->parent;
- if (parent && parent->right && parent->left == node) {
- node = parent->right;
- break;
- }
- node = parent;
- }
-
- }
- }
- db_free_unlock(db);
- return ret;
+static unsigned int db_obj_vgetall(DBMap *self, DBData **buf, unsigned int max, DBMatcher match, va_list args)
+{
+ DBMap_impl *db = (DBMap_impl *)self;
+ unsigned int i;
+ DBNode node;
+ DBNode parent;
+ unsigned int ret = 0;
+
+ DB_COUNTSTAT(db_vgetall);
+ if (db == NULL) return 0; // nullpo candidate
+ if (match == NULL) return 0; // nullpo candidate
+
+ db_free_lock(db);
+ for (i = 0; i < HASH_SIZE; i++) {
+ // Match in the order: current node, left tree, right tree
+ node = db->ht[i];
+ while (node) {
+
+ if (!(node->deleted)) {
+ va_list argscopy;
+ va_copy(argscopy, args);
+ if (match(node->key, node->data, argscopy) == 0) {
+ if (buf && ret < max)
+ buf[ret] = &node->data;
+ ret++;
+ }
+ va_end(argscopy);
+ }
+
+ if (node->left) {
+ node = node->left;
+ continue;
+ }
+
+ if (node->right) {
+ node = node->right;
+ continue;
+ }
+
+ while (node) {
+ parent = node->parent;
+ if (parent && parent->right && parent->left == node) {
+ node = parent->right;
+ break;
+ }
+ node = parent;
+ }
+
+ }
+ }
+ db_free_unlock(db);
+ return ret;
}
/**
@@ -1581,7 +1576,7 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max,
* It puts a maximum of <code>max</code> entries into <code>buf</code>.
* If <code>buf</code> is NULL, it only counts the matches.
* Returns the number of entries that matched.
- * NOTE: if the value returned is greater than <code>max</code>, only the
+ * NOTE: if the value returned is greater than <code>max</code>, only the
* first <code>max</code> entries found are put into the buffer.
* @param self Interface of the database
* @param buf Buffer to put the data of the matched entries
@@ -1593,23 +1588,23 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max,
* @see DBMap#vgetall
* @see DBMap#getall
*/
-static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, DBMatcher match, ...)
+static unsigned int db_obj_getall(DBMap *self, DBData **buf, unsigned int max, DBMatcher match, ...)
{
- va_list args;
- unsigned int ret;
+ va_list args;
+ unsigned int ret;
- DB_COUNTSTAT(db_getall);
- if (self == NULL) return 0; // nullpo candidate
+ DB_COUNTSTAT(db_getall);
+ if (self == NULL) return 0; // nullpo candidate
- va_start(args, match);
- ret = self->vgetall(self, buf, max, match, args);
- va_end(args);
- return ret;
+ va_start(args, match);
+ ret = self->vgetall(self, buf, max, match, args);
+ va_end(args);
+ return ret;
}
/**
* Get the data of the entry identified by the key.
- * If the entry does not exist, an entry is added with the data returned by
+ * If the entry does not exist, an entry is added with the data returned by
* <code>create</code>.
* @param self Interface of the database
* @param key Key that identifies the entry
@@ -1619,96 +1614,96 @@ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, D
* @protected
* @see DBMap#vensure
*/
-static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list args)
-{
- DBMap_impl* db = (DBMap_impl*)self;
- DBNode node;
- DBNode parent = NULL;
- unsigned int hash;
- int c = 0;
- DBData *data = NULL;
-
- DB_COUNTSTAT(db_vensure);
- if (db == NULL) return NULL; // nullpo candidate
- if (create == NULL) {
- ShowError("db_ensure: Create function is NULL for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return NULL; // nullpo candidate
- }
- if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
- ShowError("db_ensure: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return NULL; // nullpo candidate
- }
-
- if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0)
- return &db->cache->data; // cache hit
-
- db_free_lock(db);
- hash = db->hash(key, db->maxlen)%HASH_SIZE;
- node = db->ht[hash];
- while (node) {
- c = db->cmp(key, node->key, db->maxlen);
- if (c == 0) {
- break;
- }
- parent = node;
- if (c < 0)
- node = node->left;
- else
- node = node->right;
- }
- // Create node if necessary
- if (node == NULL) {
- va_list argscopy;
- if (db->item_count == UINT32_MAX) {
- ShowError("db_vensure: item_count overflow, aborting item insertion.\n"
- "Database allocated at %s:%d",
- db->alloc_file, db->alloc_line);
- return NULL;
- }
- DB_COUNTSTAT(db_node_alloc);
- node = ers_alloc(db->nodes, struct dbn);
- node->left = NULL;
- node->right = NULL;
- node->deleted = 0;
- db->item_count++;
- if (c == 0) { // hash entry is empty
- node->color = BLACK;
- node->parent = NULL;
- db->ht[hash] = node;
- } else {
- node->color = RED;
- if (c < 0) { // put at the left
- parent->left = node;
- node->parent = parent;
- } else { // put at the right
- parent->right = node;
- node->parent = parent;
- }
- if (parent->color == RED) // two consecutive RED nodes, must rebalance
- db_rebalance(node, &db->ht[hash]);
- }
- // put key and data in the node
- if (db->options&DB_OPT_DUP_KEY) {
- node->key = db_dup_key(db, key);
- if (db->options&DB_OPT_RELEASE_KEY)
- db->release(key, *data, DB_RELEASE_KEY);
- } else {
- node->key = key;
- }
- va_copy(argscopy, args);
- node->data = create(key, argscopy);
- va_end(argscopy);
- }
- data = &node->data;
- db->cache = node;
- db_free_unlock(db);
- return data;
+static DBData *db_obj_vensure(DBMap *self, DBKey key, DBCreateData create, va_list args)
+{
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBNode node;
+ DBNode parent = NULL;
+ unsigned int hash;
+ int c = 0;
+ DBData *data = NULL;
+
+ DB_COUNTSTAT(db_vensure);
+ if (db == NULL) return NULL; // nullpo candidate
+ if (create == NULL) {
+ ShowError("db_ensure: Create function is NULL for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return NULL; // nullpo candidate
+ }
+ if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
+ ShowError("db_ensure: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return NULL; // nullpo candidate
+ }
+
+ if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0)
+ return &db->cache->data; // cache hit
+
+ db_free_lock(db);
+ hash = db->hash(key, db->maxlen)%HASH_SIZE;
+ node = db->ht[hash];
+ while (node) {
+ c = db->cmp(key, node->key, db->maxlen);
+ if (c == 0) {
+ break;
+ }
+ parent = node;
+ if (c < 0)
+ node = node->left;
+ else
+ node = node->right;
+ }
+ // Create node if necessary
+ if (node == NULL) {
+ va_list argscopy;
+ if (db->item_count == UINT32_MAX) {
+ ShowError("db_vensure: item_count overflow, aborting item insertion.\n"
+ "Database allocated at %s:%d",
+ db->alloc_file, db->alloc_line);
+ return NULL;
+ }
+ DB_COUNTSTAT(db_node_alloc);
+ node = ers_alloc(db->nodes, struct dbn);
+ node->left = NULL;
+ node->right = NULL;
+ node->deleted = 0;
+ db->item_count++;
+ if (c == 0) { // hash entry is empty
+ node->color = BLACK;
+ node->parent = NULL;
+ db->ht[hash] = node;
+ } else {
+ node->color = RED;
+ if (c < 0) { // put at the left
+ parent->left = node;
+ node->parent = parent;
+ } else { // put at the right
+ parent->right = node;
+ node->parent = parent;
+ }
+ if (parent->color == RED) // two consecutive RED nodes, must rebalance
+ db_rebalance(node, &db->ht[hash]);
+ }
+ // put key and data in the node
+ if (db->options&DB_OPT_DUP_KEY) {
+ node->key = db_dup_key(db, key);
+ if (db->options&DB_OPT_RELEASE_KEY)
+ db->release(key, *data, DB_RELEASE_KEY);
+ } else {
+ node->key = key;
+ }
+ va_copy(argscopy, args);
+ node->data = create(key, argscopy);
+ va_end(argscopy);
+ }
+ data = &node->data;
+ db->cache = node;
+ db_free_unlock(db);
+ return data;
}
/**
* Just calls {@link DBMap#vensure}.
* Get the data of the entry identified by the key.
- * If the entry does not exist, an entry is added with the data returned by
+ * If the entry does not exist, an entry is added with the data returned by
* <code>create</code>.
* @param self Interface of the database
* @param key Key that identifies the entry
@@ -1719,18 +1714,18 @@ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_li
* @see DBMap#vensure
* @see DBMap#ensure
*/
-static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...)
+static DBData *db_obj_ensure(DBMap *self, DBKey key, DBCreateData create, ...)
{
- va_list args;
- DBData *ret = NULL;
+ va_list args;
+ DBData *ret = NULL;
- DB_COUNTSTAT(db_ensure);
- if (self == NULL) return NULL; // nullpo candidate
+ DB_COUNTSTAT(db_ensure);
+ if (self == NULL) return NULL; // nullpo candidate
- va_start(args, create);
- ret = self->vensure(self, key, create, args);
- va_end(args);
- return ret;
+ va_start(args, create);
+ ret = self->vensure(self, key, create, args);
+ va_end(args);
+ return ret;
}
/**
@@ -1746,97 +1741,97 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...)
* @see #db_malloc_dbn(void)
* @see DBMap#put
*/
-static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data)
-{
- DBMap_impl* db = (DBMap_impl*)self;
- DBNode node;
- DBNode parent = NULL;
- int c = 0, retval = 0;
- unsigned int hash;
-
- DB_COUNTSTAT(db_put);
- if (db == NULL) return 0; // nullpo candidate
- if (db->global_lock) {
- ShowError("db_put: Database is being destroyed, aborting entry insertion.\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- return 0; // nullpo candidate
- }
- if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
- ShowError("db_put: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return 0; // nullpo candidate
- }
- if (!(db->options&DB_OPT_ALLOW_NULL_DATA) && (data.type == DB_DATA_PTR && data.u.ptr == NULL)) {
- ShowError("db_put: Attempted to use non-allowed NULL data for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return 0; // nullpo candidate
- }
-
- if (db->item_count == UINT32_MAX) {
- ShowError("db_put: item_count overflow, aborting item insertion.\n"
- "Database allocated at %s:%d",
- db->alloc_file, db->alloc_line);
- return 0;
- }
- // search for an equal node
- db_free_lock(db);
- hash = db->hash(key, db->maxlen)%HASH_SIZE;
- for (node = db->ht[hash]; node; ) {
- c = db->cmp(key, node->key, db->maxlen);
- if (c == 0) { // equal entry, replace
- if (node->deleted) {
- db_free_remove(db, node);
- } else {
- db->release(node->key, node->data, DB_RELEASE_BOTH);
- if (out_data)
- memcpy(out_data, &node->data, sizeof(*out_data));
- retval = 1;
- }
- break;
- }
- parent = node;
- if (c < 0) {
- node = node->left;
- } else {
- node = node->right;
- }
- }
- // allocate a new node if necessary
- if (node == NULL) {
- DB_COUNTSTAT(db_node_alloc);
- node = ers_alloc(db->nodes, struct dbn);
- node->left = NULL;
- node->right = NULL;
- node->deleted = 0;
- db->item_count++;
- if (c == 0) { // hash entry is empty
- node->color = BLACK;
- node->parent = NULL;
- db->ht[hash] = node;
- } else {
- node->color = RED;
- if (c < 0) { // put at the left
- parent->left = node;
- node->parent = parent;
- } else { // put at the right
- parent->right = node;
- node->parent = parent;
- }
- if (parent->color == RED) // two consecutive RED nodes, must rebalance
- db_rebalance(node, &db->ht[hash]);
- }
- }
- // put key and data in the node
- if (db->options&DB_OPT_DUP_KEY) {
- node->key = db_dup_key(db, key);
- if (db->options&DB_OPT_RELEASE_KEY)
- db->release(key, data, DB_RELEASE_KEY);
- } else {
- node->key = key;
- }
- node->data = data;
- db->cache = node;
- db_free_unlock(db);
- return retval;
+static int db_obj_put(DBMap *self, DBKey key, DBData data, DBData *out_data)
+{
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBNode node;
+ DBNode parent = NULL;
+ int c = 0, retval = 0;
+ unsigned int hash;
+
+ DB_COUNTSTAT(db_put);
+ if (db == NULL) return 0; // nullpo candidate
+ if (db->global_lock) {
+ ShowError("db_put: Database is being destroyed, aborting entry insertion.\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ return 0; // nullpo candidate
+ }
+ if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
+ ShowError("db_put: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return 0; // nullpo candidate
+ }
+ if (!(db->options&DB_OPT_ALLOW_NULL_DATA) && (data.type == DB_DATA_PTR && data.u.ptr == NULL)) {
+ ShowError("db_put: Attempted to use non-allowed NULL data for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return 0; // nullpo candidate
+ }
+
+ if (db->item_count == UINT32_MAX) {
+ ShowError("db_put: item_count overflow, aborting item insertion.\n"
+ "Database allocated at %s:%d",
+ db->alloc_file, db->alloc_line);
+ return 0;
+ }
+ // search for an equal node
+ db_free_lock(db);
+ hash = db->hash(key, db->maxlen)%HASH_SIZE;
+ for (node = db->ht[hash]; node;) {
+ c = db->cmp(key, node->key, db->maxlen);
+ if (c == 0) { // equal entry, replace
+ if (node->deleted) {
+ db_free_remove(db, node);
+ } else {
+ db->release(node->key, node->data, DB_RELEASE_BOTH);
+ if (out_data)
+ memcpy(out_data, &node->data, sizeof(*out_data));
+ retval = 1;
+ }
+ break;
+ }
+ parent = node;
+ if (c < 0) {
+ node = node->left;
+ } else {
+ node = node->right;
+ }
+ }
+ // allocate a new node if necessary
+ if (node == NULL) {
+ DB_COUNTSTAT(db_node_alloc);
+ node = ers_alloc(db->nodes, struct dbn);
+ node->left = NULL;
+ node->right = NULL;
+ node->deleted = 0;
+ db->item_count++;
+ if (c == 0) { // hash entry is empty
+ node->color = BLACK;
+ node->parent = NULL;
+ db->ht[hash] = node;
+ } else {
+ node->color = RED;
+ if (c < 0) { // put at the left
+ parent->left = node;
+ node->parent = parent;
+ } else { // put at the right
+ parent->right = node;
+ node->parent = parent;
+ }
+ if (parent->color == RED) // two consecutive RED nodes, must rebalance
+ db_rebalance(node, &db->ht[hash]);
+ }
+ }
+ // put key and data in the node
+ if (db->options&DB_OPT_DUP_KEY) {
+ node->key = db_dup_key(db, key);
+ if (db->options&DB_OPT_RELEASE_KEY)
+ db->release(key, data, DB_RELEASE_KEY);
+ } else {
+ node->key = key;
+ }
+ node->data = data;
+ db->cache = node;
+ db_free_unlock(db);
+ return retval;
}
/**
@@ -1851,49 +1846,49 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data)
* @see #db_free_add(DBMap_impl*,DBNode,DBNode *)
* @see DBMap#remove
*/
-static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data)
-{
- DBMap_impl* db = (DBMap_impl*)self;
- DBNode node;
- unsigned int hash;
- int c = 0, retval = 0;
-
- DB_COUNTSTAT(db_remove);
- if (db == NULL) return 0; // nullpo candidate
- if (db->global_lock) {
- ShowError("db_remove: Database is being destroyed. Aborting entry deletion.\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- return 0; // nullpo candidate
- }
- if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
- ShowError("db_remove: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return 0; // nullpo candidate
- }
-
- db_free_lock(db);
- hash = db->hash(key, db->maxlen)%HASH_SIZE;
- for(node = db->ht[hash]; node; ){
- c = db->cmp(key, node->key, db->maxlen);
- if (c == 0) {
- if (!(node->deleted)) {
- if (db->cache == node)
- db->cache = NULL;
- if (out_data)
- memcpy(out_data, &node->data, sizeof(*out_data));
- retval = 1;
- db->release(node->key, node->data, DB_RELEASE_DATA);
- db_free_add(db, node, &db->ht[hash]);
- }
- break;
- }
- if (c < 0)
- node = node->left;
- else
- node = node->right;
- }
- db_free_unlock(db);
- return retval;
+static int db_obj_remove(DBMap *self, DBKey key, DBData *out_data)
+{
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBNode node;
+ unsigned int hash;
+ int c = 0, retval = 0;
+
+ DB_COUNTSTAT(db_remove);
+ if (db == NULL) return 0; // nullpo candidate
+ if (db->global_lock) {
+ ShowError("db_remove: Database is being destroyed. Aborting entry deletion.\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ return 0; // nullpo candidate
+ }
+ if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
+ ShowError("db_remove: Attempted to use non-allowed NULL key for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return 0; // nullpo candidate
+ }
+
+ db_free_lock(db);
+ hash = db->hash(key, db->maxlen)%HASH_SIZE;
+ for (node = db->ht[hash]; node;) {
+ c = db->cmp(key, node->key, db->maxlen);
+ if (c == 0) {
+ if (!(node->deleted)) {
+ if (db->cache == node)
+ db->cache = NULL;
+ if (out_data)
+ memcpy(out_data, &node->data, sizeof(*out_data));
+ retval = 1;
+ db->release(node->key, node->data, DB_RELEASE_DATA);
+ db_free_add(db, node, &db->ht[hash]);
+ }
+ break;
+ }
+ if (c < 0)
+ node = node->left;
+ else
+ node = node->right;
+ }
+ db_free_unlock(db);
+ return retval;
}
/**
@@ -1906,52 +1901,52 @@ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data)
* @protected
* @see DBMap#vforeach
*/
-static int db_obj_vforeach(DBMap* self, DBApply func, va_list args)
-{
- DBMap_impl* db = (DBMap_impl*)self;
- unsigned int i;
- int sum = 0;
- DBNode node;
- DBNode parent;
-
- DB_COUNTSTAT(db_vforeach);
- if (db == NULL) return 0; // nullpo candidate
- if (func == NULL) {
- ShowError("db_foreach: Passed function is NULL for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
- return 0; // nullpo candidate
- }
-
- db_free_lock(db);
- for (i = 0; i < HASH_SIZE; i++) {
- // Apply func in the order: current node, left node, right node
- node = db->ht[i];
- while (node) {
- if (!(node->deleted)) {
- va_list argscopy;
- va_copy(argscopy, args);
- sum += func(node->key, &node->data, argscopy);
- va_end(argscopy);
- }
- if (node->left) {
- node = node->left;
- continue;
- }
- if (node->right) {
- node = node->right;
- continue;
- }
- while (node) {
- parent = node->parent;
- if (parent && parent->right && parent->left == node) {
- node = parent->right;
- break;
- }
- node = parent;
- }
- }
- }
- db_free_unlock(db);
- return sum;
+static int db_obj_vforeach(DBMap *self, DBApply func, va_list args)
+{
+ DBMap_impl *db = (DBMap_impl *)self;
+ unsigned int i;
+ int sum = 0;
+ DBNode node;
+ DBNode parent;
+
+ DB_COUNTSTAT(db_vforeach);
+ if (db == NULL) return 0; // nullpo candidate
+ if (func == NULL) {
+ ShowError("db_foreach: Passed function is NULL for db allocated at %s:%d\n",db->alloc_file, db->alloc_line);
+ return 0; // nullpo candidate
+ }
+
+ db_free_lock(db);
+ for (i = 0; i < HASH_SIZE; i++) {
+ // Apply func in the order: current node, left node, right node
+ node = db->ht[i];
+ while (node) {
+ if (!(node->deleted)) {
+ va_list argscopy;
+ va_copy(argscopy, args);
+ sum += func(node->key, &node->data, argscopy);
+ va_end(argscopy);
+ }
+ if (node->left) {
+ node = node->left;
+ continue;
+ }
+ if (node->right) {
+ node = node->right;
+ continue;
+ }
+ while (node) {
+ parent = node->parent;
+ if (parent && parent->right && parent->left == node) {
+ node = parent->right;
+ break;
+ }
+ node = parent;
+ }
+ }
+ }
+ db_free_unlock(db);
+ return sum;
}
/**
@@ -1966,18 +1961,18 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args)
* @see DBMap#vforeach
* @see DBMap#foreach
*/
-static int db_obj_foreach(DBMap* self, DBApply func, ...)
+static int db_obj_foreach(DBMap *self, DBApply func, ...)
{
- va_list args;
- int ret;
+ va_list args;
+ int ret;
- DB_COUNTSTAT(db_foreach);
- if (self == NULL) return 0; // nullpo candidate
+ DB_COUNTSTAT(db_foreach);
+ if (self == NULL) return 0; // nullpo candidate
- va_start(args, func);
- ret = self->vforeach(self, func, args);
- va_end(args);
- return ret;
+ va_start(args, func);
+ ret = self->vforeach(self, func, args);
+ va_end(args);
+ return ret;
}
/**
@@ -1992,62 +1987,61 @@ static int db_obj_foreach(DBMap* self, DBApply func, ...)
* @protected
* @see DBMap#vclear
*/
-static int db_obj_vclear(DBMap* self, DBApply func, va_list args)
-{
- DBMap_impl* db = (DBMap_impl*)self;
- int sum = 0;
- unsigned int i;
- DBNode node;
- DBNode parent;
-
- DB_COUNTSTAT(db_vclear);
- if (db == NULL) return 0; // nullpo candidate
-
- db_free_lock(db);
- db->cache = NULL;
- for (i = 0; i < HASH_SIZE; i++) {
- // Apply the func and delete in the order: left tree, right tree, current node
- node = db->ht[i];
- db->ht[i] = NULL;
- while (node) {
- parent = node->parent;
- if (node->left) {
- node = node->left;
- continue;
- }
- if (node->right) {
- node = node->right;
- continue;
- }
- if (node->deleted) {
- db_dup_key_free(db, node->key);
- } else {
- if (func)
- {
- va_list argscopy;
- va_copy(argscopy, args);
- sum += func(node->key, &node->data, argscopy);
- va_end(argscopy);
- }
- db->release(node->key, node->data, DB_RELEASE_BOTH);
- node->deleted = 1;
- }
- DB_COUNTSTAT(db_node_free);
- if (parent) {
- if (parent->left == node)
- parent->left = NULL;
- else
- parent->right = NULL;
- }
- ers_free(db->nodes, node);
- node = parent;
- }
- db->ht[i] = NULL;
- }
- db->free_count = 0;
- db->item_count = 0;
- db_free_unlock(db);
- return sum;
+static int db_obj_vclear(DBMap *self, DBApply func, va_list args)
+{
+ DBMap_impl *db = (DBMap_impl *)self;
+ int sum = 0;
+ unsigned int i;
+ DBNode node;
+ DBNode parent;
+
+ DB_COUNTSTAT(db_vclear);
+ if (db == NULL) return 0; // nullpo candidate
+
+ db_free_lock(db);
+ db->cache = NULL;
+ for (i = 0; i < HASH_SIZE; i++) {
+ // Apply the func and delete in the order: left tree, right tree, current node
+ node = db->ht[i];
+ db->ht[i] = NULL;
+ while (node) {
+ parent = node->parent;
+ if (node->left) {
+ node = node->left;
+ continue;
+ }
+ if (node->right) {
+ node = node->right;
+ continue;
+ }
+ if (node->deleted) {
+ db_dup_key_free(db, node->key);
+ } else {
+ if (func) {
+ va_list argscopy;
+ va_copy(argscopy, args);
+ sum += func(node->key, &node->data, argscopy);
+ va_end(argscopy);
+ }
+ db->release(node->key, node->data, DB_RELEASE_BOTH);
+ node->deleted = 1;
+ }
+ DB_COUNTSTAT(db_node_free);
+ if (parent) {
+ if (parent->left == node)
+ parent->left = NULL;
+ else
+ parent->right = NULL;
+ }
+ ers_free(db->nodes, node);
+ node = parent;
+ }
+ db->ht[i] = NULL;
+ }
+ db->free_count = 0;
+ db->item_count = 0;
+ db_free_unlock(db);
+ return sum;
}
/**
@@ -2056,7 +2050,7 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args)
* Before deleting an entry, func is applied to it.
* Releases the key and the data.
* Returns the sum of values returned by func, if it exists.
- * NOTE: This locks the database globally. Any attempt to insert or remove
+ * NOTE: This locks the database globally. Any attempt to insert or remove
* a database entry will give an error and be aborted (except for clearing).
* @param self Interface of the database
* @param func Function to be applied to every entry before deleting
@@ -2066,25 +2060,25 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args)
* @see DBMap#vclear
* @see DBMap#clear
*/
-static int db_obj_clear(DBMap* self, DBApply func, ...)
+static int db_obj_clear(DBMap *self, DBApply func, ...)
{
- va_list args;
- int ret;
+ va_list args;
+ int ret;
- DB_COUNTSTAT(db_clear);
- if (self == NULL) return 0; // nullpo candidate
+ DB_COUNTSTAT(db_clear);
+ if (self == NULL) return 0; // nullpo candidate
- va_start(args, func);
- ret = self->vclear(self, func, args);
- va_end(args);
- return ret;
+ va_start(args, func);
+ ret = self->vclear(self, func, args);
+ va_end(args);
+ return ret;
}
/**
* Finalize the database, feeing all the memory it uses.
* Before deleting an entry, func is applied to it.
* Returns the sum of values returned by func, if it exists.
- * NOTE: This locks the database globally. Any attempt to insert or remove
+ * NOTE: This locks the database globally. Any attempt to insert or remove
* a database entry will give an error and be aborted (except for clearing).
* @param self Interface of the database
* @param func Function to be applied to every entry before deleting
@@ -2093,42 +2087,50 @@ static int db_obj_clear(DBMap* self, DBApply func, ...)
* @protected
* @see DBMap#vdestroy
*/
-static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args)
+static int db_obj_vdestroy(DBMap *self, DBApply func, va_list args)
{
- DBMap_impl* db = (DBMap_impl*)self;
- int sum;
+ DBMap_impl *db = (DBMap_impl *)self;
+ int sum;
- DB_COUNTSTAT(db_vdestroy);
- if (db == NULL) return 0; // nullpo candidate
- if (db->global_lock) {
- ShowError("db_vdestroy: Database is already locked for destruction. Aborting second database destruction.\n"
- "Database allocated at %s:%d\n",
- db->alloc_file, db->alloc_line);
- return 0;
- }
- if (db->free_lock)
- ShowWarning("db_vdestroy: Database is still in use, %u lock(s) left. Continuing database destruction.\n"
- "Database allocated at %s:%d\n",
- db->free_lock, db->alloc_file, db->alloc_line);
+ DB_COUNTSTAT(db_vdestroy);
+ if (db == NULL) return 0; // nullpo candidate
+ if (db->global_lock) {
+ ShowError("db_vdestroy: Database is already locked for destruction. Aborting second database destruction.\n"
+ "Database allocated at %s:%d\n",
+ db->alloc_file, db->alloc_line);
+ return 0;
+ }
+ if (db->free_lock)
+ ShowWarning("db_vdestroy: Database is still in use, %u lock(s) left. Continuing database destruction.\n"
+ "Database allocated at %s:%d\n",
+ db->free_lock, db->alloc_file, db->alloc_line);
#ifdef DB_ENABLE_STATS
- switch (db->type) {
- case DB_INT: DB_COUNTSTAT(db_int_destroy); break;
- case DB_UINT: DB_COUNTSTAT(db_uint_destroy); break;
- case DB_STRING: DB_COUNTSTAT(db_string_destroy); break;
- case DB_ISTRING: DB_COUNTSTAT(db_istring_destroy); break;
- }
+ switch (db->type) {
+ case DB_INT:
+ DB_COUNTSTAT(db_int_destroy);
+ break;
+ case DB_UINT:
+ DB_COUNTSTAT(db_uint_destroy);
+ break;
+ case DB_STRING:
+ DB_COUNTSTAT(db_string_destroy);
+ break;
+ case DB_ISTRING:
+ DB_COUNTSTAT(db_istring_destroy);
+ break;
+ }
#endif /* DB_ENABLE_STATS */
- db_free_lock(db);
- db->global_lock = 1;
- sum = self->vclear(self, func, args);
- aFree(db->free_list);
- db->free_list = NULL;
- db->free_max = 0;
- ers_destroy(db->nodes);
- db_free_unlock(db);
- aFree(db);
- return sum;
+ db_free_lock(db);
+ db->global_lock = 1;
+ sum = self->vclear(self, func, args);
+ aFree(db->free_list);
+ db->free_list = NULL;
+ db->free_max = 0;
+ ers_destroy(db->nodes);
+ db_free_unlock(db);
+ aFree(db);
+ return sum;
}
/**
@@ -2137,7 +2139,7 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args)
* Before deleting an entry, func is applied to it.
* Releases the key and the data.
* Returns the sum of values returned by func, if it exists.
- * NOTE: This locks the database globally. Any attempt to insert or remove
+ * NOTE: This locks the database globally. Any attempt to insert or remove
* a database entry will give an error and be aborted.
* @param self Database
* @param func Function to be applied to every entry before deleting
@@ -2147,18 +2149,18 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args)
* @see DBMap#vdestroy
* @see DBMap#destroy
*/
-static int db_obj_destroy(DBMap* self, DBApply func, ...)
+static int db_obj_destroy(DBMap *self, DBApply func, ...)
{
- va_list args;
- int ret;
+ va_list args;
+ int ret;
- DB_COUNTSTAT(db_destroy);
- if (self == NULL) return 0; // nullpo candidate
+ DB_COUNTSTAT(db_destroy);
+ if (self == NULL) return 0; // nullpo candidate
- va_start(args, func);
- ret = self->vdestroy(self, func, args);
- va_end(args);
- return ret;
+ va_start(args, func);
+ ret = self->vdestroy(self, func, args);
+ va_end(args);
+ return ret;
}
/**
@@ -2169,19 +2171,19 @@ static int db_obj_destroy(DBMap* self, DBApply func, ...)
* @see DBMap_impl#item_count
* @see DBMap#size
*/
-static unsigned int db_obj_size(DBMap* self)
+static unsigned int db_obj_size(DBMap *self)
{
- DBMap_impl* db = (DBMap_impl*)self;
- unsigned int item_count;
+ DBMap_impl *db = (DBMap_impl *)self;
+ unsigned int item_count;
- DB_COUNTSTAT(db_size);
- if (db == NULL) return 0; // nullpo candidate
+ DB_COUNTSTAT(db_size);
+ if (db == NULL) return 0; // nullpo candidate
- db_free_lock(db);
- item_count = db->item_count;
- db_free_unlock(db);
+ db_free_lock(db);
+ item_count = db->item_count;
+ db_free_unlock(db);
- return item_count;
+ return item_count;
}
/**
@@ -2192,19 +2194,19 @@ static unsigned int db_obj_size(DBMap* self)
* @see DBMap_impl#type
* @see DBMap#type
*/
-static DBType db_obj_type(DBMap* self)
+static DBType db_obj_type(DBMap *self)
{
- DBMap_impl* db = (DBMap_impl*)self;
- DBType type;
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBType type;
- DB_COUNTSTAT(db_type);
- if (db == NULL) return (DBType)-1; // nullpo candidate - TODO what should this return?
+ DB_COUNTSTAT(db_type);
+ if (db == NULL) return (DBType)-1; // nullpo candidate - TODO what should this return?
- db_free_lock(db);
- type = db->type;
- db_free_unlock(db);
+ db_free_lock(db);
+ type = db->type;
+ db_free_unlock(db);
- return type;
+ return type;
}
/**
@@ -2215,19 +2217,19 @@ static DBType db_obj_type(DBMap* self)
* @see DBMap_impl#options
* @see DBMap#options
*/
-static DBOptions db_obj_options(DBMap* self)
+static DBOptions db_obj_options(DBMap *self)
{
- DBMap_impl* db = (DBMap_impl*)self;
- DBOptions options;
+ DBMap_impl *db = (DBMap_impl *)self;
+ DBOptions options;
- DB_COUNTSTAT(db_options);
- if (db == NULL) return DB_OPT_BASE; // nullpo candidate - TODO what should this return?
+ DB_COUNTSTAT(db_options);
+ if (db == NULL) return DB_OPT_BASE; // nullpo candidate - TODO what should this return?
- db_free_lock(db);
- options = db->options;
- db_free_unlock(db);
+ db_free_lock(db);
+ options = db->options;
+ db_free_unlock(db);
- return options;
+ return options;
}
/*****************************************************************************\
@@ -2264,18 +2266,18 @@ static DBOptions db_obj_options(DBMap* self)
*/
DBOptions db_fix_options(DBType type, DBOptions options)
{
- DB_COUNTSTAT(db_fix_options);
- switch (type) {
- case DB_INT:
- case DB_UINT: // Numeric database, do nothing with the keys
- return (DBOptions)(options&~(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY));
+ DB_COUNTSTAT(db_fix_options);
+ switch (type) {
+ case DB_INT:
+ case DB_UINT: // Numeric database, do nothing with the keys
+ return (DBOptions)(options&~(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY));
- default:
- ShowError("db_fix_options: Unknown database type %u with options %x\n", type, options);
- case DB_STRING:
- case DB_ISTRING: // String databases, no fix required
- return options;
- }
+ default:
+ ShowError("db_fix_options: Unknown database type %u with options %x\n", type, options);
+ case DB_STRING:
+ case DB_ISTRING: // String databases, no fix required
+ return options;
+ }
}
/**
@@ -2290,16 +2292,20 @@ DBOptions db_fix_options(DBType type, DBOptions options)
*/
DBComparator db_default_cmp(DBType type)
{
- DB_COUNTSTAT(db_default_cmp);
- switch (type) {
- case DB_INT: return &db_int_cmp;
- case DB_UINT: return &db_uint_cmp;
- case DB_STRING: return &db_string_cmp;
- case DB_ISTRING: return &db_istring_cmp;
- default:
- ShowError("db_default_cmp: Unknown database type %u\n", type);
- return NULL;
- }
+ DB_COUNTSTAT(db_default_cmp);
+ switch (type) {
+ case DB_INT:
+ return &db_int_cmp;
+ case DB_UINT:
+ return &db_uint_cmp;
+ case DB_STRING:
+ return &db_string_cmp;
+ case DB_ISTRING:
+ return &db_istring_cmp;
+ default:
+ ShowError("db_default_cmp: Unknown database type %u\n", type);
+ return NULL;
+ }
}
/**
@@ -2314,20 +2320,24 @@ DBComparator db_default_cmp(DBType type)
*/
DBHasher db_default_hash(DBType type)
{
- DB_COUNTSTAT(db_default_hash);
- switch (type) {
- case DB_INT: return &db_int_hash;
- case DB_UINT: return &db_uint_hash;
- case DB_STRING: return &db_string_hash;
- case DB_ISTRING: return &db_istring_hash;
- default:
- ShowError("db_default_hash: Unknown database type %u\n", type);
- return NULL;
- }
+ DB_COUNTSTAT(db_default_hash);
+ switch (type) {
+ case DB_INT:
+ return &db_int_hash;
+ case DB_UINT:
+ return &db_uint_hash;
+ case DB_STRING:
+ return &db_string_hash;
+ case DB_ISTRING:
+ return &db_istring_hash;
+ default:
+ ShowError("db_default_hash: Unknown database type %u\n", type);
+ return NULL;
+ }
}
/**
- * Returns the default releaser for the specified type of database with the
+ * Returns the default releaser for the specified type of database with the
* specified options.
* NOTE: the options are fixed with {@link #db_fix_options(DBType,DBOptions)}
* before choosing the releaser.
@@ -2343,16 +2353,16 @@ DBHasher db_default_hash(DBType type)
*/
DBReleaser db_default_release(DBType type, DBOptions options)
{
- DB_COUNTSTAT(db_default_release);
- options = db_fix_options(type, options);
- if (options&DB_OPT_RELEASE_DATA) { // Release data, what about the key?
- if (options&(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY))
- return &db_release_both; // Release both key and data
- return &db_release_data; // Only release data
- }
- if (options&(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY))
- return &db_release_key; // Only release key
- return &db_release_nothing; // Release nothing
+ DB_COUNTSTAT(db_default_release);
+ options = db_fix_options(type, options);
+ if (options&DB_OPT_RELEASE_DATA) { // Release data, what about the key?
+ if (options&(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY))
+ return &db_release_both; // Release both key and data
+ return &db_release_data; // Only release data
+ }
+ if (options&(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY))
+ return &db_release_key; // Only release key
+ return &db_release_nothing; // Release nothing
}
/**
@@ -2368,16 +2378,20 @@ DBReleaser db_default_release(DBType type, DBOptions options)
*/
DBReleaser db_custom_release(DBRelease which)
{
- DB_COUNTSTAT(db_custom_release);
- switch (which) {
- case DB_RELEASE_NOTHING: return &db_release_nothing;
- case DB_RELEASE_KEY: return &db_release_key;
- case DB_RELEASE_DATA: return &db_release_data;
- case DB_RELEASE_BOTH: return &db_release_both;
- default:
- ShowError("db_custom_release: Unknown release options %u\n", which);
- return NULL;
- }
+ DB_COUNTSTAT(db_custom_release);
+ switch (which) {
+ case DB_RELEASE_NOTHING:
+ return &db_release_nothing;
+ case DB_RELEASE_KEY:
+ return &db_release_key;
+ case DB_RELEASE_DATA:
+ return &db_release_data;
+ case DB_RELEASE_BOTH:
+ return &db_release_both;
+ default:
+ ShowError("db_custom_release: Unknown release options %u\n", which);
+ return NULL;
+ }
}
/**
@@ -2388,75 +2402,83 @@ DBReleaser db_custom_release(DBRelease which)
* @param line Line of the file where the database is being allocated
* @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
+ * @param maxlen Maximum length of the string to be used as key in string
* databases. If 0, the maximum number of maxlen is used (64K).
* @return The interface of the database
* @public
* @see #DBMap_impl
* @see #db_fix_options(DBType,DBOptions)
*/
-DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen)
+DBMap *db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen)
{
- DBMap_impl* db;
- unsigned int i;
+ DBMap_impl *db;
+ unsigned int i;
#ifdef DB_ENABLE_STATS
- DB_COUNTSTAT(db_alloc);
- switch (type) {
- case DB_INT: DB_COUNTSTAT(db_int_alloc); break;
- case DB_UINT: DB_COUNTSTAT(db_uint_alloc); break;
- case DB_STRING: DB_COUNTSTAT(db_string_alloc); break;
- case DB_ISTRING: DB_COUNTSTAT(db_istring_alloc); break;
- }
+ DB_COUNTSTAT(db_alloc);
+ switch (type) {
+ case DB_INT:
+ DB_COUNTSTAT(db_int_alloc);
+ break;
+ case DB_UINT:
+ DB_COUNTSTAT(db_uint_alloc);
+ break;
+ case DB_STRING:
+ DB_COUNTSTAT(db_string_alloc);
+ break;
+ case DB_ISTRING:
+ DB_COUNTSTAT(db_istring_alloc);
+ break;
+ }
#endif /* DB_ENABLE_STATS */
- CREATE(db, struct DBMap_impl, 1);
-
- 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;
- db->vtable.ensure = db_obj_ensure;
- db->vtable.vensure = db_obj_vensure;
- db->vtable.put = db_obj_put;
- db->vtable.remove = db_obj_remove;
- db->vtable.foreach = db_obj_foreach;
- db->vtable.vforeach = db_obj_vforeach;
- db->vtable.clear = db_obj_clear;
- db->vtable.vclear = db_obj_vclear;
- db->vtable.destroy = db_obj_destroy;
- db->vtable.vdestroy = db_obj_vdestroy;
- db->vtable.size = db_obj_size;
- db->vtable.type = db_obj_type;
- db->vtable.options = db_obj_options;
- /* File and line of allocation */
- db->alloc_file = file;
- db->alloc_line = line;
- /* Lock system */
- db->free_list = NULL;
- db->free_count = 0;
- db->free_max = 0;
- db->free_lock = 0;
- /* Other */
- db->nodes = ers_new(sizeof(struct dbn),"db.c::db_alloc",ERS_OPT_NONE);
- db->cmp = db_default_cmp(type);
- db->hash = db_default_hash(type);
- db->release = db_default_release(type, options);
- for (i = 0; i < HASH_SIZE; i++)
- db->ht[i] = NULL;
- db->cache = NULL;
- db->type = type;
- db->options = options;
- db->item_count = 0;
- db->maxlen = maxlen;
- db->global_lock = 0;
-
- if( db->maxlen == 0 && (type == DB_STRING || type == DB_ISTRING) )
- db->maxlen = UINT16_MAX;
-
- return &db->vtable;
+ CREATE(db, struct DBMap_impl, 1);
+
+ 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;
+ db->vtable.ensure = db_obj_ensure;
+ db->vtable.vensure = db_obj_vensure;
+ db->vtable.put = db_obj_put;
+ db->vtable.remove = db_obj_remove;
+ db->vtable.foreach = db_obj_foreach;
+ db->vtable.vforeach = db_obj_vforeach;
+ db->vtable.clear = db_obj_clear;
+ db->vtable.vclear = db_obj_vclear;
+ db->vtable.destroy = db_obj_destroy;
+ db->vtable.vdestroy = db_obj_vdestroy;
+ db->vtable.size = db_obj_size;
+ db->vtable.type = db_obj_type;
+ db->vtable.options = db_obj_options;
+ /* File and line of allocation */
+ db->alloc_file = file;
+ db->alloc_line = line;
+ /* Lock system */
+ db->free_list = NULL;
+ db->free_count = 0;
+ db->free_max = 0;
+ db->free_lock = 0;
+ /* Other */
+ db->nodes = ers_new(sizeof(struct dbn),"db.c::db_alloc",ERS_OPT_NONE);
+ db->cmp = db_default_cmp(type);
+ db->hash = db_default_hash(type);
+ db->release = db_default_release(type, options);
+ for (i = 0; i < HASH_SIZE; i++)
+ db->ht[i] = NULL;
+ db->cache = NULL;
+ db->type = type;
+ db->options = options;
+ db->item_count = 0;
+ db->maxlen = maxlen;
+ db->global_lock = 0;
+
+ if (db->maxlen == 0 && (type == DB_STRING || type == DB_ISTRING))
+ db->maxlen = UINT16_MAX;
+
+ return &db->vtable;
}
/**
@@ -2467,11 +2489,11 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
*/
DBKey db_i2key(int key)
{
- DBKey ret;
+ DBKey ret;
- DB_COUNTSTAT(db_i2key);
- ret.i = key;
- return ret;
+ DB_COUNTSTAT(db_i2key);
+ ret.i = key;
+ return ret;
}
/**
@@ -2482,11 +2504,11 @@ DBKey db_i2key(int key)
*/
DBKey db_ui2key(unsigned int key)
{
- DBKey ret;
+ DBKey ret;
- DB_COUNTSTAT(db_ui2key);
- ret.ui = key;
- return ret;
+ DB_COUNTSTAT(db_ui2key);
+ ret.ui = key;
+ return ret;
}
/**
@@ -2497,11 +2519,11 @@ DBKey db_ui2key(unsigned int key)
*/
DBKey db_str2key(const char *key)
{
- DBKey ret;
+ DBKey ret;
- DB_COUNTSTAT(db_str2key);
- ret.str = key;
- return ret;
+ DB_COUNTSTAT(db_str2key);
+ ret.str = key;
+ return ret;
}
/**
@@ -2512,12 +2534,12 @@ DBKey db_str2key(const char *key)
*/
DBData db_i2data(int data)
{
- DBData ret;
+ DBData ret;
- DB_COUNTSTAT(db_i2data);
- ret.type = DB_DATA_INT;
- ret.u.i = data;
- return ret;
+ DB_COUNTSTAT(db_i2data);
+ ret.type = DB_DATA_INT;
+ ret.u.i = data;
+ return ret;
}
/**
@@ -2528,12 +2550,12 @@ DBData db_i2data(int data)
*/
DBData db_ui2data(unsigned int data)
{
- DBData ret;
+ DBData ret;
- DB_COUNTSTAT(db_ui2data);
- ret.type = DB_DATA_UINT;
- ret.u.ui = data;
- return ret;
+ DB_COUNTSTAT(db_ui2data);
+ ret.type = DB_DATA_UINT;
+ ret.u.ui = data;
+ return ret;
}
/**
@@ -2544,12 +2566,12 @@ DBData db_ui2data(unsigned int data)
*/
DBData db_ptr2data(void *data)
{
- DBData ret;
+ DBData ret;
- DB_COUNTSTAT(db_ptr2data);
- ret.type = DB_DATA_PTR;
- ret.u.ptr = data;
- return ret;
+ DB_COUNTSTAT(db_ptr2data);
+ ret.type = DB_DATA_PTR;
+ ret.u.ptr = data;
+ return ret;
}
/**
@@ -2561,10 +2583,10 @@ DBData db_ptr2data(void *data)
*/
int db_data2i(DBData *data)
{
- DB_COUNTSTAT(db_data2i);
- if (data && DB_DATA_INT == data->type)
- return data->u.i;
- return 0;
+ DB_COUNTSTAT(db_data2i);
+ if (data && DB_DATA_INT == data->type)
+ return data->u.i;
+ return 0;
}
/**
@@ -2576,10 +2598,10 @@ int db_data2i(DBData *data)
*/
unsigned int db_data2ui(DBData *data)
{
- DB_COUNTSTAT(db_data2ui);
- if (data && DB_DATA_UINT == data->type)
- return data->u.ui;
- return 0;
+ DB_COUNTSTAT(db_data2ui);
+ if (data && DB_DATA_UINT == data->type)
+ return data->u.ui;
+ return 0;
}
/**
@@ -2589,12 +2611,12 @@ unsigned int db_data2ui(DBData *data)
* @return Void* value of the data.
* @public
*/
-void* db_data2ptr(DBData *data)
+void *db_data2ptr(DBData *data)
{
- DB_COUNTSTAT(db_data2ptr);
- if (data && DB_DATA_PTR == data->type)
- return data->u.ptr;
- return NULL;
+ DB_COUNTSTAT(db_data2ptr);
+ if (data && DB_DATA_PTR == data->type)
+ return data->u.ptr;
+ return NULL;
}
/**
@@ -2604,7 +2626,7 @@ void* db_data2ptr(DBData *data)
*/
void db_init(void)
{
- DB_COUNTSTAT(db_init);
+ DB_COUNTSTAT(db_init);
}
/**
@@ -2615,208 +2637,208 @@ void db_init(void)
void db_final(void)
{
#ifdef DB_ENABLE_STATS
- DB_COUNTSTAT(db_final);
- ShowInfo(CL_WHITE"Database nodes"CL_RESET":\n"
- "allocated %u, freed %u\n",
- stats.db_node_alloc, stats.db_node_free);
- ShowInfo(CL_WHITE"Database types"CL_RESET":\n"
- "DB_INT : allocated %10u, destroyed %10u\n"
- "DB_UINT : allocated %10u, destroyed %10u\n"
- "DB_STRING : allocated %10u, destroyed %10u\n"
- "DB_ISTRING : allocated %10u, destroyed %10u\n",
- stats.db_int_alloc, stats.db_int_destroy,
- stats.db_uint_alloc, stats.db_uint_destroy,
- stats.db_string_alloc, stats.db_string_destroy,
- stats.db_istring_alloc, stats.db_istring_destroy);
- ShowInfo(CL_WHITE"Database function counters"CL_RESET":\n"
- "db_rotate_left %10u, db_rotate_right %10u,\n"
- "db_rebalance %10u, db_rebalance_erase %10u,\n"
- "db_is_key_null %10u,\n"
- "db_dup_key %10u, db_dup_key_free %10u,\n"
- "db_free_add %10u, db_free_remove %10u,\n"
- "db_free_lock %10u, db_free_unlock %10u,\n"
- "db_int_cmp %10u, db_uint_cmp %10u,\n"
- "db_string_cmp %10u, db_istring_cmp %10u,\n"
- "db_int_hash %10u, db_uint_hash %10u,\n"
- "db_string_hash %10u, db_istring_hash %10u,\n"
- "db_release_nothing %10u, db_release_key %10u,\n"
- "db_release_data %10u, db_release_both %10u,\n"
- "dbit_first %10u, dbit_last %10u,\n"
- "dbit_next %10u, dbit_prev %10u,\n"
- "dbit_exists %10u, dbit_remove %10u,\n"
- "dbit_destroy %10u, db_iterator %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"
- "db_foreach %10u, db_vforeach %10u,\n"
- "db_clear %10u, db_vclear %10u,\n"
- "db_destroy %10u, db_vdestroy %10u,\n"
- "db_size %10u, db_type %10u,\n"
- "db_options %10u, db_fix_options %10u,\n"
- "db_default_cmp %10u, db_default_hash %10u,\n"
- "db_default_release %10u, db_custom_release %10u,\n"
- "db_alloc %10u, db_i2key %10u,\n"
- "db_ui2key %10u, db_str2key %10u,\n"
- "db_i2data %10u, db_ui2data %10u,\n"
- "db_ptr2data %10u, db_data2i %10u,\n"
- "db_data2ui %10u, db_data2ptr %10u,\n"
- "db_init %10u, db_final %10u\n",
- stats.db_rotate_left, stats.db_rotate_right,
- stats.db_rebalance, stats.db_rebalance_erase,
- stats.db_is_key_null,
- stats.db_dup_key, stats.db_dup_key_free,
- stats.db_free_add, stats.db_free_remove,
- stats.db_free_lock, stats.db_free_unlock,
- stats.db_int_cmp, stats.db_uint_cmp,
- stats.db_string_cmp, stats.db_istring_cmp,
- stats.db_int_hash, stats.db_uint_hash,
- stats.db_string_hash, stats.db_istring_hash,
- stats.db_release_nothing, stats.db_release_key,
- stats.db_release_data, stats.db_release_both,
- stats.dbit_first, stats.dbit_last,
- stats.dbit_next, stats.dbit_prev,
- stats.dbit_exists, stats.dbit_remove,
- stats.dbit_destroy, stats.db_iterator,
- stats.db_exists, stats.db_get,
- stats.db_getall, stats.db_vgetall,
- stats.db_ensure, stats.db_vensure,
- stats.db_put, stats.db_remove,
- stats.db_foreach, stats.db_vforeach,
- stats.db_clear, stats.db_vclear,
- stats.db_destroy, stats.db_vdestroy,
- stats.db_size, stats.db_type,
- stats.db_options, stats.db_fix_options,
- stats.db_default_cmp, stats.db_default_hash,
- stats.db_default_release, stats.db_custom_release,
- stats.db_alloc, stats.db_i2key,
- stats.db_ui2key, stats.db_str2key,
- stats.db_i2data, stats.db_ui2data,
- stats.db_ptr2data, stats.db_data2i,
- stats.db_data2ui, stats.db_data2ptr,
- stats.db_init, stats.db_final);
+ DB_COUNTSTAT(db_final);
+ ShowInfo(CL_WHITE"Database nodes"CL_RESET":\n"
+ "allocated %u, freed %u\n",
+ stats.db_node_alloc, stats.db_node_free);
+ ShowInfo(CL_WHITE"Database types"CL_RESET":\n"
+ "DB_INT : allocated %10u, destroyed %10u\n"
+ "DB_UINT : allocated %10u, destroyed %10u\n"
+ "DB_STRING : allocated %10u, destroyed %10u\n"
+ "DB_ISTRING : allocated %10u, destroyed %10u\n",
+ stats.db_int_alloc, stats.db_int_destroy,
+ stats.db_uint_alloc, stats.db_uint_destroy,
+ stats.db_string_alloc, stats.db_string_destroy,
+ stats.db_istring_alloc, stats.db_istring_destroy);
+ ShowInfo(CL_WHITE"Database function counters"CL_RESET":\n"
+ "db_rotate_left %10u, db_rotate_right %10u,\n"
+ "db_rebalance %10u, db_rebalance_erase %10u,\n"
+ "db_is_key_null %10u,\n"
+ "db_dup_key %10u, db_dup_key_free %10u,\n"
+ "db_free_add %10u, db_free_remove %10u,\n"
+ "db_free_lock %10u, db_free_unlock %10u,\n"
+ "db_int_cmp %10u, db_uint_cmp %10u,\n"
+ "db_string_cmp %10u, db_istring_cmp %10u,\n"
+ "db_int_hash %10u, db_uint_hash %10u,\n"
+ "db_string_hash %10u, db_istring_hash %10u,\n"
+ "db_release_nothing %10u, db_release_key %10u,\n"
+ "db_release_data %10u, db_release_both %10u,\n"
+ "dbit_first %10u, dbit_last %10u,\n"
+ "dbit_next %10u, dbit_prev %10u,\n"
+ "dbit_exists %10u, dbit_remove %10u,\n"
+ "dbit_destroy %10u, db_iterator %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"
+ "db_foreach %10u, db_vforeach %10u,\n"
+ "db_clear %10u, db_vclear %10u,\n"
+ "db_destroy %10u, db_vdestroy %10u,\n"
+ "db_size %10u, db_type %10u,\n"
+ "db_options %10u, db_fix_options %10u,\n"
+ "db_default_cmp %10u, db_default_hash %10u,\n"
+ "db_default_release %10u, db_custom_release %10u,\n"
+ "db_alloc %10u, db_i2key %10u,\n"
+ "db_ui2key %10u, db_str2key %10u,\n"
+ "db_i2data %10u, db_ui2data %10u,\n"
+ "db_ptr2data %10u, db_data2i %10u,\n"
+ "db_data2ui %10u, db_data2ptr %10u,\n"
+ "db_init %10u, db_final %10u\n",
+ stats.db_rotate_left, stats.db_rotate_right,
+ stats.db_rebalance, stats.db_rebalance_erase,
+ stats.db_is_key_null,
+ stats.db_dup_key, stats.db_dup_key_free,
+ stats.db_free_add, stats.db_free_remove,
+ stats.db_free_lock, stats.db_free_unlock,
+ stats.db_int_cmp, stats.db_uint_cmp,
+ stats.db_string_cmp, stats.db_istring_cmp,
+ stats.db_int_hash, stats.db_uint_hash,
+ stats.db_string_hash, stats.db_istring_hash,
+ stats.db_release_nothing, stats.db_release_key,
+ stats.db_release_data, stats.db_release_both,
+ stats.dbit_first, stats.dbit_last,
+ stats.dbit_next, stats.dbit_prev,
+ stats.dbit_exists, stats.dbit_remove,
+ stats.dbit_destroy, stats.db_iterator,
+ stats.db_exists, stats.db_get,
+ stats.db_getall, stats.db_vgetall,
+ stats.db_ensure, stats.db_vensure,
+ stats.db_put, stats.db_remove,
+ stats.db_foreach, stats.db_vforeach,
+ stats.db_clear, stats.db_vclear,
+ stats.db_destroy, stats.db_vdestroy,
+ stats.db_size, stats.db_type,
+ stats.db_options, stats.db_fix_options,
+ stats.db_default_cmp, stats.db_default_hash,
+ stats.db_default_release, stats.db_custom_release,
+ stats.db_alloc, stats.db_i2key,
+ stats.db_ui2key, stats.db_str2key,
+ stats.db_i2data, stats.db_ui2data,
+ stats.db_ptr2data, stats.db_data2i,
+ stats.db_data2ui, stats.db_data2ptr,
+ stats.db_init, stats.db_final);
#endif /* DB_ENABLE_STATS */
}
// Link DB System - jAthena
-void linkdb_insert( struct linkdb_node** head, void *key, void* data)
-{
- struct linkdb_node *node;
- if( head == NULL ) return ;
- node = (struct linkdb_node*)aMalloc( sizeof(struct linkdb_node) );
- if( *head == NULL ) {
- // first node
- *head = node;
- node->prev = NULL;
- node->next = NULL;
- } else {
- // link nodes
- node->next = *head;
- node->prev = (*head)->prev;
- (*head)->prev = node;
- (*head) = node;
- }
- node->key = key;
- node->data = data;
-}
-
-void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... )
-{
- struct linkdb_node *node;
- if( head == NULL ) return;
- node = *head;
- while ( node ) {
- va_list args;
- va_start(args, func);
- func( node->key, node->data, args );
- va_end(args);
- node = node->next;
- }
-}
-
-void* linkdb_search( struct linkdb_node** head, void *key)
-{
- int n = 0;
- struct linkdb_node *node;
- if( head == NULL ) return NULL;
- node = *head;
- while( node ) {
- if( node->key == key ) {
- if( node->prev && n > 5 ) {
- //Moving the head in order to improve processing efficiency
- if(node->prev) node->prev->next = node->next;
- if(node->next) node->next->prev = node->prev;
- node->next = *head;
- node->prev = (*head)->prev;
- (*head)->prev = node;
- (*head) = node;
- }
- return node->data;
- }
- node = node->next;
- n++;
- }
- return NULL;
-}
-
-void* linkdb_erase( struct linkdb_node** head, void *key)
-{
- struct linkdb_node *node;
- if( head == NULL ) return NULL;
- node = *head;
- while( node ) {
- if( node->key == key ) {
- void *data = node->data;
- if( node->prev == NULL )
- *head = node->next;
- else
- node->prev->next = node->next;
- if( node->next )
- node->next->prev = node->prev;
- aFree( node );
- return data;
- }
- node = node->next;
- }
- return NULL;
-}
-
-void linkdb_replace( struct linkdb_node** head, void *key, void *data )
-{
- int n = 0;
- struct linkdb_node *node;
- if( head == NULL ) return ;
- node = *head;
- while( node ) {
- if( node->key == key ) {
- if( node->prev && n > 5 ) {
- //Moving the head in order to improve processing efficiency
- if(node->prev) node->prev->next = node->next;
- if(node->next) node->next->prev = node->prev;
- node->next = *head;
- node->prev = (*head)->prev;
- (*head)->prev = node;
- (*head) = node;
- }
- node->data = data;
- return ;
- }
- node = node->next;
- n++;
- }
- //Insert because it can not find
- linkdb_insert( head, key, data );
-}
-
-void linkdb_final( struct linkdb_node** head )
-{
- struct linkdb_node *node, *node2;
- if( head == NULL ) return ;
- node = *head;
- while( node ) {
- node2 = node->next;
- aFree( node );
- node = node2;
- }
- *head = NULL;
+void linkdb_insert(struct linkdb_node **head, void *key, void *data)
+{
+ struct linkdb_node *node;
+ if (head == NULL) return ;
+ node = (struct linkdb_node *)aMalloc(sizeof(struct linkdb_node));
+ if (*head == NULL) {
+ // first node
+ *head = node;
+ node->prev = NULL;
+ node->next = NULL;
+ } else {
+ // link nodes
+ node->next = *head;
+ node->prev = (*head)->prev;
+ (*head)->prev = node;
+ (*head) = node;
+ }
+ node->key = key;
+ node->data = data;
+}
+
+void linkdb_foreach(struct linkdb_node **head, LinkDBFunc func, ...)
+{
+ struct linkdb_node *node;
+ if (head == NULL) return;
+ node = *head;
+ while (node) {
+ va_list args;
+ va_start(args, func);
+ func(node->key, node->data, args);
+ va_end(args);
+ node = node->next;
+ }
+}
+
+void *linkdb_search(struct linkdb_node **head, void *key)
+{
+ int n = 0;
+ struct linkdb_node *node;
+ if (head == NULL) return NULL;
+ node = *head;
+ while (node) {
+ if (node->key == key) {
+ if (node->prev && n > 5) {
+ //Moving the head in order to improve processing efficiency
+ if (node->prev) node->prev->next = node->next;
+ if (node->next) node->next->prev = node->prev;
+ node->next = *head;
+ node->prev = (*head)->prev;
+ (*head)->prev = node;
+ (*head) = node;
+ }
+ return node->data;
+ }
+ node = node->next;
+ n++;
+ }
+ return NULL;
+}
+
+void *linkdb_erase(struct linkdb_node **head, void *key)
+{
+ struct linkdb_node *node;
+ if (head == NULL) return NULL;
+ node = *head;
+ while (node) {
+ if (node->key == key) {
+ void *data = node->data;
+ if (node->prev == NULL)
+ *head = node->next;
+ else
+ node->prev->next = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
+ aFree(node);
+ return data;
+ }
+ node = node->next;
+ }
+ return NULL;
+}
+
+void linkdb_replace(struct linkdb_node **head, void *key, void *data)
+{
+ int n = 0;
+ struct linkdb_node *node;
+ if (head == NULL) return ;
+ node = *head;
+ while (node) {
+ if (node->key == key) {
+ if (node->prev && n > 5) {
+ //Moving the head in order to improve processing efficiency
+ if (node->prev) node->prev->next = node->next;
+ if (node->next) node->next->prev = node->prev;
+ node->next = *head;
+ node->prev = (*head)->prev;
+ (*head)->prev = node;
+ (*head) = node;
+ }
+ node->data = data;
+ return ;
+ }
+ node = node->next;
+ n++;
+ }
+ //Insert because it can not find
+ linkdb_insert(head, key, data);
+}
+
+void linkdb_final(struct linkdb_node **head)
+{
+ struct linkdb_node *node, *node2;
+ if (head == NULL) return ;
+ node = *head;
+ while (node) {
+ node2 = node->next;
+ aFree(node);
+ node = node2;
+ }
+ *head = NULL;
}
diff --git a/src/common/db.h b/src/common/db.h
index 4fe6a93d6..eff3b775e 100644
--- a/src/common/db.h
+++ b/src/common/db.h
@@ -69,15 +69,15 @@
* @see #db_custom_release(DBRelease)
*/
typedef enum DBRelease {
- DB_RELEASE_NOTHING = 0,
- DB_RELEASE_KEY = 1,
- DB_RELEASE_DATA = 2,
- DB_RELEASE_BOTH = 3
+ DB_RELEASE_NOTHING = 0,
+ DB_RELEASE_KEY = 1,
+ DB_RELEASE_DATA = 2,
+ DB_RELEASE_BOTH = 3
} DBRelease;
/**
* Supported types of database.
- * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the
+ * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the
* types of databases.
* @param DB_INT Uses int's for keys
* @param DB_UINT Uses unsigned int's for keys
@@ -93,22 +93,22 @@ typedef enum DBRelease {
* @see #db_alloc(const char *,int,DBType,DBOptions,unsigned short)
*/
typedef enum DBType {
- DB_INT,
- DB_UINT,
- DB_STRING,
- DB_ISTRING
+ DB_INT,
+ DB_UINT,
+ DB_STRING,
+ DB_ISTRING
} DBType;
/**
* Bitfield of options that define the behaviour of the database.
- * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the
+ * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the
* types of databases.
* @param DB_OPT_BASE Base options: does not duplicate keys, releases nothing
* and does not allow NULL keys or NULL data.
- * @param DB_OPT_DUP_KEY Duplicates the keys internally. If DB_OPT_RELEASE_KEY
+ * @param DB_OPT_DUP_KEY Duplicates the keys internally. If DB_OPT_RELEASE_KEY
* is defined, the real key is freed as soon as the entry is added.
* @param DB_OPT_RELEASE_KEY Releases the key.
- * @param DB_OPT_RELEASE_DATA Releases the data whenever an entry is removed
+ * @param DB_OPT_RELEASE_DATA Releases the data whenever an entry is removed
* from the database.
* WARNING: for funtions that return the data (like DBMap::remove),
* a dangling pointer will be returned.
@@ -121,13 +121,13 @@ typedef enum DBType {
* @see #db_alloc(const char *,int,DBType,DBOptions,unsigned short)
*/
typedef enum DBOptions {
- DB_OPT_BASE = 0,
- DB_OPT_DUP_KEY = 1,
- DB_OPT_RELEASE_KEY = 2,
- DB_OPT_RELEASE_DATA = 4,
- DB_OPT_RELEASE_BOTH = 6,
- DB_OPT_ALLOW_NULL_KEY = 8,
- DB_OPT_ALLOW_NULL_DATA = 16,
+ DB_OPT_BASE = 0,
+ DB_OPT_DUP_KEY = 1,
+ DB_OPT_RELEASE_KEY = 2,
+ DB_OPT_RELEASE_DATA = 4,
+ DB_OPT_RELEASE_BOTH = 6,
+ DB_OPT_ALLOW_NULL_KEY = 8,
+ DB_OPT_ALLOW_NULL_DATA = 16,
} DBOptions;
/**
@@ -142,9 +142,9 @@ typedef enum DBOptions {
* @see DBMap#remove
*/
typedef union DBKey {
- int i;
- unsigned int ui;
- const char *str;
+ int i;
+ unsigned int ui;
+ const char *str;
} DBKey;
/**
@@ -156,9 +156,9 @@ typedef union DBKey {
* @see #DBData
*/
typedef enum DBDataType {
- DB_DATA_INT,
- DB_DATA_UINT,
- DB_DATA_PTR
+ DB_DATA_INT,
+ DB_DATA_UINT,
+ DB_DATA_PTR
} DBDataType;
/**
@@ -171,16 +171,16 @@ typedef enum DBDataType {
* @public
*/
typedef struct DBData {
- DBDataType type;
- union {
- int i;
- unsigned int ui;
- void *ptr;
- } u;
+ DBDataType type;
+ union {
+ int i;
+ unsigned int ui;
+ void *ptr;
+ } u;
} DBData;
/**
- * Format of functions that create the data for the key when the entry doesn't
+ * Format of functions that create the data for the key when the entry doesn't
* exist in the database yet.
* @param key Key of the database entry
* @param args Extra arguments of the function
@@ -189,12 +189,12 @@ typedef struct DBData {
* @see DBMap#vensure
* @see DBMap#ensure
*/
-typedef DBData (*DBCreateData)(DBKey key, va_list args);
+typedef DBData(*DBCreateData)(DBKey key, va_list args);
/**
- * Format of functions to be applied to an unspecified quantity of entries of
+ * Format of functions to be applied to an unspecified quantity of entries of
* a database.
- * Any function that applies this function to the database will return the sum
+ * Any function that applies this function to the database will return the sum
* of values returned by this function.
* @param key Key of the database entry
* @param data Data of the database entry
@@ -272,87 +272,86 @@ typedef struct DBMap DBMap;
* Database iterator.
* Supports forward iteration, backward iteration and removing entries from the database.
* The iterator is initially positioned before the first entry of the database.
- * While the iterator exists the database is locked internally, so invoke
+ * While the iterator exists the database is locked internally, so invoke
* {@link DBIterator#destroy} as soon as possible.
* @public
* @see #DBMap
*/
-struct DBIterator
-{
-
- /**
- * Fetches the first entry in the database.
- * Returns the data of the entry.
- * Puts the key in out_key, if out_key is not NULL.
- * @param self Iterator
- * @param out_key Key of the entry
- * @return Data of the entry
- * @protected
- */
- DBData* (*first)(DBIterator* self, DBKey* out_key);
-
- /**
- * Fetches the last entry in the database.
- * Returns the data of the entry.
- * Puts the key in out_key, if out_key is not NULL.
- * @param self Iterator
- * @param out_key Key of the entry
- * @return Data of the entry
- * @protected
- */
- DBData* (*last)(DBIterator* self, DBKey* out_key);
-
- /**
- * Fetches the next entry in the database.
- * Returns the data of the entry.
- * Puts the key in out_key, if out_key is not NULL.
- * @param self Iterator
- * @param out_key Key of the entry
- * @return Data of the entry
- * @protected
- */
- DBData* (*next)(DBIterator* self, DBKey* out_key);
-
- /**
- * Fetches the previous entry in the database.
- * Returns the data of the entry.
- * Puts the key in out_key, if out_key is not NULL.
- * @param self Iterator
- * @param out_key Key of the entry
- * @return Data of the entry
- * @protected
- */
- DBData* (*prev)(DBIterator* self, DBKey* out_key);
-
- /**
- * Returns true if the fetched entry exists.
- * The databases entries might have NULL data, so use this to to test if
- * the iterator is done.
- * @param self Iterator
- * @return true is the entry exists
- * @protected
- */
- bool (*exists)(DBIterator* self);
-
- /**
- * Removes the current entry from the database.
- * NOTE: {@link DBIterator#exists} will return false until another entry
- * is fetched
- * Puts data of the removed entry in out_data, if out_data is not NULL.
- * @param self Iterator
- * @param out_data Data of the removed entry.
- * @return 1 if entry was removed, 0 otherwise
- * @protected
- * @see DBMap#remove
- */
- int (*remove)(DBIterator* self, DBData *out_data);
-
- /**
- * Destroys this iterator and unlocks the database.
- * @param self Iterator
- * @protected
- */
- void (*destroy)(DBIterator* self);
+struct DBIterator {
+
+ /**
+ * Fetches the first entry in the database.
+ * Returns the data of the entry.
+ * Puts the key in out_key, if out_key is not NULL.
+ * @param self Iterator
+ * @param out_key Key of the entry
+ * @return Data of the entry
+ * @protected
+ */
+ DBData *(*first)(DBIterator *self, DBKey *out_key);
+
+ /**
+ * Fetches the last entry in the database.
+ * Returns the data of the entry.
+ * Puts the key in out_key, if out_key is not NULL.
+ * @param self Iterator
+ * @param out_key Key of the entry
+ * @return Data of the entry
+ * @protected
+ */
+ DBData *(*last)(DBIterator *self, DBKey *out_key);
+
+ /**
+ * Fetches the next entry in the database.
+ * Returns the data of the entry.
+ * Puts the key in out_key, if out_key is not NULL.
+ * @param self Iterator
+ * @param out_key Key of the entry
+ * @return Data of the entry
+ * @protected
+ */
+ DBData *(*next)(DBIterator *self, DBKey *out_key);
+
+ /**
+ * Fetches the previous entry in the database.
+ * Returns the data of the entry.
+ * Puts the key in out_key, if out_key is not NULL.
+ * @param self Iterator
+ * @param out_key Key of the entry
+ * @return Data of the entry
+ * @protected
+ */
+ DBData *(*prev)(DBIterator *self, DBKey *out_key);
+
+ /**
+ * Returns true if the fetched entry exists.
+ * The databases entries might have NULL data, so use this to to test if
+ * the iterator is done.
+ * @param self Iterator
+ * @return true is the entry exists
+ * @protected
+ */
+ bool (*exists)(DBIterator *self);
+
+ /**
+ * Removes the current entry from the database.
+ * NOTE: {@link DBIterator#exists} will return false until another entry
+ * is fetched
+ * Puts data of the removed entry in out_data, if out_data is not NULL.
+ * @param self Iterator
+ * @param out_data Data of the removed entry.
+ * @return 1 if entry was removed, 0 otherwise
+ * @protected
+ * @see DBMap#remove
+ */
+ int (*remove)(DBIterator *self, DBData *out_data);
+
+ /**
+ * Destroys this iterator and unlocks the database.
+ * @param self Iterator
+ * @protected
+ */
+ void (*destroy)(DBIterator *self);
};
@@ -364,235 +363,235 @@ struct DBIterator
*/
struct DBMap {
- /**
- * Returns a new iterator for this database.
- * The iterator keeps the database locked until it is destroyed.
- * The database will keep functioning normally but will only free internal
- * memory when unlocked, so destroy the iterator as soon as possible.
- * @param self Database
- * @return New iterator
- * @protected
- */
- 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 identified by the key.
- * @param self Database
- * @param key Key that identifies the entry
- * @return Data of the entry or NULL if not found
- * @protected
- */
- DBData* (*get)(DBMap* self, DBKey key);
-
- /**
- * Just calls {@link DBMap#vgetall}.
- * Get the data of the entries matched by <code>match</code>.
- * It puts a maximum of <code>max</code> entries into <code>buf</code>.
- * If <code>buf</code> is NULL, it only counts the matches.
- * Returns the number of entries that matched.
- * NOTE: if the value returned is greater than <code>max</code>, only the
- * first <code>max</code> entries found are put into the buffer.
- * @param self Database
- * @param buf Buffer to put the data of the matched entries
- * @param max Maximum number of data entries to be put into buf
- * @param match Function that matches the database entries
- * @param ... Extra arguments for match
- * @return The number of entries that matched
- * @protected
- * @see DBMap#vgetall(DBMap*,void **,unsigned int,DBMatcher,va_list)
- */
- unsigned int (*getall)(DBMap* self, DBData** buf, unsigned int max, DBMatcher match, ...);
-
- /**
- * Get the data of the entries matched by <code>match</code>.
- * It puts a maximum of <code>max</code> entries into <code>buf</code>.
- * If <code>buf</code> is NULL, it only counts the matches.
- * Returns the number of entries that matched.
- * NOTE: if the value returned is greater than <code>max</code>, only the
- * first <code>max</code> entries found are put into the buffer.
- * @param self Database
- * @param buf Buffer to put the data of the matched entries
- * @param max Maximum number of data entries to be put into buf
- * @param match Function that matches the database entries
- * @param ... Extra arguments for match
- * @return The number of entries that matched
- * @protected
- * @see DBMap#getall(DBMap*,void **,unsigned int,DBMatcher,...)
- */
- unsigned int (*vgetall)(DBMap* self, DBData** buf, unsigned int max, DBMatcher match, va_list args);
-
- /**
- * Just calls {@link DBMap#vensure}.
- * Get the data of the entry identified by the key.
- * If the entry does not exist, an entry is added with the data returned by
- * <code>create</code>.
- * @param self Database
- * @param key Key that identifies the entry
- * @param create Function used to create the data if the entry doesn't exist
- * @param ... Extra arguments for create
- * @return Data of the entry
- * @protected
- * @see DBMap#vensure(DBMap*,DBKey,DBCreateData,va_list)
- */
- DBData* (*ensure)(DBMap* self, DBKey key, DBCreateData create, ...);
-
- /**
- * Get the data of the entry identified by the key.
- * If the entry does not exist, an entry is added with the data returned by
- * <code>create</code>.
- * @param self Database
- * @param key Key that identifies the entry
- * @param create Function used to create the data if the entry doesn't exist
- * @param args Extra arguments for create
- * @return Data of the entry
- * @protected
- * @see DBMap#ensure(DBMap*,DBKey,DBCreateData,...)
- */
- DBData* (*vensure)(DBMap* self, DBKey key, DBCreateData create, va_list args);
-
- /**
- * Put the data identified by the key in the database.
- * Puts the previous data in out_data, if out_data is not NULL.
- * NOTE: Uses the new key, the old one is released.
- * @param self Database
- * @param key Key that identifies the data
- * @param data Data to be put in the database
- * @param out_data Previous data if the entry exists
- * @return 1 if if the entry already exists, 0 otherwise
- * @protected
- */
- int (*put)(DBMap* self, DBKey key, DBData data, DBData *out_data);
-
- /**
- * Remove an entry from the database.
- * Puts the previous data in out_data, if out_data is not NULL.
- * NOTE: The key (of the database) is released.
- * @param self Database
- * @param key Key that identifies the entry
- * @param out_data Previous data if the entry exists
- * @return 1 if if the entry already exists, 0 otherwise
- * @protected
- */
- int (*remove)(DBMap* self, DBKey key, DBData *out_data);
-
- /**
- * Just calls {@link DBMap#vforeach}.
- * Apply <code>func</code> to every entry in the database.
- * Returns the sum of values returned by func.
- * @param self Database
- * @param func Function to be applied
- * @param ... Extra arguments for func
- * @return Sum of the values returned by func
- * @protected
- * @see DBMap#vforeach(DBMap*,DBApply,va_list)
- */
- int (*foreach)(DBMap* self, DBApply func, ...);
-
- /**
- * Apply <code>func</code> to every entry in the database.
- * Returns the sum of values returned by func.
- * @param self Database
- * @param func Function to be applied
- * @param args Extra arguments for func
- * @return Sum of the values returned by func
- * @protected
- * @see DBMap#foreach(DBMap*,DBApply,...)
- */
- int (*vforeach)(DBMap* self, DBApply func, va_list args);
-
- /**
- * Just calls {@link DBMap#vclear}.
- * Removes all entries from the database.
- * Before deleting an entry, func is applied to it.
- * Releases the key and the data.
- * Returns the sum of values returned by func, if it exists.
- * @param self Database
- * @param func Function to be applied to every entry before deleting
- * @param ... Extra arguments for func
- * @return Sum of values returned by func
- * @protected
- * @see DBMap#vclear(DBMap*,DBApply,va_list)
- */
- int (*clear)(DBMap* self, DBApply func, ...);
-
- /**
- * Removes all entries from the database.
- * Before deleting an entry, func is applied to it.
- * Releases the key and the data.
- * Returns the sum of values returned by func, if it exists.
- * @param self Database
- * @param func Function to be applied to every entry before deleting
- * @param args Extra arguments for func
- * @return Sum of values returned by func
- * @protected
- * @see DBMap#clear(DBMap*,DBApply,...)
- */
- int (*vclear)(DBMap* self, DBApply func, va_list args);
-
- /**
- * Just calls {@link DBMap#vdestroy}.
- * Finalize the database, feeing all the memory it uses.
- * Before deleting an entry, func is applied to it.
- * Releases the key and the data.
- * Returns the sum of values returned by func, if it exists.
- * NOTE: This locks the database globally. Any attempt to insert or remove
- * a database entry will give an error and be aborted (except for clearing).
- * @param self Database
- * @param func Function to be applied to every entry before deleting
- * @param ... Extra arguments for func
- * @return Sum of values returned by func
- * @protected
- * @see DBMap#vdestroy(DBMap*,DBApply,va_list)
- */
- int (*destroy)(DBMap* self, DBApply func, ...);
-
- /**
- * Finalize the database, feeing all the memory it uses.
- * Before deleting an entry, func is applied to it.
- * Returns the sum of values returned by func, if it exists.
- * NOTE: This locks the database globally. Any attempt to insert or remove
- * a database entry will give an error and be aborted (except for clearing).
- * @param self Database
- * @param func Function to be applied to every entry before deleting
- * @param args Extra arguments for func
- * @return Sum of values returned by func
- * @protected
- * @see DBMap#destroy(DBMap*,DBApply,...)
- */
- int (*vdestroy)(DBMap* self, DBApply func, va_list args);
-
- /**
- * Return the size of the database (number of items in the database).
- * @param self Database
- * @return Size of the database
- * @protected
- */
- unsigned int (*size)(DBMap* self);
-
- /**
- * Return the type of the database.
- * @param self Database
- * @return Type of the database
- * @protected
- */
- DBType (*type)(DBMap* self);
-
- /**
- * Return the options of the database.
- * @param self Database
- * @return Options of the database
- * @protected
- */
- DBOptions (*options)(DBMap* self);
+ /**
+ * Returns a new iterator for this database.
+ * The iterator keeps the database locked until it is destroyed.
+ * The database will keep functioning normally but will only free internal
+ * memory when unlocked, so destroy the iterator as soon as possible.
+ * @param self Database
+ * @return New iterator
+ * @protected
+ */
+ 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 identified by the key.
+ * @param self Database
+ * @param key Key that identifies the entry
+ * @return Data of the entry or NULL if not found
+ * @protected
+ */
+ DBData *(*get)(DBMap *self, DBKey key);
+
+ /**
+ * Just calls {@link DBMap#vgetall}.
+ * Get the data of the entries matched by <code>match</code>.
+ * It puts a maximum of <code>max</code> entries into <code>buf</code>.
+ * If <code>buf</code> is NULL, it only counts the matches.
+ * Returns the number of entries that matched.
+ * NOTE: if the value returned is greater than <code>max</code>, only the
+ * first <code>max</code> entries found are put into the buffer.
+ * @param self Database
+ * @param buf Buffer to put the data of the matched entries
+ * @param max Maximum number of data entries to be put into buf
+ * @param match Function that matches the database entries
+ * @param ... Extra arguments for match
+ * @return The number of entries that matched
+ * @protected
+ * @see DBMap#vgetall(DBMap*,void **,unsigned int,DBMatcher,va_list)
+ */
+ unsigned int (*getall)(DBMap *self, DBData **buf, unsigned int max, DBMatcher match, ...);
+
+ /**
+ * Get the data of the entries matched by <code>match</code>.
+ * It puts a maximum of <code>max</code> entries into <code>buf</code>.
+ * If <code>buf</code> is NULL, it only counts the matches.
+ * Returns the number of entries that matched.
+ * NOTE: if the value returned is greater than <code>max</code>, only the
+ * first <code>max</code> entries found are put into the buffer.
+ * @param self Database
+ * @param buf Buffer to put the data of the matched entries
+ * @param max Maximum number of data entries to be put into buf
+ * @param match Function that matches the database entries
+ * @param ... Extra arguments for match
+ * @return The number of entries that matched
+ * @protected
+ * @see DBMap#getall(DBMap*,void **,unsigned int,DBMatcher,...)
+ */
+ unsigned int (*vgetall)(DBMap *self, DBData **buf, unsigned int max, DBMatcher match, va_list args);
+
+ /**
+ * Just calls {@link DBMap#vensure}.
+ * Get the data of the entry identified by the key.
+ * If the entry does not exist, an entry is added with the data returned by
+ * <code>create</code>.
+ * @param self Database
+ * @param key Key that identifies the entry
+ * @param create Function used to create the data if the entry doesn't exist
+ * @param ... Extra arguments for create
+ * @return Data of the entry
+ * @protected
+ * @see DBMap#vensure(DBMap*,DBKey,DBCreateData,va_list)
+ */
+ DBData *(*ensure)(DBMap *self, DBKey key, DBCreateData create, ...);
+
+ /**
+ * Get the data of the entry identified by the key.
+ * If the entry does not exist, an entry is added with the data returned by
+ * <code>create</code>.
+ * @param self Database
+ * @param key Key that identifies the entry
+ * @param create Function used to create the data if the entry doesn't exist
+ * @param args Extra arguments for create
+ * @return Data of the entry
+ * @protected
+ * @see DBMap#ensure(DBMap*,DBKey,DBCreateData,...)
+ */
+ DBData *(*vensure)(DBMap *self, DBKey key, DBCreateData create, va_list args);
+
+ /**
+ * Put the data identified by the key in the database.
+ * Puts the previous data in out_data, if out_data is not NULL.
+ * NOTE: Uses the new key, the old one is released.
+ * @param self Database
+ * @param key Key that identifies the data
+ * @param data Data to be put in the database
+ * @param out_data Previous data if the entry exists
+ * @return 1 if if the entry already exists, 0 otherwise
+ * @protected
+ */
+ int (*put)(DBMap *self, DBKey key, DBData data, DBData *out_data);
+
+ /**
+ * Remove an entry from the database.
+ * Puts the previous data in out_data, if out_data is not NULL.
+ * NOTE: The key (of the database) is released.
+ * @param self Database
+ * @param key Key that identifies the entry
+ * @param out_data Previous data if the entry exists
+ * @return 1 if if the entry already exists, 0 otherwise
+ * @protected
+ */
+ int (*remove)(DBMap *self, DBKey key, DBData *out_data);
+
+ /**
+ * Just calls {@link DBMap#vforeach}.
+ * Apply <code>func</code> to every entry in the database.
+ * Returns the sum of values returned by func.
+ * @param self Database
+ * @param func Function to be applied
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ * @protected
+ * @see DBMap#vforeach(DBMap*,DBApply,va_list)
+ */
+ int (*foreach)(DBMap *self, DBApply func, ...);
+
+ /**
+ * Apply <code>func</code> to every entry in the database.
+ * Returns the sum of values returned by func.
+ * @param self Database
+ * @param func Function to be applied
+ * @param args Extra arguments for func
+ * @return Sum of the values returned by func
+ * @protected
+ * @see DBMap#foreach(DBMap*,DBApply,...)
+ */
+ int (*vforeach)(DBMap *self, DBApply func, va_list args);
+
+ /**
+ * Just calls {@link DBMap#vclear}.
+ * Removes all entries from the database.
+ * Before deleting an entry, func is applied to it.
+ * Releases the key and the data.
+ * Returns the sum of values returned by func, if it exists.
+ * @param self Database
+ * @param func Function to be applied to every entry before deleting
+ * @param ... Extra arguments for func
+ * @return Sum of values returned by func
+ * @protected
+ * @see DBMap#vclear(DBMap*,DBApply,va_list)
+ */
+ int (*clear)(DBMap *self, DBApply func, ...);
+
+ /**
+ * Removes all entries from the database.
+ * Before deleting an entry, func is applied to it.
+ * Releases the key and the data.
+ * Returns the sum of values returned by func, if it exists.
+ * @param self Database
+ * @param func Function to be applied to every entry before deleting
+ * @param args Extra arguments for func
+ * @return Sum of values returned by func
+ * @protected
+ * @see DBMap#clear(DBMap*,DBApply,...)
+ */
+ int (*vclear)(DBMap *self, DBApply func, va_list args);
+
+ /**
+ * Just calls {@link DBMap#vdestroy}.
+ * Finalize the database, feeing all the memory it uses.
+ * Before deleting an entry, func is applied to it.
+ * Releases the key and the data.
+ * Returns the sum of values returned by func, if it exists.
+ * NOTE: This locks the database globally. Any attempt to insert or remove
+ * a database entry will give an error and be aborted (except for clearing).
+ * @param self Database
+ * @param func Function to be applied to every entry before deleting
+ * @param ... Extra arguments for func
+ * @return Sum of values returned by func
+ * @protected
+ * @see DBMap#vdestroy(DBMap*,DBApply,va_list)
+ */
+ int (*destroy)(DBMap *self, DBApply func, ...);
+
+ /**
+ * Finalize the database, feeing all the memory it uses.
+ * Before deleting an entry, func is applied to it.
+ * Returns the sum of values returned by func, if it exists.
+ * NOTE: This locks the database globally. Any attempt to insert or remove
+ * a database entry will give an error and be aborted (except for clearing).
+ * @param self Database
+ * @param func Function to be applied to every entry before deleting
+ * @param args Extra arguments for func
+ * @return Sum of values returned by func
+ * @protected
+ * @see DBMap#destroy(DBMap*,DBApply,...)
+ */
+ int (*vdestroy)(DBMap *self, DBApply func, va_list args);
+
+ /**
+ * Return the size of the database (number of items in the database).
+ * @param self Database
+ * @return Size of the database
+ * @protected
+ */
+ unsigned int (*size)(DBMap *self);
+
+ /**
+ * Return the type of the database.
+ * @param self Database
+ * @return Type of the database
+ * @protected
+ */
+ DBType(*type)(DBMap *self);
+
+ /**
+ * Return the options of the database.
+ * @param self Database
+ * @return Options of the database
+ * @protected
+ */
+ DBOptions(*options)(DBMap *self);
};
@@ -727,7 +726,7 @@ DBComparator db_default_cmp(DBType type);
DBHasher db_default_hash(DBType type);
/**
- * Returns the default releaser for the specified type of database with the
+ * Returns the default releaser for the specified type of database with the
* specified options.
* NOTE: the options are fixed by {@link #db_fix_options(DBType,DBOptions)}
* before choosing the releaser
@@ -756,7 +755,7 @@ DBReleaser db_custom_release(DBRelease which);
/**
* Allocate a new database of the specified type.
- * It uses the default comparator, hasher and releaser of the specified
+ * It uses the default comparator, hasher and releaser of the specified
* database type and fixed options.
* NOTE: the options are fixed by {@link #db_fix_options(DBType,DBOptions)}
* before creating the database.
@@ -764,7 +763,7 @@ DBReleaser db_custom_release(DBRelease which);
* @param line Line of the file where the database is being allocated
* @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
+ * @param maxlen Maximum length of the string to be used as key in string
* databases. If 0, the maximum number of maxlen is used (64K).
* @return The interface of the database
* @public
@@ -775,7 +774,7 @@ DBReleaser db_custom_release(DBRelease which);
* @see #db_default_release(DBType,DBOptions)
* @see #db_fix_options(DBType,DBOptions)
*/
-DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen);
+DBMap *db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen);
/**
* Manual cast from 'int' to the union DBKey.
@@ -850,7 +849,7 @@ unsigned int db_data2ui(DBData *data);
* @return Void* value of the data.
* @public
*/
-void* db_data2ptr(DBData *data);
+void *db_data2ptr(DBData *data);
/**
* Initialize the database system.
@@ -869,20 +868,20 @@ void db_final(void);
// Link DB System - From jAthena
struct linkdb_node {
- struct linkdb_node *next;
- struct linkdb_node *prev;
- void *key;
- void *data;
+ struct linkdb_node *next;
+ struct linkdb_node *prev;
+ void *key;
+ void *data;
};
-typedef void (*LinkDBFunc)(void* key, void* data, va_list args);
+typedef void (*LinkDBFunc)(void *key, void *data, va_list args);
-void linkdb_insert ( struct linkdb_node** head, void *key, void* data); // d•¡‚ðl—¶‚µ‚È‚¢
-void linkdb_replace( struct linkdb_node** head, void *key, void* data); // d•¡‚ðl—¶‚·‚é
-void* linkdb_search ( struct linkdb_node** head, void *key);
-void* linkdb_erase ( struct linkdb_node** head, void *key);
-void linkdb_final ( struct linkdb_node** head );
-void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
+void linkdb_insert(struct linkdb_node **head, void *key, void *data); // d•¡‚ðl—¶‚µ‚È‚¢
+void linkdb_replace(struct linkdb_node **head, void *key, void *data); // d•¡‚ðl—¶‚·‚é
+void *linkdb_search(struct linkdb_node **head, void *key);
+void *linkdb_erase(struct linkdb_node **head, void *key);
+void linkdb_final(struct linkdb_node **head);
+void linkdb_foreach(struct linkdb_node **head, LinkDBFunc func, ...);
@@ -894,11 +893,11 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __var Index variable
/// @param __cmp Expression that returns true when the target entry is found
#define ARR_FIND(__start, __end, __var, __cmp) \
- do{ \
- for( (__var) = (__start); (__var) < (__end); ++(__var) ) \
- if( __cmp ) \
- break; \
- }while(0)
+ do{ \
+ for( (__var) = (__start); (__var) < (__end); ++(__var) ) \
+ if( __cmp ) \
+ break; \
+ }while(0)
@@ -912,18 +911,18 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __arr Array
/// @param __type Type of entry
#define ARR_MOVE(__from, __to, __arr, __type) \
- do{ \
- if( (__from) != (__to) ) \
- { \
- __type __backup__; \
- memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
- if( (__from) < (__to) ) \
- memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
- else if( (__from) > (__to) ) \
- memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
- memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
- } \
- }while(0)
+ do{ \
+ if( (__from) != (__to) ) \
+ { \
+ __type __backup__; \
+ memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
+ if( (__from) < (__to) ) \
+ memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
+ else if( (__from) > (__to) ) \
+ memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
+ memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+ } \
+ }while(0)
@@ -935,12 +934,12 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __arr Array
/// @param __type Type of entry
#define ARR_MOVERIGHT(__from, __to, __arr, __type) \
- do{ \
- __type __backup__; \
- memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
- memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
- memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
- }while(0)
+ do{ \
+ __type __backup__; \
+ memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
+ memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \
+ memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+ }while(0)
@@ -952,12 +951,12 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __arr Array
/// @param __type Type of entry
#define ARR_MOVELEFT(__from, __to, __arr, __type) \
- do{ \
- __type __backup__; \
- memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
- memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
- memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
- }while(0)
+ do{ \
+ __type __backup__; \
+ memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \
+ memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \
+ memmove((__arr)+(__to), &__backup__, sizeof(__type)); \
+ }while(0)
@@ -971,11 +970,11 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
///
/// @param __type Type of data
#define VECTOR_DECL(__type) \
- struct { \
- size_t _max_; \
- size_t _len_; \
- __type* _data_; \
- }
+ struct { \
+ size_t _max_; \
+ size_t _len_; \
+ __type* _data_; \
+ }
@@ -984,11 +983,11 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __name Structure name
/// @param __type Type of data
#define VECTOR_STRUCT_DECL(__name,__type) \
- struct __name { \
- size_t _max_; \
- size_t _len_; \
- __type* _data_; \
- }
+ struct __name { \
+ size_t _max_; \
+ size_t _len_; \
+ __type* _data_; \
+ }
@@ -997,7 +996,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __type Type of data
/// @param __var Variable name
#define VECTOR_VAR(__type,__var) \
- VECTOR_DECL(__type) __var = {0,0,NULL}
+ VECTOR_DECL(__type) __var = {0,0,NULL}
@@ -1006,7 +1005,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __name Structure name
/// @param __var Variable name
#define VECTOR_STRUCT_VAR(__name,__var) \
- struct __name __var = {0,0,NULL}
+ struct __name __var = {0,0,NULL}
@@ -1014,7 +1013,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
///
/// @param __vec Vector
#define VECTOR_INIT(__vec) \
- memset(&(__vec), 0, sizeof(__vec))
+ memset(&(__vec), 0, sizeof(__vec))
@@ -1023,7 +1022,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @return Array of values
#define VECTOR_DATA(__vec) \
- ( (__vec)._data_ )
+ ( (__vec)._data_ )
@@ -1032,7 +1031,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @return Length
#define VECTOR_LENGTH(__vec) \
- ( (__vec)._len_ )
+ ( (__vec)._len_ )
@@ -1041,7 +1040,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @return Capacity
#define VECTOR_CAPACITY(__vec) \
- ( (__vec)._max_ )
+ ( (__vec)._max_ )
@@ -1052,7 +1051,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __idx Index
/// @return Value
#define VECTOR_INDEX(__vec,__idx) \
- ( VECTOR_DATA(__vec)[__idx] )
+ ( VECTOR_DATA(__vec)[__idx] )
@@ -1062,7 +1061,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @return First value
#define VECTOR_FIRST(__vec) \
- ( VECTOR_INDEX(__vec,0) )
+ ( VECTOR_INDEX(__vec,0) )
@@ -1072,7 +1071,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @return Last value
#define VECTOR_LAST(__vec) \
- ( VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)-1) )
+ ( VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)-1) )
@@ -1082,27 +1081,27 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @param __n Size
#define VECTOR_RESIZE(__vec,__n) \
- do{ \
- if( (__n) > VECTOR_CAPACITY(__vec) ) \
- { /* increase size */ \
- if( VECTOR_CAPACITY(__vec) == 0 ) SET_POINTER(VECTOR_DATA(__vec), aMalloc((__n)*sizeof(VECTOR_FIRST(__vec)))); /* allocate new */ \
- else SET_POINTER(VECTOR_DATA(__vec), aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec)))); /* reallocate */ \
- memset(VECTOR_DATA(__vec)+VECTOR_LENGTH(__vec), 0, (VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec))*sizeof(VECTOR_FIRST(__vec))); /* clear new data */ \
- VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \
- } \
- else if( (__n) == 0 && VECTOR_CAPACITY(__vec) ) \
- { /* clear vector */ \
- aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* free data */ \
- VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \
- VECTOR_LENGTH(__vec) = 0; /* clear length */ \
- } \
- else if( (__n) < VECTOR_CAPACITY(__vec) ) \
- { /* reduce size */ \
- SET_POINTER(VECTOR_DATA(__vec), aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec)))); /* reallocate */ \
- VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \
- if( VECTOR_LENGTH(__vec) > (__n) ) VECTOR_LENGTH(__vec) = (__n); /* update length */ \
- } \
- }while(0)
+ do{ \
+ if( (__n) > VECTOR_CAPACITY(__vec) ) \
+ { /* increase size */ \
+ if( VECTOR_CAPACITY(__vec) == 0 ) SET_POINTER(VECTOR_DATA(__vec), aMalloc((__n)*sizeof(VECTOR_FIRST(__vec)))); /* allocate new */ \
+ else SET_POINTER(VECTOR_DATA(__vec), aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec)))); /* reallocate */ \
+ memset(VECTOR_DATA(__vec)+VECTOR_LENGTH(__vec), 0, (VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec))*sizeof(VECTOR_FIRST(__vec))); /* clear new data */ \
+ VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \
+ } \
+ else if( (__n) == 0 && VECTOR_CAPACITY(__vec) ) \
+ { /* clear vector */ \
+ aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* free data */ \
+ VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \
+ VECTOR_LENGTH(__vec) = 0; /* clear length */ \
+ } \
+ else if( (__n) < VECTOR_CAPACITY(__vec) ) \
+ { /* reduce size */ \
+ SET_POINTER(VECTOR_DATA(__vec), aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec)))); /* reallocate */ \
+ VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \
+ if( VECTOR_LENGTH(__vec) > (__n) ) VECTOR_LENGTH(__vec) = (__n); /* update length */ \
+ } \
+ }while(0)
@@ -1113,11 +1112,11 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __n Empty positions
/// @param __step Increase
#define VECTOR_ENSURE(__vec,__n,__step) \
- do{ \
- size_t _empty_ = VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec); \
- while( (__n) > _empty_ ) _empty_ += (__step); \
- if( _empty_ != VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec) ) VECTOR_RESIZE(__vec,_empty_+VECTOR_LENGTH(__vec)); \
- }while(0)
+ do{ \
+ size_t _empty_ = VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec); \
+ while( (__n) > _empty_ ) _empty_ += (__step); \
+ if( _empty_ != VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec) ) VECTOR_RESIZE(__vec,_empty_+VECTOR_LENGTH(__vec)); \
+ }while(0)
@@ -1127,12 +1126,12 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @param __idx Index
#define VECTOR_INSERTZEROED(__vec,__idx) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
- memset(&VECTOR_INDEX(__vec,__idx), 0, sizeof(VECTOR_INDEX(__vec,__idx))); /* set zeroed value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
+ do{ \
+ if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
+ memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
+ memset(&VECTOR_INDEX(__vec,__idx), 0, sizeof(VECTOR_INDEX(__vec,__idx))); /* set zeroed value */ \
+ ++VECTOR_LENGTH(__vec); /* increase length */ \
+ }while(0)
@@ -1143,12 +1142,12 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __idx Index
/// @param __val Value
#define VECTOR_INSERT(__vec,__idx,__val) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
- VECTOR_INDEX(__vec,__idx) = (__val); /* set value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
+ do{ \
+ if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
+ memmove(&VECTOR_INDEX(__vec,(__idx)+1),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
+ VECTOR_INDEX(__vec,__idx) = (__val); /* set value */ \
+ ++VECTOR_LENGTH(__vec); /* increase length */ \
+ }while(0)
@@ -1159,7 +1158,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __idx Index
/// @param __val Value
#define VECTOR_INSERTCOPY(__vec,__idx,__val) \
- VECTOR_INSERTARRAY(__vec,__idx,&(__val),1)
+ VECTOR_INSERTARRAY(__vec,__idx,&(__val),1)
@@ -1171,12 +1170,12 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __pval Array of values
/// @param __n Number of values
#define VECTOR_INSERTARRAY(__vec,__idx,__pval,__n) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,(__idx)+(__n)),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
- memcpy(&VECTOR_INDEX(__vec,__idx), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \
- VECTOR_LENGTH(__vec) += (__n); /* increase length */ \
- }while(0)
+ do{ \
+ if( (__idx) < VECTOR_LENGTH(__vec) ) /* move data */ \
+ memmove(&VECTOR_INDEX(__vec,(__idx)+(__n)),&VECTOR_INDEX(__vec,__idx),(VECTOR_LENGTH(__vec)-(__idx))*sizeof(VECTOR_FIRST(__vec))); \
+ memcpy(&VECTOR_INDEX(__vec,__idx), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \
+ VECTOR_LENGTH(__vec) += (__n); /* increase length */ \
+ }while(0)
@@ -1185,10 +1184,10 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
///
/// @param __vec Vector
#define VECTOR_PUSHZEROED(__vec) \
- do{ \
- memset(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), 0, sizeof(VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)))); /* set zeroed value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
+ do{ \
+ memset(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), 0, sizeof(VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)))); /* set zeroed value */ \
+ ++VECTOR_LENGTH(__vec); /* increase length */ \
+ }while(0)
/// Inserts a value in the end of the vector. (using the '=' operator)
@@ -1197,10 +1196,10 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @param __val Value
#define VECTOR_PUSH(__vec,__val) \
- do{ \
- VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)) = (__val); /* set value */ \
- ++VECTOR_LENGTH(__vec); /* increase length */ \
- }while(0)
+ do{ \
+ VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)) = (__val); /* set value */ \
+ ++VECTOR_LENGTH(__vec); /* increase length */ \
+ }while(0)
@@ -1210,7 +1209,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @param __val Value
#define VECTOR_PUSHCOPY(__vec,__val) \
- VECTOR_PUSHARRAY(__vec,&(__val),1)
+ VECTOR_PUSHARRAY(__vec,&(__val),1)
@@ -1221,10 +1220,10 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __pval Array of values
/// @param __n Number of values
#define VECTOR_PUSHARRAY(__vec,__pval,__n) \
- do{ \
- memcpy(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \
- VECTOR_LENGTH(__vec) += (__n); /* increase length */ \
- }while(0)
+ do{ \
+ memcpy(&VECTOR_INDEX(__vec,VECTOR_LENGTH(__vec)), (__pval), (__n)*sizeof(VECTOR_FIRST(__vec))); /* set values */ \
+ VECTOR_LENGTH(__vec) += (__n); /* increase length */ \
+ }while(0)
@@ -1234,7 +1233,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @return Removed value
#define VECTOR_POP(__vec) \
- ( VECTOR_INDEX(__vec,--VECTOR_LENGTH(__vec)) )
+ ( VECTOR_INDEX(__vec,--VECTOR_LENGTH(__vec)) )
@@ -1245,7 +1244,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __n Number of pops
/// @return Last removed value
#define VECTOR_POPN(__vec,__n) \
- ( VECTOR_INDEX(__vec,(VECTOR_LENGTH(__vec)-=(__n))) )
+ ( VECTOR_INDEX(__vec,(VECTOR_LENGTH(__vec)-=(__n))) )
@@ -1255,7 +1254,7 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __vec Vector
/// @param __idx Index
#define VECTOR_ERASE(__vec,__idx) \
- VECTOR_ERASEN(__vec,__idx,1)
+ VECTOR_ERASEN(__vec,__idx,1)
@@ -1266,11 +1265,11 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __idx Index
/// @param __n Number of values
#define VECTOR_ERASEN(__vec,__idx,__n) \
- do{ \
- if( (__idx) < VECTOR_LENGTH(__vec)-(__n) ) /* move data */ \
- memmove(&VECTOR_INDEX(__vec,__idx),&VECTOR_INDEX(__vec,(__idx)+(__n)),(VECTOR_LENGTH(__vec)-((__idx)+(__n)))*sizeof(VECTOR_FIRST(__vec))); \
- VECTOR_LENGTH(__vec) -= (__n); /* decrease length */ \
- }while(0)
+ do{ \
+ if( (__idx) < VECTOR_LENGTH(__vec)-(__n) ) /* move data */ \
+ memmove(&VECTOR_INDEX(__vec,__idx),&VECTOR_INDEX(__vec,(__idx)+(__n)),(VECTOR_LENGTH(__vec)-((__idx)+(__n)))*sizeof(VECTOR_FIRST(__vec))); \
+ VECTOR_LENGTH(__vec) -= (__n); /* decrease length */ \
+ }while(0)
@@ -1278,14 +1277,14 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
///
/// @param __vec Vector
#define VECTOR_CLEAR(__vec) \
- do{ \
- if( VECTOR_CAPACITY(__vec) ) \
- { \
- aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* clear allocated array */ \
- VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \
- VECTOR_LENGTH(__vec) = 0; /* clear length */ \
- } \
- }while(0)
+ do{ \
+ if( VECTOR_CAPACITY(__vec) ) \
+ { \
+ aFree(VECTOR_DATA(__vec)); VECTOR_DATA(__vec) = NULL; /* clear allocated array */ \
+ VECTOR_CAPACITY(__vec) = 0; /* clear capacity */ \
+ VECTOR_LENGTH(__vec) = 0; /* clear length */ \
+ } \
+ }while(0)
@@ -1388,18 +1387,18 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __val Value
/// @param __topcmp Comparator
#define BHEAP_PUSH(__heap,__val,__topcmp) \
- do{ \
- size_t _i_ = VECTOR_LENGTH(__heap); \
- VECTOR_PUSH(__heap,__val); /* insert at end */ \
- while( _i_ ) \
- { /* restore heap property in parents */ \
- size_t _parent_ = (_i_-1)/2; \
- if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \
- break; /* done */ \
- swap(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \
- _i_ = _parent_; \
- } \
- }while(0)
+ do{ \
+ size_t _i_ = VECTOR_LENGTH(__heap); \
+ VECTOR_PUSH(__heap,__val); /* insert at end */ \
+ while( _i_ ) \
+ { /* restore heap property in parents */ \
+ size_t _parent_ = (_i_-1)/2; \
+ if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \
+ break; /* done */ \
+ swap(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \
+ _i_ = _parent_; \
+ } \
+ }while(0)
@@ -1429,36 +1428,36 @@ void linkdb_foreach( struct linkdb_node** head, LinkDBFunc func, ... );
/// @param __idx Index
/// @param __topcmp Comparator
#define BHEAP_POPINDEX(__heap,__idx,__topcmp) \
- do{ \
- size_t _i_ = __idx; \
- VECTOR_INDEX(__heap,__idx) = VECTOR_POP(__heap); /* put last at index */ \
- while( _i_ ) \
- { /* restore heap property in parents */ \
- size_t _parent_ = (_i_-1)/2; \
- if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \
- break; /* done */ \
- swap(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \
- _i_ = _parent_; \
- } \
- while( _i_ < VECTOR_LENGTH(__heap) ) \
- { /* restore heap property in childs */ \
- size_t _lchild_ = _i_*2 + 1; \
- size_t _rchild_ = _i_*2 + 2; \
- if( (_lchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)) <= 0) && \
- (_rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)) <= 0) ) \
- break; /* done */ \
- else if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) <= 0 ) \
- { /* left child */ \
- swap(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \
- _i_ = _lchild_; \
- } \
- else \
- { /* right child */ \
- swap(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \
- _i_ = _rchild_; \
- } \
- } \
- }while(0)
+ do{ \
+ size_t _i_ = __idx; \
+ VECTOR_INDEX(__heap,__idx) = VECTOR_POP(__heap); /* put last at index */ \
+ while( _i_ ) \
+ { /* restore heap property in parents */ \
+ size_t _parent_ = (_i_-1)/2; \
+ if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)) < 0 ) \
+ break; /* done */ \
+ swap(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i_)); \
+ _i_ = _parent_; \
+ } \
+ while( _i_ < VECTOR_LENGTH(__heap) ) \
+ { /* restore heap property in childs */ \
+ size_t _lchild_ = _i_*2 + 1; \
+ size_t _rchild_ = _i_*2 + 2; \
+ if( (_lchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)) <= 0) && \
+ (_rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)) <= 0) ) \
+ break; /* done */ \
+ else if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) <= 0 ) \
+ { /* left child */ \
+ swap(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \
+ _i_ = _lchild_; \
+ } \
+ else \
+ { /* right child */ \
+ swap(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \
+ _i_ = _rchild_; \
+ } \
+ } \
+ }while(0)
diff --git a/src/common/des.c b/src/common/des.c
index 917fc33e0..f2347f3c4 100644
--- a/src/common/des.c
+++ b/src/common/des.c
@@ -12,207 +12,201 @@
/// Bitmask for accessing individual bits of a byte.
static const uint8_t mask[8] = {
- 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
};
/// Initial permutation (IP).
-static void IP(BIT64* src)
+static void IP(BIT64 *src)
{
- BIT64 tmp = {{0}};
-
- static const uint8_t ip_table[64] = {
- 58, 50, 42, 34, 26, 18, 10, 2,
- 60, 52, 44, 36, 28, 20, 12, 4,
- 62, 54, 46, 38, 30, 22, 14, 6,
- 64, 56, 48, 40, 32, 24, 16, 8,
- 57, 49, 41, 33, 25, 17, 9, 1,
- 59, 51, 43, 35, 27, 19, 11, 3,
- 61, 53, 45, 37, 29, 21, 13, 5,
- 63, 55, 47, 39, 31, 23, 15, 7,
- };
-
- size_t i;
- for( i = 0; i < ARRAYLENGTH(ip_table); ++i )
- {
- uint8_t j = ip_table[i] - 1;
- if( src->b[(j >> 3) & 7] & mask[j & 7] )
- tmp .b[(i >> 3) & 7] |= mask[i & 7];
- }
-
- *src = tmp;
+ BIT64 tmp = {{0}};
+
+ static const uint8_t ip_table[64] = {
+ 58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7,
+ };
+
+ size_t i;
+ for (i = 0; i < ARRAYLENGTH(ip_table); ++i) {
+ uint8_t j = ip_table[i] - 1;
+ if (src->b[(j >> 3) & 7] & mask[j & 7])
+ tmp .b[(i >> 3) & 7] |= mask[i & 7];
+ }
+
+ *src = tmp;
}
/// Final permutation (IP^-1).
-static void FP(BIT64* src)
+static void FP(BIT64 *src)
{
- BIT64 tmp = {{0}};
-
- static const uint8_t fp_table[64] = {
- 40, 8, 48, 16, 56, 24, 64, 32,
- 39, 7, 47, 15, 55, 23, 63, 31,
- 38, 6, 46, 14, 54, 22, 62, 30,
- 37, 5, 45, 13, 53, 21, 61, 29,
- 36, 4, 44, 12, 52, 20, 60, 28,
- 35, 3, 43, 11, 51, 19, 59, 27,
- 34, 2, 42, 10, 50, 18, 58, 26,
- 33, 1, 41, 9, 49, 17, 57, 25,
- };
-
- size_t i;
- for( i = 0; i < ARRAYLENGTH(fp_table); ++i )
- {
- uint8_t j = fp_table[i] - 1;
- if( src->b[(j >> 3) & 7] & mask[j & 7] )
- tmp .b[(i >> 3) & 7] |= mask[i & 7];
- }
-
- *src = tmp;
+ BIT64 tmp = {{0}};
+
+ static const uint8_t fp_table[64] = {
+ 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25,
+ };
+
+ size_t i;
+ for (i = 0; i < ARRAYLENGTH(fp_table); ++i) {
+ uint8_t j = fp_table[i] - 1;
+ if (src->b[(j >> 3) & 7] & mask[j & 7])
+ tmp .b[(i >> 3) & 7] |= mask[i & 7];
+ }
+
+ *src = tmp;
}
/// Expansion (E).
/// Expands upper four 8-bits (32b) into eight 6-bits (48b).
-static void E(BIT64* src)
+static void E(BIT64 *src)
{
- BIT64 tmp = {{0}};
-
-if( false )
-{// original
- static const uint8_t expand_table[48] = {
- 32, 1, 2, 3, 4, 5,
- 4, 5, 6, 7, 8, 9,
- 8, 9, 10, 11, 12, 13,
- 12, 13, 14, 15, 16, 17,
- 16, 17, 18, 19, 20, 21,
- 20, 21, 22, 23, 24, 25,
- 24, 25, 26, 27, 28, 29,
- 28, 29, 30, 31, 32, 1,
- };
-
- size_t i;
- for( i = 0; i < ARRAYLENGTH(expand_table); ++i )
- {
- uint8_t j = expand_table[i] - 1;
- if( src->b[j / 8 + 4] & mask[j % 8] )
- tmp .b[i / 6 + 0] |= mask[i % 6];
- }
-}
-else
-{// optimized
- tmp.b[0] = ((src->b[7]<<5) | (src->b[4]>>3)) & 0x3f; // ..0 vutsr
- tmp.b[1] = ((src->b[4]<<1) | (src->b[5]>>7)) & 0x3f; // ..srqpo n
- tmp.b[2] = ((src->b[4]<<5) | (src->b[5]>>3)) & 0x3f; // ..o nmlkj
- tmp.b[3] = ((src->b[5]<<1) | (src->b[6]>>7)) & 0x3f; // ..kjihg f
- tmp.b[4] = ((src->b[5]<<5) | (src->b[6]>>3)) & 0x3f; // ..g fedcb
- tmp.b[5] = ((src->b[6]<<1) | (src->b[7]>>7)) & 0x3f; // ..cba98 7
- tmp.b[6] = ((src->b[6]<<5) | (src->b[7]>>3)) & 0x3f; // ..8 76543
- tmp.b[7] = ((src->b[7]<<1) | (src->b[4]>>7)) & 0x3f; // ..43210 v
-}
-
- *src = tmp;
+ BIT64 tmp = {{0}};
+
+ if (false) {
+ // original
+ static const uint8_t expand_table[48] = {
+ 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1,
+ };
+
+ size_t i;
+ for (i = 0; i < ARRAYLENGTH(expand_table); ++i) {
+ uint8_t j = expand_table[i] - 1;
+ if (src->b[j / 8 + 4] & mask[j % 8])
+ tmp .b[i / 6 + 0] |= mask[i % 6];
+ }
+ } else {
+ // optimized
+ tmp.b[0] = ((src->b[7]<<5) | (src->b[4]>>3)) & 0x3f; // ..0 vutsr
+ tmp.b[1] = ((src->b[4]<<1) | (src->b[5]>>7)) & 0x3f; // ..srqpo n
+ tmp.b[2] = ((src->b[4]<<5) | (src->b[5]>>3)) & 0x3f; // ..o nmlkj
+ tmp.b[3] = ((src->b[5]<<1) | (src->b[6]>>7)) & 0x3f; // ..kjihg f
+ tmp.b[4] = ((src->b[5]<<5) | (src->b[6]>>3)) & 0x3f; // ..g fedcb
+ tmp.b[5] = ((src->b[6]<<1) | (src->b[7]>>7)) & 0x3f; // ..cba98 7
+ tmp.b[6] = ((src->b[6]<<5) | (src->b[7]>>3)) & 0x3f; // ..8 76543
+ tmp.b[7] = ((src->b[7]<<1) | (src->b[4]>>7)) & 0x3f; // ..43210 v
+ }
+
+ *src = tmp;
}
/// Transposition (P-BOX).
-static void TP(BIT64* src)
+static void TP(BIT64 *src)
{
- BIT64 tmp = {{0}};
-
- static const uint8_t tp_table[32] = {
- 16, 7, 20, 21,
- 29, 12, 28, 17,
- 1, 15, 23, 26,
- 5, 18, 31, 10,
- 2, 8, 24, 14,
- 32, 27, 3, 9,
- 19, 13, 30, 6,
- 22, 11, 4, 25,
- };
-
- size_t i;
- for( i = 0; i < ARRAYLENGTH(tp_table); ++i )
- {
- uint8_t j = tp_table[i] - 1;
- if( src->b[(j >> 3) + 0] & mask[j & 7] )
- tmp .b[(i >> 3) + 4] |= mask[i & 7];
- }
-
- *src = tmp;
+ BIT64 tmp = {{0}};
+
+ static const uint8_t tp_table[32] = {
+ 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25,
+ };
+
+ size_t i;
+ for (i = 0; i < ARRAYLENGTH(tp_table); ++i) {
+ uint8_t j = tp_table[i] - 1;
+ if (src->b[(j >> 3) + 0] & mask[j & 7])
+ tmp .b[(i >> 3) + 4] |= mask[i & 7];
+ }
+
+ *src = tmp;
}
/// Substitution boxes (S-boxes).
/// NOTE: This implementation was optimized to process two nibbles in one step (twice as fast).
-static void SBOX(BIT64* src)
+static void SBOX(BIT64 *src)
{
- BIT64 tmp = {{0}};
-
- static const uint8_t s_table[4][64] = {
- {
- 0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47, 0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e,
- 0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba, 0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85,
- 0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21, 0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72,
- 0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec, 0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9,
- },{
- 0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95, 0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3,
- 0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec, 0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19,
- 0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06, 0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78,
- 0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b, 0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce,
- },{
- 0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2, 0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15,
- 0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae, 0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68,
- 0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c, 0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda,
- 0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97, 0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d,
- },{
- 0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78, 0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4,
- 0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb, 0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62,
- 0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87, 0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d,
- 0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0, 0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb,
- }
- };
-
- size_t i;
- for( i = 0; i < ARRAYLENGTH(s_table); ++i )
- {
- tmp.b[i] = (s_table[i][src->b[i*2+0]] & 0xf0)
- | (s_table[i][src->b[i*2+1]] & 0x0f);
- }
-
- *src = tmp;
+ BIT64 tmp = {{0}};
+
+ static const uint8_t s_table[4][64] = {
+ {
+ 0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47, 0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e,
+ 0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba, 0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85,
+ 0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21, 0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72,
+ 0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec, 0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9,
+ },{
+ 0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95, 0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3,
+ 0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec, 0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19,
+ 0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06, 0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78,
+ 0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b, 0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce,
+ },{
+ 0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2, 0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15,
+ 0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae, 0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68,
+ 0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c, 0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda,
+ 0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97, 0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d,
+ },{
+ 0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78, 0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4,
+ 0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb, 0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62,
+ 0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87, 0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d,
+ 0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0, 0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb,
+ }
+ };
+
+ size_t i;
+ for (i = 0; i < ARRAYLENGTH(s_table); ++i) {
+ tmp.b[i] = (s_table[i][src->b[i*2+0]] & 0xf0)
+ | (s_table[i][src->b[i*2+1]] & 0x0f);
+ }
+
+ *src = tmp;
}
/// DES round function.
/// XORs src[0..3] with TP(SBOX(E(src[4..7]))).
-static void RoundFunction(BIT64* src)
+static void RoundFunction(BIT64 *src)
{
- BIT64 tmp = *src;
- E(&tmp);
- SBOX(&tmp);
- TP(&tmp);
-
- src->b[0] ^= tmp.b[4];
- src->b[1] ^= tmp.b[5];
- src->b[2] ^= tmp.b[6];
- src->b[3] ^= tmp.b[7];
+ BIT64 tmp = *src;
+ E(&tmp);
+ SBOX(&tmp);
+ TP(&tmp);
+
+ src->b[0] ^= tmp.b[4];
+ src->b[1] ^= tmp.b[5];
+ src->b[2] ^= tmp.b[6];
+ src->b[3] ^= tmp.b[7];
}
-void des_decrypt_block(BIT64* block)
+void des_decrypt_block(BIT64 *block)
{
- IP(block);
- RoundFunction(block);
- FP(block);
+ IP(block);
+ RoundFunction(block);
+ FP(block);
}
-void des_decrypt(unsigned char* data, size_t size)
+void des_decrypt(unsigned char *data, size_t size)
{
- BIT64* p = (BIT64*)data;
- size_t i;
+ BIT64 *p = (BIT64 *)data;
+ size_t i;
- for( i = 0; i*8 < size; i += 8 )
- des_decrypt_block(p);
+ for (i = 0; i*8 < size; i += 8)
+ des_decrypt_block(p);
}
diff --git a/src/common/des.h b/src/common/des.h
index e42136436..a13a17165 100644
--- a/src/common/des.h
+++ b/src/common/des.h
@@ -1,15 +1,17 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _DES_H_
-#define _DES_H_
+#ifndef _DES_H_
+#define _DES_H_
/// One 64-bit block.
-typedef struct BIT64 { uint8_t b[8]; } BIT64;
+typedef struct BIT64 {
+ uint8_t b[8];
+} BIT64;
-void des_decrypt_block(BIT64* block);
-void des_decrypt(unsigned char* data, size_t size);
+void des_decrypt_block(BIT64 *block);
+void des_decrypt(unsigned char *data, size_t size);
#endif // _DES_H_
diff --git a/src/common/ers.c b/src/common/ers.c
index b94b0888d..d75f23f6f 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -51,54 +51,51 @@
#define ERS_ROOT_SIZE 256
#define ERS_BLOCK_ENTRIES 4096
-struct ers_list
-{
- struct ers_list *Next;
+struct ers_list {
+ struct ers_list *Next;
};
-typedef struct ers_cache
-{
- // Allocated object size, including ers_list size
- unsigned int ObjectSize;
+typedef struct ers_cache {
+ // Allocated object size, including ers_list size
+ unsigned int ObjectSize;
+
+ // Number of ers_instances referencing this
+ int ReferenceCount;
- // Number of ers_instances referencing this
- int ReferenceCount;
+ // Reuse linked list
+ struct ers_list *ReuseList;
- // Reuse linked list
- struct ers_list *ReuseList;
+ // Memory blocks array
+ unsigned char **Blocks;
- // Memory blocks array
- unsigned char **Blocks;
+ // Max number of blocks
+ unsigned int Max;
- // Max number of blocks
- unsigned int Max;
+ // Free objects count
+ unsigned int Free;
- // Free objects count
- unsigned int Free;
-
- // Used objects count
- unsigned int Used;
+ // Used objects count
+ unsigned int Used;
- // Linked list
- struct ers_cache *Next, *Prev;
+ // Linked list
+ struct ers_cache *Next, *Prev;
} ers_cache_t;
-typedef struct
-{
- // Interface to ERS
- struct eri VTable;
-
- // Name, used for debbuging purpouses
- char *Name;
+typedef struct {
+ // Interface to ERS
+ struct eri VTable;
+
+ // Name, used for debbuging purpouses
+ char *Name;
- // Misc options
- enum ERSOptions Options;
+ // Misc options
+ enum ERSOptions Options;
- // Our cache
- ers_cache_t *Cache;
+ // Our cache
+ ers_cache_t *Cache;
- // Count of objects in use, used for detecting memory leaks
- unsigned int Count;
+ // Count of objects in use, used for detecting memory leaks
+ unsigned int Count;
} ers_instance_t;
@@ -107,186 +104,171 @@ static ers_cache_t *CacheList;
static ers_cache_t *ers_find_cache(unsigned int size)
{
- ers_cache_t *cache;
-
- for (cache = CacheList; cache; cache = cache->Next)
- if (cache->ObjectSize == size)
- return cache;
-
- CREATE(cache, ers_cache_t, 1);
- cache->ObjectSize = size;
- cache->ReferenceCount = 0;
- cache->ReuseList = NULL;
- cache->Blocks = NULL;
- cache->Free = 0;
- cache->Used = 0;
- cache->Max = 0;
-
- if (CacheList == NULL)
- {
- CacheList = cache;
- }
- else
- {
- cache->Next = CacheList;
- cache->Next->Prev = cache;
- CacheList = cache;
- CacheList->Prev = NULL;
- }
-
- return cache;
+ ers_cache_t *cache;
+
+ for (cache = CacheList; cache; cache = cache->Next)
+ if (cache->ObjectSize == size)
+ return cache;
+
+ CREATE(cache, ers_cache_t, 1);
+ cache->ObjectSize = size;
+ cache->ReferenceCount = 0;
+ cache->ReuseList = NULL;
+ cache->Blocks = NULL;
+ cache->Free = 0;
+ cache->Used = 0;
+ cache->Max = 0;
+
+ if (CacheList == NULL) {
+ CacheList = cache;
+ } else {
+ cache->Next = CacheList;
+ cache->Next->Prev = cache;
+ CacheList = cache;
+ CacheList->Prev = NULL;
+ }
+
+ return cache;
}
static void ers_free_cache(ers_cache_t *cache, bool remove)
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; i < cache->Used; i++)
- aFree(cache->Blocks[i]);
+ for (i = 0; i < cache->Used; i++)
+ aFree(cache->Blocks[i]);
- if (cache->Next)
- cache->Next->Prev = cache->Prev;
+ if (cache->Next)
+ cache->Next->Prev = cache->Prev;
- if (cache->Prev)
- cache->Prev->Next = cache->Next;
- else
- CacheList = cache->Next;
+ if (cache->Prev)
+ cache->Prev->Next = cache->Next;
+ else
+ CacheList = cache->Next;
- aFree(cache->Blocks);
- aFree(cache);
+ aFree(cache->Blocks);
+ aFree(cache);
}
static void *ers_obj_alloc_entry(ERS self)
{
- ers_instance_t *instance = (ers_instance_t *)self;
- void *ret;
-
- if (instance == NULL)
- {
- ShowError("ers_obj_alloc_entry: NULL object, aborting entry freeing.\n");
- return NULL;
- }
-
- if (instance->Cache->ReuseList != NULL)
- {
- ret = (void *)((unsigned char *)instance->Cache->ReuseList + sizeof(struct ers_list));
- instance->Cache->ReuseList = instance->Cache->ReuseList->Next;
- }
- else if (instance->Cache->Free > 0)
- {
- instance->Cache->Free--;
- ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
- }
- else
- {
- if (instance->Cache->Used == instance->Cache->Max)
- {
- instance->Cache->Max = (instance->Cache->Max * 4) + 3;
- RECREATE(instance->Cache->Blocks, unsigned char *, instance->Cache->Max);
- }
-
- CREATE(instance->Cache->Blocks[instance->Cache->Used], unsigned char, instance->Cache->ObjectSize * ERS_BLOCK_ENTRIES);
- instance->Cache->Used++;
-
- instance->Cache->Free = ERS_BLOCK_ENTRIES -1;
- ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
- }
-
- instance->Count++;
-
- return ret;
+ ers_instance_t *instance = (ers_instance_t *)self;
+ void *ret;
+
+ if (instance == NULL) {
+ ShowError("ers_obj_alloc_entry: NULL object, aborting entry freeing.\n");
+ return NULL;
+ }
+
+ if (instance->Cache->ReuseList != NULL) {
+ ret = (void *)((unsigned char *)instance->Cache->ReuseList + sizeof(struct ers_list));
+ instance->Cache->ReuseList = instance->Cache->ReuseList->Next;
+ } else if (instance->Cache->Free > 0) {
+ instance->Cache->Free--;
+ ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
+ } else {
+ if (instance->Cache->Used == instance->Cache->Max) {
+ instance->Cache->Max = (instance->Cache->Max * 4) + 3;
+ RECREATE(instance->Cache->Blocks, unsigned char *, instance->Cache->Max);
+ }
+
+ CREATE(instance->Cache->Blocks[instance->Cache->Used], unsigned char, instance->Cache->ObjectSize * ERS_BLOCK_ENTRIES);
+ instance->Cache->Used++;
+
+ instance->Cache->Free = ERS_BLOCK_ENTRIES -1;
+ ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
+ }
+
+ instance->Count++;
+
+ return ret;
}
static void ers_obj_free_entry(ERS self, void *entry)
{
- ers_instance_t *instance = (ers_instance_t *)self;
- struct ers_list *reuse = (struct ers_list *)((unsigned char *)entry - sizeof(struct ers_list));
-
- if (instance == NULL)
- {
- ShowError("ers_obj_free_entry: NULL object, aborting entry freeing.\n");
- return;
- }
- else if (entry == NULL)
- {
- ShowError("ers_obj_free_entry: NULL entry, nothing to free.\n");
- return;
- }
-
- reuse->Next = instance->Cache->ReuseList;
- instance->Cache->ReuseList = reuse;
- instance->Count--;
+ ers_instance_t *instance = (ers_instance_t *)self;
+ struct ers_list *reuse = (struct ers_list *)((unsigned char *)entry - sizeof(struct ers_list));
+
+ if (instance == NULL) {
+ ShowError("ers_obj_free_entry: NULL object, aborting entry freeing.\n");
+ return;
+ } else if (entry == NULL) {
+ ShowError("ers_obj_free_entry: NULL entry, nothing to free.\n");
+ return;
+ }
+
+ reuse->Next = instance->Cache->ReuseList;
+ instance->Cache->ReuseList = reuse;
+ instance->Count--;
}
static size_t ers_obj_entry_size(ERS self)
{
- ers_instance_t *instance = (ers_instance_t *)self;
+ ers_instance_t *instance = (ers_instance_t *)self;
- if (instance == NULL)
- {
- ShowError("ers_obj_entry_size: NULL object, aborting entry freeing.\n");
- return 0;
- }
+ if (instance == NULL) {
+ ShowError("ers_obj_entry_size: NULL object, aborting entry freeing.\n");
+ return 0;
+ }
- return instance->Cache->ObjectSize;
+ return instance->Cache->ObjectSize;
}
static void ers_obj_destroy(ERS self)
{
- ers_instance_t *instance = (ers_instance_t *)self;
+ ers_instance_t *instance = (ers_instance_t *)self;
- if (instance == NULL)
- {
- ShowError("ers_obj_destroy: NULL object, aborting entry freeing.\n");
- return;
- }
+ if (instance == NULL) {
+ ShowError("ers_obj_destroy: NULL object, aborting entry freeing.\n");
+ return;
+ }
- if (instance->Count > 0)
- if (!(instance->Options & ERS_OPT_CLEAR))
- ShowWarning("Memory leak detected at ERS '%s', %d objects not freed.\n", instance->Name, instance->Count);
+ if (instance->Count > 0)
+ if (!(instance->Options & ERS_OPT_CLEAR))
+ ShowWarning("Memory leak detected at ERS '%s', %d objects not freed.\n", instance->Name, instance->Count);
- if (--instance->Cache->ReferenceCount <= 0)
- ers_free_cache(instance->Cache, true);
+ if (--instance->Cache->ReferenceCount <= 0)
+ ers_free_cache(instance->Cache, true);
- aFree(instance);
+ aFree(instance);
}
ERS ers_new(uint32 size, char *name, enum ERSOptions options)
{
- ers_instance_t *instance;
- CREATE(instance, ers_instance_t, 1);
+ ers_instance_t *instance;
+ CREATE(instance, ers_instance_t, 1);
- size += sizeof(struct ers_list);
- if (size % ERS_ALIGNED)
- size += ERS_ALIGNED - size % ERS_ALIGNED;
+ size += sizeof(struct ers_list);
+ if (size % ERS_ALIGNED)
+ size += ERS_ALIGNED - size % ERS_ALIGNED;
- instance->VTable.alloc = ers_obj_alloc_entry;
- instance->VTable.free = ers_obj_free_entry;
- instance->VTable.entry_size = ers_obj_entry_size;
- instance->VTable.destroy = ers_obj_destroy;
+ instance->VTable.alloc = ers_obj_alloc_entry;
+ instance->VTable.free = ers_obj_free_entry;
+ instance->VTable.entry_size = ers_obj_entry_size;
+ instance->VTable.destroy = ers_obj_destroy;
- instance->Name = name;
- instance->Options = options;
+ instance->Name = name;
+ instance->Options = options;
- instance->Cache = ers_find_cache(size);
- instance->Cache->ReferenceCount++;
+ instance->Cache = ers_find_cache(size);
+ instance->Cache->ReferenceCount++;
- instance->Count = 0;
+ instance->Count = 0;
- return &instance->VTable;
+ return &instance->VTable;
}
void ers_report(void)
{
- // FIXME: Someone use this? Is it really needed?
+ // FIXME: Someone use this? Is it really needed?
}
void ers_force_destroy_all(void)
{
- ers_cache_t *cache;
-
- for (cache = CacheList; cache; cache = cache->Next)
- ers_free_cache(cache, false);
+ ers_cache_t *cache;
+
+ for (cache = CacheList; cache; cache = cache->Next)
+ ers_free_cache(cache, false);
}
#endif
diff --git a/src/common/ers.h b/src/common/ers.h
index dc66af5ef..c8fe2b4af 100644
--- a/src/common/ers.h
+++ b/src/common/ers.h
@@ -55,7 +55,7 @@
/**
* Define this to disable the Entry Reusage System.
* All code except the typedef of ERInterface will be disabled.
- * To allow a smooth transition,
+ * To allow a smooth transition,
*/
//#define DISABLE_ERS
@@ -63,16 +63,16 @@
* Entries are aligned to ERS_ALIGNED bytes in the blocks of entries.
* By default it aligns to one byte, using the "natural order" of the entries.
* This should NEVER be set to zero or less.
- * If greater than one, some memory can be wasted. This should never be needed
+ * If greater than one, some memory can be wasted. This should never be needed
* but is here just in case some aligment issues arise.
*/
#ifndef ERS_ALIGNED
-# define ERS_ALIGNED 1
+# define ERS_ALIGNED 1
#endif /* not ERS_ALIGN_ENTRY */
enum ERSOptions {
- ERS_OPT_NONE = 0,
- ERS_OPT_CLEAR = 1,/* silently clears any entries left in the manager upon destruction */
+ ERS_OPT_NONE = 0,
+ ERS_OPT_CLEAR = 1,/* silently clears any entries left in the manager upon destruction */
};
/**
@@ -84,65 +84,65 @@ enum ERSOptions {
*/
typedef struct eri {
- /**
- * Allocate an entry from this entry manager.
- * If there are reusable entries available, it reuses one instead.
- * @param self Interface of the entry manager
- * @return An entry
- */
- void *(*alloc)(struct eri *self);
-
- /**
- * Free an entry allocated from this manager.
- * WARNING: Does not check if the entry was allocated by this manager.
- * Freeing such an entry can lead to unexpected behaviour.
- * @param self Interface of the entry manager
- * @param entry Entry to be freed
- */
- void (*free)(struct eri *self, void *entry);
-
- /**
- * Return the size of the entries allocated from this manager.
- * @param self Interface of the entry manager
- * @return Size of the entries of this manager in bytes
- */
- size_t (*entry_size)(struct eri *self);
-
- /**
- * Destroy this instance of the manager.
- * The manager is actually only destroyed when all the instances are destroyed.
- * When destroying the manager a warning is shown if the manager has
- * missing/extra entries.
- * @param self Interface of the entry manager
- */
- void (*destroy)(struct eri *self);
+ /**
+ * Allocate an entry from this entry manager.
+ * If there are reusable entries available, it reuses one instead.
+ * @param self Interface of the entry manager
+ * @return An entry
+ */
+ void *(*alloc)(struct eri *self);
+
+ /**
+ * Free an entry allocated from this manager.
+ * WARNING: Does not check if the entry was allocated by this manager.
+ * Freeing such an entry can lead to unexpected behaviour.
+ * @param self Interface of the entry manager
+ * @param entry Entry to be freed
+ */
+ void (*free)(struct eri *self, void *entry);
+
+ /**
+ * Return the size of the entries allocated from this manager.
+ * @param self Interface of the entry manager
+ * @return Size of the entries of this manager in bytes
+ */
+ size_t (*entry_size)(struct eri *self);
+
+ /**
+ * Destroy this instance of the manager.
+ * The manager is actually only destroyed when all the instances are destroyed.
+ * When destroying the manager a warning is shown if the manager has
+ * missing/extra entries.
+ * @param self Interface of the entry manager
+ */
+ void (*destroy)(struct eri *self);
} *ERS;
#ifdef DISABLE_ERS
// Use memory manager to allocate/free and disable other interface functions
-# define ers_alloc(obj,type) (type *)aMalloc(sizeof(type))
-# define ers_free(obj,entry) aFree(entry)
-# define ers_entry_size(obj) (size_t)0
-# define ers_destroy(obj)
+# define ers_alloc(obj,type) (type *)aMalloc(sizeof(type))
+# define ers_free(obj,entry) aFree(entry)
+# define ers_entry_size(obj) (size_t)0
+# define ers_destroy(obj)
// Disable the public functions
-# define ers_new(size,name,options) NULL
-# define ers_report()
-# define ers_force_destroy_all()
+# define ers_new(size,name,options) NULL
+# define ers_report()
+# define ers_force_destroy_all()
#else /* not DISABLE_ERS */
-// These defines should be used to allow the code to keep working whenever
+// These defines should be used to allow the code to keep working whenever
// the system is disabled
-# define ers_alloc(obj,type) (type *)(obj)->alloc(obj)
-# define ers_free(obj,entry) (obj)->free((obj),(entry))
-# define ers_entry_size(obj) (obj)->entry_size(obj)
-# define ers_destroy(obj) (obj)->destroy(obj)
+# define ers_alloc(obj,type) (type *)(obj)->alloc(obj)
+# define ers_free(obj,entry) (obj)->free((obj),(entry))
+# define ers_entry_size(obj) (obj)->entry_size(obj)
+# define ers_destroy(obj) (obj)->destroy(obj)
/**
* Get a new instance of the manager that handles the specified entry size.
* Size has to greater than 0.
- * If the specified size is smaller than a pointer, the size of a pointer is
+ * If the specified size is smaller than a pointer, the size of a pointer is
* used instead.
- * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of
+ * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of
* ERS_ALIGNED that is greater or equal to size is what's actually used.
* @param The requested size of the entry in bytes
* @return Interface of the object
@@ -152,7 +152,7 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options);
/**
* Print a report about the current state of the Entry Reusage System.
* Shows information about the global system and each entry manager.
- * The number of entries are checked and a warning is shown if extra reusable
+ * The number of entries are checked and a warning is shown if extra reusable
* entries are found.
* The extra entries are included in the count of reusable entries.
*/
@@ -163,7 +163,7 @@ void ers_report(void);
* The system is left as if no instances or entries had ever been allocated.
* All previous entries and instances of the managers become invalid.
* The use of this is NOT recommended.
- * It should only be used in extreme situations to make shure all the memory
+ * It should only be used in extreme situations to make shure all the memory
* allocated by this system is released.
*/
void ers_force_destroy_all(void);
diff --git a/src/common/evdp.h b/src/common/evdp.h
index bc3454686..c9cff9e2b 100644
--- a/src/common/evdp.h
+++ b/src/common/evdp.h
@@ -8,27 +8,27 @@ typedef struct EVDP_DATA EVDP_DATA;
//#idef EVDP_EPOLL
#include <sys/epoll.h>
-struct EVDP_DATA{
- struct epoll_event ev_data;
- bool ev_added;
+struct EVDP_DATA {
+ struct epoll_event ev_data;
+ bool ev_added;
};
//#endif
-enum EVDP_EVENTFLAGS{
- EVDP_EVENT_IN = 1, // Incomming data
- EVDP_EVENT_OUT = 2, // Connection accepts writing.
- EVDP_EVENT_HUP = 4 // Connection Closed.
+enum EVDP_EVENTFLAGS {
+ EVDP_EVENT_IN = 1, // Incomming data
+ EVDP_EVENT_OUT = 2, // Connection accepts writing.
+ EVDP_EVENT_HUP = 4 // Connection Closed.
};
-typedef struct EVDP_EVENT{
- int32 events; // due to performance reasons, this should be the first member.
- int32 fd; // Connection Identifier
+typedef struct EVDP_EVENT {
+ int32 events; // due to performance reasons, this should be the first member.
+ int32 fd; // Connection Identifier
} EVDP_EVENT;
-/**
+/**
* Network Event Dispatcher Initialization / Finalization routines
*/
void evdp_init();
@@ -38,56 +38,56 @@ void evdp_final();
/**
* Will Wait for events.
*
- * @param *out_ev pointer to array in size at least of max_events.
- * @param max_events max no of events to report with this call (coalesc)
- * @param timeout_ticks max time to wait in ticks (milliseconds)
+ * @param *out_ev pointer to array in size at least of max_events.
+ * @param max_events max no of events to report with this call (coalesc)
+ * @param timeout_ticks max time to wait in ticks (milliseconds)
*
* @Note:
- * The function will block until an event has occured on one of the monitored connections
- * or the timeout of timeout_ticks has passed by.
- * Upon successfull call (changed connections) this function will write the connection
- * Identifier & event to the out_fds array.
+ * The function will block until an event has occured on one of the monitored connections
+ * or the timeout of timeout_ticks has passed by.
+ * Upon successfull call (changed connections) this function will write the connection
+ * Identifier & event to the out_fds array.
*
- * @return 0 -> Timeout, > 0 no of changed connections.
+ * @return 0 -> Timeout, > 0 no of changed connections.
*/
-int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks);
+int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks);
-/**
+/**
* Applys the given mask on the given connection.
- *
- * @param fd connection identifier
- * @param *ep event data pointer for the connection
- * @param mask new event mask we're monitoring for.
+ *
+ * @param fd connection identifier
+ * @param *ep event data pointer for the connection
+ * @param mask new event mask we're monitoring for.
*/
-//void evdp_apply(int32 fd, EVDP_DATA *ep, int32 mask);
+//void evdp_apply(int32 fd, EVDP_DATA *ep, int32 mask);
-/**
+/**
* Adds a connection (listner) to the event notification system.
*
- * @param fd connection identifier
- * @param *ep event data pointer for the connection
+ * @param fd connection identifier
+ * @param *ep event data pointer for the connection
*
- * @note:
- * Listener type sockets are edge triggered, (see epoll manual for more information)
+ * @note:
+ * Listener type sockets are edge triggered, (see epoll manual for more information)
* - This basicaly means that youll receive one event, adn you have to accept until accept returns an error (nothing to accept)
*
* MONITORS by default: IN
- *
+ *
* @return success indicator.
- */
+ */
bool evdp_addlistener(int32 fd, EVDP_DATA *ep);
/**
* Adds a connection (client connectioN) to the event notification system
*
- * @param fd connection identifier
- * @param *ep event data pointr for the connection
- *
+ * @param fd connection identifier
+ * @param *ep event data pointr for the connection
+ *
* @note:
- *
- * MONITORS by default: IN, HUP
+ *
+ * MONITORS by default: IN, HUP
*
* @return success indicator.
*/
@@ -96,17 +96,17 @@ bool evdp_addclient(int32 fd, EVDP_DATA *ep);
/**
* Adds a connection (pending / outgoing connection!) to the event notification system.
*
- * @param fd connection identifier
- * @param *ep event data pointer for the conneciton.
+ * @param fd connection identifier
+ * @param *ep event data pointer for the conneciton.
*
* @note:
- * Outgoing connection type sockets are getting monitored for connection established
- * successfull
- * - if the connection has been established - we're generitng a writable notification .. (send)
- * this is typical for BSD / posix conform network stacks.
- * - Additinionally its edge triggered.
+ * Outgoing connection type sockets are getting monitored for connection established
+ * successfull
+ * - if the connection has been established - we're generitng a writable notification .. (send)
+ * this is typical for BSD / posix conform network stacks.
+ * - Additinionally its edge triggered.
*
- * @see evdp_outgoingconnection_established
+ * @see evdp_outgoingconnection_established
*
*
* @return success indicator
@@ -114,14 +114,14 @@ bool evdp_addclient(int32 fd, EVDP_DATA *ep);
bool evdp_addconnecting(int32 fd, EVDP_DATA *ep);
/**
- * Adds an outgoing connection to the normal event notification system after it has been successfully established.
- *
- * @param fd connection identifier
- * @param *ep event data pointer for the conneciton.
-
- * @note
- * after this call, its handled like a normal "client" connection (incomming)
- *
+ * Adds an outgoing connection to the normal event notification system after it has been successfully established.
+ *
+ * @param fd connection identifier
+ * @param *ep event data pointer for the conneciton.
+
+ * @note
+ * after this call, its handled like a normal "client" connection (incomming)
+ *
* @rturn success indicator
*/
bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep);
@@ -129,24 +129,24 @@ bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep);
/**
* Marks a connection to be monitored for writable.
*
- * @param fd connection identifier
- * @param *ep event data pointer for the connection
+ * @param fd connection identifier
+ * @param *ep event data pointer for the connection
*
* @note:
- * the connection must be already added (as client or listener)
- *
+ * the connection must be already added (as client or listener)
+ *
*
* @return sucess indicator
*/
bool evdp_writable_add(int32 fd, EVDP_DATA *ep);
-/**
+/**
* Removes the connection from writable notification monitoring
*
- * @param fd connection identifier
- * @param *ep event data pointr for the connection
+ * @param fd connection identifier
+ * @param *ep event data pointr for the connection
*
- */
+ */
void evdp_writable_remove(int32 fd, EVDP_DATA *ep);
/**
@@ -157,11 +157,11 @@ void evdp_writable_remove(int32 fd, EVDP_DATA *ep);
*
*
* @note:
- * this will also clear the given EVENT_DATA block
- * so the connection slot is in an "initial" blank status / ready to get reused.
+ * this will also clear the given EVENT_DATA block
+ * so the connection slot is in an "initial" blank status / ready to get reused.
*
*/
-void evdp_remove(int32 fd, EVDP_DATA *ep);
+void evdp_remove(int32 fd, EVDP_DATA *ep);
diff --git a/src/common/evdp_epoll.c b/src/common/evdp_epoll.c
index 0357dfc66..9f7c3d8ea 100644
--- a/src/common/evdp_epoll.c
+++ b/src/common/evdp_epoll.c
@@ -1,5 +1,5 @@
//
-// Event Dispatcher Abstraction for EPOLL
+// Event Dispatcher Abstraction for EPOLL
//
// Author: Florian Wilkemeyer <fw@f-ws.de>
//
@@ -23,210 +23,220 @@
#include "../common/evdp.h"
-#define EPOLL_MAX_PER_CYCLE 10 // Max Events to coalesc. per cycle.
+#define EPOLL_MAX_PER_CYCLE 10 // Max Events to coalesc. per cycle.
static int epoll_fd = -1;
-void evdp_init(){
-
- epoll_fd = epoll_create( EPOLL_MAX_PER_CYCLE );
- if(epoll_fd == -1){
- ShowFatalError("evdp [EPOLL]: Cannot create event dispatcher (errno: %u / %s)\n", errno, strerror(errno) );
- exit(1);
- }
-
+void evdp_init()
+{
+
+ epoll_fd = epoll_create(EPOLL_MAX_PER_CYCLE);
+ if (epoll_fd == -1) {
+ ShowFatalError("evdp [EPOLL]: Cannot create event dispatcher (errno: %u / %s)\n", errno, strerror(errno));
+ exit(1);
+ }
+
}//end: evdp_init()
-void evdp_final(){
-
- if(epoll_fd != -1){
- close(epoll_fd);
- epoll_fd = -1;
- }
-
+void evdp_final()
+{
+
+ if (epoll_fd != -1) {
+ close(epoll_fd);
+ epoll_fd = -1;
+ }
+
}//end: evdp_final()
-int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks){
- struct epoll_event l_events[EPOLL_MAX_PER_CYCLE];
- register struct epoll_event *ev;
- register int nfds, n;
-
- if(max_events > EPOLL_MAX_PER_CYCLE)
- max_events = EPOLL_MAX_PER_CYCLE;
-
- nfds = epoll_wait( epoll_fd, l_events, max_events, timeout_ticks);
- if(nfds == -1){
- // @TODO: check if core is in shutdown mode. if - ignroe error.
-
- ShowFatalError("evdp [EPOLL]: epoll_wait returned bad / unexpected status (errno: %u / %s)\n", errno, strerror(errno));
- exit(1); //..
- }
-
- // Loop thru all events and copy it to the local ra evdp_event.. struct.
- for(n = 0; n < nfds; n++){
- ev = &l_events[n];
-
- out_fds->fd = ev->data.fd;
- out_fds->events = 0; // clear
-
- if(ev->events & EPOLLHUP)
- out_fds->events |= EVDP_EVENT_HUP;
-
- if(ev->events & EPOLLIN)
- out_fds->events |= EVDP_EVENT_IN;
-
- if(ev->events & EPOLLOUT)
- out_fds->events |= EVDP_EVENT_OUT;
-
- out_fds++;
- }
-
- return nfds; // 0 on timeout or > 0 ..
+int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks)
+{
+ struct epoll_event l_events[EPOLL_MAX_PER_CYCLE];
+ register struct epoll_event *ev;
+ register int nfds, n;
+
+ if (max_events > EPOLL_MAX_PER_CYCLE)
+ max_events = EPOLL_MAX_PER_CYCLE;
+
+ nfds = epoll_wait(epoll_fd, l_events, max_events, timeout_ticks);
+ if (nfds == -1) {
+ // @TODO: check if core is in shutdown mode. if - ignroe error.
+
+ ShowFatalError("evdp [EPOLL]: epoll_wait returned bad / unexpected status (errno: %u / %s)\n", errno, strerror(errno));
+ exit(1); //..
+ }
+
+ // Loop thru all events and copy it to the local ra evdp_event.. struct.
+ for (n = 0; n < nfds; n++) {
+ ev = &l_events[n];
+
+ out_fds->fd = ev->data.fd;
+ out_fds->events = 0; // clear
+
+ if (ev->events & EPOLLHUP)
+ out_fds->events |= EVDP_EVENT_HUP;
+
+ if (ev->events & EPOLLIN)
+ out_fds->events |= EVDP_EVENT_IN;
+
+ if (ev->events & EPOLLOUT)
+ out_fds->events |= EVDP_EVENT_OUT;
+
+ out_fds++;
+ }
+
+ return nfds; // 0 on timeout or > 0 ..
}//end: evdp_wait()
-void evdp_remove(int32 fd, EVDP_DATA *ep){
-
- if(ep->ev_added == true){
-
- if( epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep->ev_data) != 0){
- ShowError("evdp [EPOLL]: evdp_remove - epoll_ctl (EPOLL_CTL_DEL) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
- }
-
- ep->ev_data.events = 0; // clear struct.
- ep->ev_data.data.fd = -1; // .. clear struct ..
+void evdp_remove(int32 fd, EVDP_DATA *ep)
+{
+
+ if (ep->ev_added == true) {
+
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep->ev_data) != 0) {
+ ShowError("evdp [EPOLL]: evdp_remove - epoll_ctl (EPOLL_CTL_DEL) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
+ }
+
+ ep->ev_data.events = 0; // clear struct.
+ ep->ev_data.data.fd = -1; // .. clear struct ..
+
+ ep->ev_added = false; // not added!
+ }
- ep->ev_added = false; // not added!
- }
-
}//end: evdp_remove()
-bool evdp_addlistener(int32 fd, EVDP_DATA *ep){
-
- ep->ev_data.events = EPOLLET|EPOLLIN;
- ep->ev_data.data.fd = fd;
-
- // No check here for 'added ?'
- // listeners cannot be added twice.
- //
- if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0 ){
- ShowError("evdp [EPOLL]: evdp_addlistener - epoll_ctl (EPOLL_CTL_ADD) faield! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
- ep->ev_data.events = 0;
- ep->ev_data.data.fd = -1;
- return false;
- }
-
- ep->ev_added = true;
-
- return true;
+bool evdp_addlistener(int32 fd, EVDP_DATA *ep)
+{
+
+ ep->ev_data.events = EPOLLET|EPOLLIN;
+ ep->ev_data.data.fd = fd;
+
+ // No check here for 'added ?'
+ // listeners cannot be added twice.
+ //
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0) {
+ ShowError("evdp [EPOLL]: evdp_addlistener - epoll_ctl (EPOLL_CTL_ADD) faield! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
+ ep->ev_data.events = 0;
+ ep->ev_data.data.fd = -1;
+ return false;
+ }
+
+ ep->ev_added = true;
+
+ return true;
}//end: evdp_addlistener()
-bool evdp_addclient(int32 fd, EVDP_DATA *ep){
-
- ep->ev_data.events = EPOLLIN | EPOLLHUP;
- ep->ev_data.data.fd = fd;
-
- // No check for "added?" here,
- // this function only gets called upon accpept.
- //
-
- if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0){
- ShowError("evdp [EPOLL]: evdp_addclient - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
- ep->ev_data.events = 0;
- ep->ev_data.data.fd = -1;
- return false;
- }
-
- ep->ev_added = true;
-
- return true;
+bool evdp_addclient(int32 fd, EVDP_DATA *ep)
+{
+
+ ep->ev_data.events = EPOLLIN | EPOLLHUP;
+ ep->ev_data.data.fd = fd;
+
+ // No check for "added?" here,
+ // this function only gets called upon accpept.
+ //
+
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0) {
+ ShowError("evdp [EPOLL]: evdp_addclient - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
+ ep->ev_data.events = 0;
+ ep->ev_data.data.fd = -1;
+ return false;
+ }
+
+ ep->ev_added = true;
+
+ return true;
}//end: evdp_addclient()
-bool evdp_addconnecting(int32 fd, EVDP_DATA *ep){
-
- ep->ev_data.events = EPOLLET | EPOLLOUT | EPOLLHUP;
- ep->ev_data.data.fd = fd;
-
- if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0){
- ShowError("evdp [EPOLL]: evdp_addconnecting - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
- ep->ev_data.events = 0;
- ep->ev_data.data.fd = -1;
- }
-
- ep->ev_added = true;
-
- return true;
+bool evdp_addconnecting(int32 fd, EVDP_DATA *ep)
+{
+
+ ep->ev_data.events = EPOLLET | EPOLLOUT | EPOLLHUP;
+ ep->ev_data.data.fd = fd;
+
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0) {
+ ShowError("evdp [EPOLL]: evdp_addconnecting - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
+ ep->ev_data.events = 0;
+ ep->ev_data.data.fd = -1;
+ }
+
+ ep->ev_added = true;
+
+ return true;
}//end: evdp_addconnecting()
-bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep){
- int32 saved_mask;
-
- if(ep->ev_added != true){
- // !
- ShowError("evdp [EPOLL]: evdp_outgoingconnection_established fd #%u is not added to event dispatcher! invalid call.\n", fd);
- return false;
- }
-
- saved_mask = ep->ev_data.events;
-
- ep->ev_data.events = EPOLLIN | EPOLLHUP;
-
- if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0){
- ep->ev_data.events = saved_mask; // restore old mask.
- ShowError("evdp [EPOLL]: evdp_outgoingconnection_established - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
- return false;
- }
-
- return true;
+bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep)
+{
+ int32 saved_mask;
+
+ if (ep->ev_added != true) {
+ // !
+ ShowError("evdp [EPOLL]: evdp_outgoingconnection_established fd #%u is not added to event dispatcher! invalid call.\n", fd);
+ return false;
+ }
+
+ saved_mask = ep->ev_data.events;
+
+ ep->ev_data.events = EPOLLIN | EPOLLHUP;
+
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0) {
+ ep->ev_data.events = saved_mask; // restore old mask.
+ ShowError("evdp [EPOLL]: evdp_outgoingconnection_established - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
+ return false;
+ }
+
+ return true;
}//end: evdp_outgoingconnection_established()
-bool evdp_writable_add(int32 fd, EVDP_DATA *ep){
-
- if(ep->ev_added != true){
- ShowError("evdp [EPOLL]: evdp_writable_add - tried to add not added fd #%u\n",fd);
- return false;
- }
-
- if(! (ep->ev_data.events & EPOLLOUT) ){ //
-
- ep->ev_data.events |= EPOLLOUT;
- if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0 ){
- ShowError("evdp [EPOLL]: evdp_writable_add - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno: %u / %s)\n", fd, errno, strerror(errno));
- ep->ev_data.events &= ~EPOLLOUT; // remove from local flagmask due to failed syscall.
- return false;
- }
- }
-
- return true;
+bool evdp_writable_add(int32 fd, EVDP_DATA *ep)
+{
+
+ if (ep->ev_added != true) {
+ ShowError("evdp [EPOLL]: evdp_writable_add - tried to add not added fd #%u\n",fd);
+ return false;
+ }
+
+ if (!(ep->ev_data.events & EPOLLOUT)) { //
+
+ ep->ev_data.events |= EPOLLOUT;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0) {
+ ShowError("evdp [EPOLL]: evdp_writable_add - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno: %u / %s)\n", fd, errno, strerror(errno));
+ ep->ev_data.events &= ~EPOLLOUT; // remove from local flagmask due to failed syscall.
+ return false;
+ }
+ }
+
+ return true;
}//end: evdp_writable_add()
-void evdp_writable_remove(int32 fd, EVDP_DATA *ep){
-
- if(ep->ev_added != true){
- ShowError("evdp [EPOLL]: evdp_writable_remove - tried to remove not added fd #%u\n", fd);
- return;
- }
-
- if( ep->ev_data.events & EPOLLOUT ){
-
- ep->ev_data.events &= ~EPOLLOUT;
- if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0){
- ShowError("evdp [EPOLL]: evdp_writable_remove - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
- ep->ev_data.events |= EPOLLOUT; // add back to local flagmask because of failed syscall.
- return;
- }
- }
-
- return;
+void evdp_writable_remove(int32 fd, EVDP_DATA *ep)
+{
+
+ if (ep->ev_added != true) {
+ ShowError("evdp [EPOLL]: evdp_writable_remove - tried to remove not added fd #%u\n", fd);
+ return;
+ }
+
+ if (ep->ev_data.events & EPOLLOUT) {
+
+ ep->ev_data.events &= ~EPOLLOUT;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0) {
+ ShowError("evdp [EPOLL]: evdp_writable_remove - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
+ ep->ev_data.events |= EPOLLOUT; // add back to local flagmask because of failed syscall.
+ return;
+ }
+ }
+
+ return;
}//end: evdp_writable_remove()
diff --git a/src/common/grfio.c b/src/common/grfio.c
index 8f430cfb9..f86f9c1cb 100644
--- a/src/common/grfio.c
+++ b/src/common/grfio.c
@@ -16,18 +16,18 @@
#include <zlib.h>
//----------------------------
-// file entry table struct
+// file entry table struct
//----------------------------
typedef struct _FILELIST {
- int srclen; // compressed size
- int srclen_aligned;
- int declen; // original size
- int srcpos; // position of entry in grf
- int next; // index of next filelist entry with same hash (-1: end of entry chain)
- char type;
- char fn[128-4*5]; // file name
- char* fnd; // if the file was cloned, contains name of original file
- char gentry; // read grf file select
+ int srclen; // compressed size
+ int srclen_aligned;
+ int declen; // original size
+ int srcpos; // position of entry in grf
+ int next; // index of next filelist entry with same hash (-1: end of entry chain)
+ char type;
+ char fn[128-4*5]; // file name
+ char *fnd; // if the file was cloned, contains name of original file
+ char gentry; // read grf file select
} FILELIST;
#define FILELIST_TYPE_FILE 0x01 // entry is a file
@@ -45,34 +45,33 @@ typedef struct _FILELIST {
// stores info about every loaded file
-FILELIST* filelist = NULL;
-int filelist_entrys = 0;
-int filelist_maxentry = 0;
+FILELIST *filelist = NULL;
+int filelist_entrys = 0;
+int filelist_maxentry = 0;
// stores grf file names
-char** gentry_table = NULL;
-int gentry_entrys = 0;
-int gentry_maxentry = 0;
+char **gentry_table = NULL;
+int gentry_entrys = 0;
+int gentry_maxentry = 0;
// the path to the data directory
char data_dir[1024] = "";
// little endian char array to uint conversion
-static unsigned int getlong(unsigned char* p)
+static unsigned int getlong(unsigned char *p)
{
- return (p[0] << 0 | p[1] << 8 | p[2] << 16 | p[3] << 24);
+ return (p[0] << 0 | p[1] << 8 | p[2] << 16 | p[3] << 24);
}
-static void NibbleSwap(unsigned char* src, int len)
+static void NibbleSwap(unsigned char *src, int len)
{
- while( len > 0 )
- {
- *src = (*src >> 4) | (*src << 4);
- ++src;
- --len;
- }
+ while (len > 0) {
+ *src = (*src >> 4) | (*src << 4);
+ ++src;
+ --len;
+ }
}
@@ -80,114 +79,142 @@ static void NibbleSwap(unsigned char* src, int len)
/// NOTE: Operation is symmetric (calling it twice gives back the original input).
static uint8_t grf_substitution(uint8_t in)
{
- uint8_t out;
-
- switch( in )
- {
- case 0x00: out = 0x2B; break;
- case 0x2B: out = 0x00; break;
- case 0x6C: out = 0x80; break;
- case 0x01: out = 0x68; break;
- case 0x68: out = 0x01; break;
- case 0x48: out = 0x77; break;
- case 0x60: out = 0xFF; break;
- case 0x77: out = 0x48; break;
- case 0xB9: out = 0xC0; break;
- case 0xC0: out = 0xB9; break;
- case 0xFE: out = 0xEB; break;
- case 0xEB: out = 0xFE; break;
- case 0x80: out = 0x6C; break;
- case 0xFF: out = 0x60; break;
- default: out = in; break;
- }
-
- return out;
+ uint8_t out;
+
+ switch (in) {
+ case 0x00:
+ out = 0x2B;
+ break;
+ case 0x2B:
+ out = 0x00;
+ break;
+ case 0x6C:
+ out = 0x80;
+ break;
+ case 0x01:
+ out = 0x68;
+ break;
+ case 0x68:
+ out = 0x01;
+ break;
+ case 0x48:
+ out = 0x77;
+ break;
+ case 0x60:
+ out = 0xFF;
+ break;
+ case 0x77:
+ out = 0x48;
+ break;
+ case 0xB9:
+ out = 0xC0;
+ break;
+ case 0xC0:
+ out = 0xB9;
+ break;
+ case 0xFE:
+ out = 0xEB;
+ break;
+ case 0xEB:
+ out = 0xFE;
+ break;
+ case 0x80:
+ out = 0x6C;
+ break;
+ case 0xFF:
+ out = 0x60;
+ break;
+ default:
+ out = in;
+ break;
+ }
+
+ return out;
}
/* this is not used anywhere, is it ok to delete? */
//static void grf_shuffle_enc(BIT64* src) {
-// BIT64 out;
+// BIT64 out;
//
-// out.b[0] = src->b[3];
-// out.b[1] = src->b[4];
-// out.b[2] = src->b[5];
-// out.b[3] = src->b[0];
-// out.b[4] = src->b[1];
-// out.b[5] = src->b[6];
-// out.b[6] = src->b[2];
-// out.b[7] = grf_substitution(src->b[7]);
+// out.b[0] = src->b[3];
+// out.b[1] = src->b[4];
+// out.b[2] = src->b[5];
+// out.b[3] = src->b[0];
+// out.b[4] = src->b[1];
+// out.b[5] = src->b[6];
+// out.b[6] = src->b[2];
+// out.b[7] = grf_substitution(src->b[7]);
//
-// *src = out;
+// *src = out;
//}
-static void grf_shuffle_dec(BIT64* src)
+static void grf_shuffle_dec(BIT64 *src)
{
- BIT64 out;
-
- out.b[0] = src->b[3];
- out.b[1] = src->b[4];
- out.b[2] = src->b[6];
- out.b[3] = src->b[0];
- out.b[4] = src->b[1];
- out.b[5] = src->b[2];
- out.b[6] = src->b[5];
- out.b[7] = grf_substitution(src->b[7]);
-
- *src = out;
+ BIT64 out;
+
+ out.b[0] = src->b[3];
+ out.b[1] = src->b[4];
+ out.b[2] = src->b[6];
+ out.b[3] = src->b[0];
+ out.b[4] = src->b[1];
+ out.b[5] = src->b[2];
+ out.b[6] = src->b[5];
+ out.b[7] = grf_substitution(src->b[7]);
+
+ *src = out;
}
-static void grf_decode_header(unsigned char* buf, size_t len)
+static void grf_decode_header(unsigned char *buf, size_t len)
{
- BIT64* p = (BIT64*)buf;
- size_t nblocks = len / sizeof(BIT64);
- size_t i;
+ BIT64 *p = (BIT64 *)buf;
+ size_t nblocks = len / sizeof(BIT64);
+ size_t i;
- // first 20 blocks are all des-encrypted
- for( i = 0; i < 20 && i < nblocks; ++i )
- des_decrypt_block(&p[i]);
+ // first 20 blocks are all des-encrypted
+ for (i = 0; i < 20 && i < nblocks; ++i)
+ des_decrypt_block(&p[i]);
- // the rest is plaintext, done.
+ // the rest is plaintext, done.
}
-static void grf_decode_full(unsigned char* buf, size_t len, int cycle)
+static void grf_decode_full(unsigned char *buf, size_t len, int cycle)
{
- BIT64* p = (BIT64*)buf;
- size_t nblocks = len / sizeof(BIT64);
- int dcycle, scycle;
- size_t i, j;
-
- // first 20 blocks are all des-encrypted
- for( i = 0; i < 20 && i < nblocks; ++i )
- des_decrypt_block(&p[i]);
-
- // after that only one of every 'dcycle' blocks is des-encrypted
- dcycle = cycle;
-
- // and one of every 'scycle' plaintext blocks is shuffled (starting from the 0th but skipping the 0th)
- scycle = 7;
-
- // so decrypt/de-shuffle periodically
- j = -1; // 0, adjusted to fit the ++j step
- for( i = 20; i < nblocks; ++i )
- {
- if( i % dcycle == 0 )
- {// decrypt block
- des_decrypt_block(&p[i]);
- continue;
- }
-
- ++j;
- if( j % scycle == 0 && j != 0 )
- {// de-shuffle block
- grf_shuffle_dec(&p[i]);
- continue;
- }
-
- // plaintext, do nothing.
- }
+ BIT64 *p = (BIT64 *)buf;
+ size_t nblocks = len / sizeof(BIT64);
+ int dcycle, scycle;
+ size_t i, j;
+
+ // first 20 blocks are all des-encrypted
+ for (i = 0; i < 20 && i < nblocks; ++i)
+ des_decrypt_block(&p[i]);
+
+ // after that only one of every 'dcycle' blocks is des-encrypted
+ dcycle = cycle;
+
+ // and one of every 'scycle' plaintext blocks is shuffled (starting from the 0th but skipping the 0th)
+ scycle = 7;
+
+ // so decrypt/de-shuffle periodically
+ j = -1; // 0, adjusted to fit the ++j step
+ for (i = 20; i < nblocks; ++i) {
+ if (i % dcycle == 0) {
+ // decrypt block
+ des_decrypt_block(&p[i]);
+ continue;
+ }
+
+ ++j;
+ if (j % scycle == 0 && j != 0) {
+ // de-shuffle block
+ grf_shuffle_dec(&p[i]);
+ continue;
+ }
+
+ // plaintext, do nothing.
+ }
}
@@ -196,38 +223,35 @@ static void grf_decode_full(unsigned char* buf, size_t len, int cycle)
/// @param len length of the data
/// @param entry_type flags associated with the data
/// @param entry_len true (unaligned) length of the data
-static void grf_decode(unsigned char* buf, size_t len, char entry_type, int entry_len)
+static void grf_decode(unsigned char *buf, size_t len, char entry_type, int entry_len)
{
- if( entry_type & FILELIST_TYPE_ENCRYPT_MIXED )
- {// fully encrypted
- int digits;
- int cycle;
- int i;
-
- // compute number of digits of the entry length
- digits = 1;
- for( i = 10; i <= entry_len; i *= 10 )
- ++digits;
-
- // choose size of gap between two encrypted blocks
- // digits: 0 1 2 3 4 5 6 7 8 9 ...
- // cycle: 1 1 1 4 5 14 15 22 23 24 ...
- cycle = ( digits < 3 ) ? 1
- : ( digits < 5 ) ? digits + 1
- : ( digits < 7 ) ? digits + 9
- : digits + 15;
-
- grf_decode_full(buf, len, cycle);
- }
- else
- if( entry_type & FILELIST_TYPE_ENCRYPT_HEADER )
- {// header encrypted
- grf_decode_header(buf, len);
- }
- else
- {// plaintext
- ;
- }
+ if (entry_type & FILELIST_TYPE_ENCRYPT_MIXED) {
+ // fully encrypted
+ int digits;
+ int cycle;
+ int i;
+
+ // compute number of digits of the entry length
+ digits = 1;
+ for (i = 10; i <= entry_len; i *= 10)
+ ++digits;
+
+ // choose size of gap between two encrypted blocks
+ // digits: 0 1 2 3 4 5 6 7 8 9 ...
+ // cycle: 1 1 1 4 5 14 15 22 23 24 ...
+ cycle = (digits < 3) ? 1
+ : (digits < 5) ? digits + 1
+ : (digits < 7) ? digits + 9
+ : digits + 15;
+
+ grf_decode_full(buf, len, cycle);
+ } else if (entry_type & FILELIST_TYPE_ENCRYPT_HEADER) {
+ // header encrypted
+ grf_decode_header(buf, len);
+ } else {
+ // plaintext
+ ;
+ }
}
@@ -236,23 +260,23 @@ static void grf_decode(unsigned char* buf, size_t len, char entry_type, int entr
******************************************************/
/// zlib crc32
-unsigned long grfio_crc32(const unsigned char* buf, unsigned int len)
+unsigned long grfio_crc32(const unsigned char *buf, unsigned int len)
{
- return crc32(crc32(0L, Z_NULL, 0), buf, len);
+ return crc32(crc32(0L, Z_NULL, 0), buf, len);
}
/// zlib uncompress
-int decode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen)
+int decode_zip(void *dest, unsigned long *destLen, const void *source, unsigned long sourceLen)
{
- return uncompress((Bytef*)dest, destLen, (const Bytef*)source, sourceLen);
+ return uncompress((Bytef *)dest, destLen, (const Bytef *)source, sourceLen);
}
/// zlib compress
-int encode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen)
+int encode_zip(void *dest, unsigned long *destLen, const void *source, unsigned long sourceLen)
{
- return compress((Bytef*)dest, destLen, (const Bytef*)source, sourceLen);
+ return compress((Bytef *)dest, destLen, (const Bytef *)source, sourceLen);
}
@@ -265,94 +289,94 @@ int filelist_hash[256];
// initializes the table that holds the first elements of all hash chains
static void hashinit(void)
{
- int i;
- for (i = 0; i < 256; i++)
- filelist_hash[i] = -1;
+ int i;
+ for (i = 0; i < 256; i++)
+ filelist_hash[i] = -1;
}
// hashes a filename string into a number from {0..255}
-static int filehash(const char* fname)
+static int filehash(const char *fname)
{
- unsigned int hash = 0;
- while(*fname) {
- hash = (hash<<1) + (hash>>7)*9 + TOLOWER(*fname);
- fname++;
- }
- return hash & 255;
+ unsigned int hash = 0;
+ while (*fname) {
+ hash = (hash<<1) + (hash>>7)*9 + TOLOWER(*fname);
+ fname++;
+ }
+ return hash & 255;
}
// finds a FILELIST entry with the specified file name
-static FILELIST* filelist_find(const char* fname)
+static FILELIST *filelist_find(const char *fname)
{
- int hash, index;
+ int hash, index;
- if (!filelist)
- return NULL;
+ if (!filelist)
+ return NULL;
- hash = filelist_hash[filehash(fname)];
- for (index = hash; index != -1; index = filelist[index].next)
- if(!strcmpi(filelist[index].fn, fname))
- break;
+ hash = filelist_hash[filehash(fname)];
+ for (index = hash; index != -1; index = filelist[index].next)
+ if (!strcmpi(filelist[index].fn, fname))
+ break;
- return (index >= 0) ? &filelist[index] : NULL;
+ return (index >= 0) ? &filelist[index] : NULL;
}
// returns the original file name
-char* grfio_find_file(const char* fname)
+char *grfio_find_file(const char *fname)
{
- FILELIST *filelist = filelist_find(fname);
- if (!filelist) return NULL;
- return (!filelist->fnd ? filelist->fn : filelist->fnd);
+ FILELIST *filelist = filelist_find(fname);
+ if (!filelist) return NULL;
+ return (!filelist->fnd ? filelist->fn : filelist->fnd);
}
// adds a FILELIST entry into the list of loaded files
-static FILELIST* filelist_add(FILELIST* entry)
+static FILELIST *filelist_add(FILELIST *entry)
{
- int hash;
+ int hash;
- #define FILELIST_ADDS 1024 // number increment of file lists `
+#define FILELIST_ADDS 1024 // number increment of file lists `
- if (filelist_entrys >= filelist_maxentry) {
- filelist = (FILELIST *)aRealloc(filelist, (filelist_maxentry + FILELIST_ADDS) * sizeof(FILELIST));
- memset(filelist + filelist_maxentry, '\0', FILELIST_ADDS * sizeof(FILELIST));
- filelist_maxentry += FILELIST_ADDS;
- }
+ if (filelist_entrys >= filelist_maxentry) {
+ filelist = (FILELIST *)aRealloc(filelist, (filelist_maxentry + FILELIST_ADDS) * sizeof(FILELIST));
+ memset(filelist + filelist_maxentry, '\0', FILELIST_ADDS * sizeof(FILELIST));
+ filelist_maxentry += FILELIST_ADDS;
+ }
- memcpy (&filelist[filelist_entrys], entry, sizeof(FILELIST));
+ memcpy(&filelist[filelist_entrys], entry, sizeof(FILELIST));
- hash = filehash(entry->fn);
- filelist[filelist_entrys].next = filelist_hash[hash];
- filelist_hash[hash] = filelist_entrys;
+ hash = filehash(entry->fn);
+ filelist[filelist_entrys].next = filelist_hash[hash];
+ filelist_hash[hash] = filelist_entrys;
- filelist_entrys++;
+ filelist_entrys++;
- return &filelist[filelist_entrys - 1];
+ return &filelist[filelist_entrys - 1];
}
// adds a new FILELIST entry or overwrites an existing one
-static FILELIST* filelist_modify(FILELIST* entry)
+static FILELIST *filelist_modify(FILELIST *entry)
{
- FILELIST* fentry = filelist_find(entry->fn);
- if (fentry != NULL) {
- int tmp = fentry->next;
- memcpy(fentry, entry, sizeof(FILELIST));
- fentry->next = tmp;
- } else {
- fentry = filelist_add(entry);
- }
- return fentry;
+ FILELIST *fentry = filelist_find(entry->fn);
+ if (fentry != NULL) {
+ int tmp = fentry->next;
+ memcpy(fentry, entry, sizeof(FILELIST));
+ fentry->next = tmp;
+ } else {
+ fentry = filelist_add(entry);
+ }
+ return fentry;
}
// shrinks the file list array if too long
static void filelist_compact(void)
{
- if (filelist == NULL)
- return;
+ if (filelist == NULL)
+ return;
- if (filelist_entrys < filelist_maxentry) {
- filelist = (FILELIST *)aRealloc(filelist, filelist_entrys * sizeof(FILELIST));
- filelist_maxentry = filelist_entrys;
- }
+ if (filelist_entrys < filelist_maxentry) {
+ filelist = (FILELIST *)aRealloc(filelist, filelist_entrys * sizeof(FILELIST));
+ filelist_maxentry = filelist_entrys;
+ }
}
@@ -362,457 +386,448 @@ static void filelist_compact(void)
/// Combines are resource path with the data folder location to create local resource path.
-static void grfio_localpath_create(char* buffer, size_t size, const char* filename)
+static void grfio_localpath_create(char *buffer, size_t size, const char *filename)
{
- unsigned int i;
- size_t len;
-
- len = strlen(data_dir);
-
- if( data_dir[0] == '\0' || data_dir[len-1] == '/' || data_dir[len-1] == '\\' )
- {
- safesnprintf(buffer, size, "%s%s", data_dir, filename);
- }
- else
- {
- safesnprintf(buffer, size, "%s/%s", data_dir, filename);
- }
-
- // normalize path
- for( i = 0; buffer[i] != '\0'; ++i )
- if( buffer[i] == '\\' )
- buffer[i] = '/';
+ unsigned int i;
+ size_t len;
+
+ len = strlen(data_dir);
+
+ if (data_dir[0] == '\0' || data_dir[len-1] == '/' || data_dir[len-1] == '\\') {
+ safesnprintf(buffer, size, "%s%s", data_dir, filename);
+ } else {
+ safesnprintf(buffer, size, "%s/%s", data_dir, filename);
+ }
+
+ // normalize path
+ for (i = 0; buffer[i] != '\0'; ++i)
+ if (buffer[i] == '\\')
+ buffer[i] = '/';
}
/// Reads a file into a newly allocated buffer (from grf or data directory).
-void* grfio_reads(const char* fname, int* size)
+void *grfio_reads(const char *fname, int *size)
{
- unsigned char* buf2 = NULL;
-
- FILELIST* entry = filelist_find(fname);
- if( entry == NULL || entry->gentry <= 0 ) {// LocalFileCheck
- char lfname[256];
- int declen;
- FILE* in;
- grfio_localpath_create(lfname, sizeof(lfname), ( entry && entry->fnd ) ? entry->fnd : fname);
-
- in = fopen(lfname, "rb");
- if( in != NULL ) {
- fseek(in,0,SEEK_END);
- declen = ftell(in);
- fseek(in,0,SEEK_SET);
- buf2 = (unsigned char *)aMalloc(declen+1); // +1 for resnametable zero-termination
- if(fread(buf2, 1, declen, in) != declen) ShowError("An error occured in fread grfio_reads, fname=%s \n",fname);
- fclose(in);
-
- if( size )
- *size = declen;
- } else {
- if (entry != NULL && entry->gentry < 0) {
- entry->gentry = -entry->gentry; // local file checked
- } else {
- ShowError("grfio_reads: %s not found (local file: %s)\n", fname, lfname);
- return NULL;
- }
- }
- }
-
- if( entry != NULL && entry->gentry > 0 ) {// Archive[GRF] File Read
- char* grfname = gentry_table[entry->gentry - 1];
- FILE* in = fopen(grfname, "rb");
- if( in != NULL ) {
- int fsize = entry->srclen_aligned;
- unsigned char *buf = (unsigned char *)aMalloc(fsize);
- fseek(in, entry->srcpos, 0);
- if(fread(buf, 1, fsize, in) != fsize) ShowError("An error occured in fread in grfio_reads, grfname=%s\n",grfname);
- fclose(in);
-
- buf2 = (unsigned char *)aMalloc(entry->declen+1); // +1 for resnametable zero-termination
- if( entry->type & FILELIST_TYPE_FILE )
- {// file
- uLongf len;
- grf_decode(buf, fsize, entry->type, entry->srclen);
- len = entry->declen;
- decode_zip(buf2, &len, buf, entry->srclen);
- if (len != (uLong)entry->declen) {
- ShowError("decode_zip size mismatch err: %d != %d\n", (int)len, entry->declen);
- aFree(buf);
- aFree(buf2);
- return NULL;
- }
- } else {// directory?
- memcpy(buf2, buf, entry->declen);
- }
-
- if( size )
- *size = entry->declen;
-
- aFree(buf);
- } else {
- ShowError("grfio_reads: %s not found (GRF file: %s)\n", fname, grfname);
- return NULL;
- }
- }
-
- return buf2;
+ unsigned char *buf2 = NULL;
+
+ FILELIST *entry = filelist_find(fname);
+ if (entry == NULL || entry->gentry <= 0) { // LocalFileCheck
+ char lfname[256];
+ int declen;
+ FILE *in;
+ grfio_localpath_create(lfname, sizeof(lfname), (entry && entry->fnd) ? entry->fnd : fname);
+
+ in = fopen(lfname, "rb");
+ if (in != NULL) {
+ fseek(in,0,SEEK_END);
+ declen = ftell(in);
+ fseek(in,0,SEEK_SET);
+ buf2 = (unsigned char *)aMalloc(declen+1); // +1 for resnametable zero-termination
+ if (fread(buf2, 1, declen, in) != declen) ShowError("An error occured in fread grfio_reads, fname=%s \n",fname);
+ fclose(in);
+
+ if (size)
+ *size = declen;
+ } else {
+ if (entry != NULL && entry->gentry < 0) {
+ entry->gentry = -entry->gentry; // local file checked
+ } else {
+ ShowError("grfio_reads: %s not found (local file: %s)\n", fname, lfname);
+ return NULL;
+ }
+ }
+ }
+
+ if (entry != NULL && entry->gentry > 0) { // Archive[GRF] File Read
+ char *grfname = gentry_table[entry->gentry - 1];
+ FILE *in = fopen(grfname, "rb");
+ if (in != NULL) {
+ int fsize = entry->srclen_aligned;
+ unsigned char *buf = (unsigned char *)aMalloc(fsize);
+ fseek(in, entry->srcpos, 0);
+ if (fread(buf, 1, fsize, in) != fsize) ShowError("An error occured in fread in grfio_reads, grfname=%s\n",grfname);
+ fclose(in);
+
+ buf2 = (unsigned char *)aMalloc(entry->declen+1); // +1 for resnametable zero-termination
+ if (entry->type & FILELIST_TYPE_FILE) {
+ // file
+ uLongf len;
+ grf_decode(buf, fsize, entry->type, entry->srclen);
+ len = entry->declen;
+ decode_zip(buf2, &len, buf, entry->srclen);
+ if (len != (uLong)entry->declen) {
+ ShowError("decode_zip size mismatch err: %d != %d\n", (int)len, entry->declen);
+ aFree(buf);
+ aFree(buf2);
+ return NULL;
+ }
+ } else {// directory?
+ memcpy(buf2, buf, entry->declen);
+ }
+
+ if (size)
+ *size = entry->declen;
+
+ aFree(buf);
+ } else {
+ ShowError("grfio_reads: %s not found (GRF file: %s)\n", fname, grfname);
+ return NULL;
+ }
+ }
+
+ return buf2;
}
/// Decodes encrypted filename from a version 01xx grf index.
-static char* decode_filename(unsigned char* buf, int len)
+static char *decode_filename(unsigned char *buf, int len)
{
- int lop;
- for(lop=0;lop<len;lop+=8) {
- NibbleSwap(&buf[lop],8);
- des_decrypt(&buf[lop],8);
- }
- return (char*)buf;
+ int lop;
+ for (lop=0; lop<len; lop+=8) {
+ NibbleSwap(&buf[lop],8);
+ des_decrypt(&buf[lop],8);
+ }
+ return (char *)buf;
}
/// Compares file extension against known large file types.
/// @return true if the file should undergo full mode 0 decryption, and true otherwise.
-static bool isFullEncrypt(const char* fname)
+static bool isFullEncrypt(const char *fname)
{
- static const char extensions[4][5] = { ".gnd", ".gat", ".act", ".str" };
- size_t i;
+ static const char extensions[4][5] = { ".gnd", ".gat", ".act", ".str" };
+ size_t i;
- const char* ext = strrchr(fname, '.');
- if( ext != NULL )
- for( i = 0; i < ARRAYLENGTH(extensions); ++i )
- if( strcmpi(ext, extensions[i]) == 0 )
- return false;
+ const char *ext = strrchr(fname, '.');
+ if (ext != NULL)
+ for (i = 0; i < ARRAYLENGTH(extensions); ++i)
+ if (strcmpi(ext, extensions[i]) == 0)
+ return false;
- return true;
+ return true;
}
/// Loads all entries in the specified grf file into the filelist.
/// @param gentry index of the grf file name in the gentry_table
-static int grfio_entryread(const char* grfname, int gentry)
+static int grfio_entryread(const char *grfname, int gentry)
{
- long grf_size,list_size;
- unsigned char grf_header[0x2e];
- int entry,entrys,ofs,grf_version;
- unsigned char *grf_filelist;
-
- FILE* fp = fopen(grfname, "rb");
- if( fp == NULL ) {
- ShowWarning("GRF data file not found: '%s'\n",grfname);
- return 1; // 1:not found error
- } else
- ShowInfo("GRF data file found: '%s'\n",grfname);
-
- fseek(fp,0,SEEK_END);
- grf_size = ftell(fp);
- fseek(fp,0,SEEK_SET);
-
- if(fread(grf_header,1,0x2e,fp) != 0x2e) { ShowError("Couldn't read all grf_header element of %s \n", grfname); }
- if( strcmp((const char*)grf_header,"Master of Magic") != 0 || fseek(fp,getlong(grf_header+0x1e),SEEK_CUR) != 0 ) {
- fclose(fp);
- ShowError("GRF %s read error\n", grfname);
- return 2; // 2:file format error
- }
-
- grf_version = getlong(grf_header+0x2a) >> 8;
-
- if( grf_version == 0x01 ) {// ****** Grf version 01xx ******
- list_size = grf_size - ftell(fp);
- grf_filelist = (unsigned char *) aMalloc(list_size);
- if(fread(grf_filelist,1,list_size,fp) != list_size) { ShowError("Couldn't read all grf_filelist element of %s \n", grfname); }
- fclose(fp);
-
- entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7;
-
- // Get an entry
- for( entry = 0, ofs = 0; entry < entrys; ++entry ) {
- FILELIST aentry;
-
- int ofs2 = ofs+getlong(grf_filelist+ofs)+4;
- unsigned char type = grf_filelist[ofs2+12];
- if( type & FILELIST_TYPE_FILE ) {
- char* fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6);
- int srclen = getlong(grf_filelist+ofs2+0) - getlong(grf_filelist+ofs2+8) - 715;
-
- if( strlen(fname) > sizeof(aentry.fn) - 1 ) {
- ShowFatalError("GRF file name %s is too long\n", fname);
- aFree(grf_filelist);
- exit(EXIT_FAILURE);
- }
-
- type |= ( isFullEncrypt(fname) ) ? FILELIST_TYPE_ENCRYPT_MIXED : FILELIST_TYPE_ENCRYPT_HEADER;
-
- aentry.srclen = srclen;
- aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579;
- aentry.declen = getlong(grf_filelist+ofs2+8);
- aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e;
- aentry.type = type;
- safestrncpy(aentry.fn, fname, sizeof(aentry.fn));
- aentry.fnd = NULL;
-#ifdef GRFIO_LOCAL
- aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck
+ long grf_size,list_size;
+ unsigned char grf_header[0x2e];
+ int entry,entrys,ofs,grf_version;
+ unsigned char *grf_filelist;
+
+ FILE *fp = fopen(grfname, "rb");
+ if (fp == NULL) {
+ ShowWarning("GRF data file not found: '%s'\n",grfname);
+ return 1; // 1:not found error
+ } else
+ ShowInfo("GRF data file found: '%s'\n",grfname);
+
+ fseek(fp,0,SEEK_END);
+ grf_size = ftell(fp);
+ fseek(fp,0,SEEK_SET);
+
+ if (fread(grf_header,1,0x2e,fp) != 0x2e) {
+ ShowError("Couldn't read all grf_header element of %s \n", grfname);
+ }
+ if (strcmp((const char *)grf_header,"Master of Magic") != 0 || fseek(fp,getlong(grf_header+0x1e),SEEK_CUR) != 0) {
+ fclose(fp);
+ ShowError("GRF %s read error\n", grfname);
+ return 2; // 2:file format error
+ }
+
+ grf_version = getlong(grf_header+0x2a) >> 8;
+
+ if (grf_version == 0x01) { // ****** Grf version 01xx ******
+ list_size = grf_size - ftell(fp);
+ grf_filelist = (unsigned char *) aMalloc(list_size);
+ if (fread(grf_filelist,1,list_size,fp) != list_size) {
+ ShowError("Couldn't read all grf_filelist element of %s \n", grfname);
+ }
+ fclose(fp);
+
+ entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7;
+
+ // Get an entry
+ for (entry = 0, ofs = 0; entry < entrys; ++entry) {
+ FILELIST aentry;
+
+ int ofs2 = ofs+getlong(grf_filelist+ofs)+4;
+ unsigned char type = grf_filelist[ofs2+12];
+ if (type & FILELIST_TYPE_FILE) {
+ char *fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6);
+ int srclen = getlong(grf_filelist+ofs2+0) - getlong(grf_filelist+ofs2+8) - 715;
+
+ if (strlen(fname) > sizeof(aentry.fn) - 1) {
+ ShowFatalError("GRF file name %s is too long\n", fname);
+ aFree(grf_filelist);
+ exit(EXIT_FAILURE);
+ }
+
+ type |= (isFullEncrypt(fname)) ? FILELIST_TYPE_ENCRYPT_MIXED : FILELIST_TYPE_ENCRYPT_HEADER;
+
+ aentry.srclen = srclen;
+ aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579;
+ aentry.declen = getlong(grf_filelist+ofs2+8);
+ aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e;
+ aentry.type = type;
+ safestrncpy(aentry.fn, fname, sizeof(aentry.fn));
+ aentry.fnd = NULL;
+#ifdef GRFIO_LOCAL
+ aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck
#else
- aentry.gentry = gentry+1; // With no first time LocalFileCheck
+ aentry.gentry = gentry+1; // With no first time LocalFileCheck
#endif
- filelist_modify(&aentry);
- }
-
- ofs = ofs2 + 17;
- }
-
- aFree(grf_filelist);
- } else if( grf_version == 0x02 ) {// ****** Grf version 02xx ******
- unsigned char eheader[8];
- unsigned char *rBuf;
- uLongf rSize, eSize;
-
- if(fread(eheader,1,8,fp) != 8) ShowError("An error occured in fread while reading eheader buffer\n");
- rSize = getlong(eheader); // Read Size
- eSize = getlong(eheader+4); // Extend Size
-
- if( (long)rSize > grf_size-ftell(fp) ) {
- fclose(fp);
- ShowError("Illegal data format: GRF compress entry size\n");
- return 4;
- }
-
- rBuf = (unsigned char *)aMalloc(rSize); // Get a Read Size
- grf_filelist = (unsigned char *)aMalloc(eSize); // Get a Extend Size
- if(fread(rBuf,1,rSize,fp) != rSize) ShowError("An error occured in fread \n");
- fclose(fp);
- decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function
- aFree(rBuf);
-
- entrys = getlong(grf_header+0x26) - 7;
-
- // Get an entry
- for( entry = 0, ofs = 0; entry < entrys; ++entry ) {
- FILELIST aentry;
-
- char* fname = (char*)(grf_filelist+ofs);
- int ofs2 = ofs + (int)strlen(fname)+1;
- int type = grf_filelist[ofs2+12];
-
- if( strlen(fname) > sizeof(aentry.fn)-1 ) {
- ShowFatalError("GRF file name %s is too long\n", fname);
- aFree(grf_filelist);
- exit(EXIT_FAILURE);
- }
-
- if( type & FILELIST_TYPE_FILE ) {// file
- aentry.srclen = getlong(grf_filelist+ofs2+0);
- aentry.srclen_aligned = getlong(grf_filelist+ofs2+4);
- aentry.declen = getlong(grf_filelist+ofs2+8);
- aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e;
- aentry.type = type;
- safestrncpy(aentry.fn, fname, sizeof(aentry.fn));
- aentry.fnd = NULL;
-#ifdef GRFIO_LOCAL
- aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck
+ filelist_modify(&aentry);
+ }
+
+ ofs = ofs2 + 17;
+ }
+
+ aFree(grf_filelist);
+ } else if (grf_version == 0x02) { // ****** Grf version 02xx ******
+ unsigned char eheader[8];
+ unsigned char *rBuf;
+ uLongf rSize, eSize;
+
+ if (fread(eheader,1,8,fp) != 8) ShowError("An error occured in fread while reading eheader buffer\n");
+ rSize = getlong(eheader); // Read Size
+ eSize = getlong(eheader+4); // Extend Size
+
+ if ((long)rSize > grf_size-ftell(fp)) {
+ fclose(fp);
+ ShowError("Illegal data format: GRF compress entry size\n");
+ return 4;
+ }
+
+ rBuf = (unsigned char *)aMalloc(rSize); // Get a Read Size
+ grf_filelist = (unsigned char *)aMalloc(eSize); // Get a Extend Size
+ if (fread(rBuf,1,rSize,fp) != rSize) ShowError("An error occured in fread \n");
+ fclose(fp);
+ decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function
+ aFree(rBuf);
+
+ entrys = getlong(grf_header+0x26) - 7;
+
+ // Get an entry
+ for (entry = 0, ofs = 0; entry < entrys; ++entry) {
+ FILELIST aentry;
+
+ char *fname = (char *)(grf_filelist+ofs);
+ int ofs2 = ofs + (int)strlen(fname)+1;
+ int type = grf_filelist[ofs2+12];
+
+ if (strlen(fname) > sizeof(aentry.fn)-1) {
+ ShowFatalError("GRF file name %s is too long\n", fname);
+ aFree(grf_filelist);
+ exit(EXIT_FAILURE);
+ }
+
+ if (type & FILELIST_TYPE_FILE) { // file
+ aentry.srclen = getlong(grf_filelist+ofs2+0);
+ aentry.srclen_aligned = getlong(grf_filelist+ofs2+4);
+ aentry.declen = getlong(grf_filelist+ofs2+8);
+ aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e;
+ aentry.type = type;
+ safestrncpy(aentry.fn, fname, sizeof(aentry.fn));
+ aentry.fnd = NULL;
+#ifdef GRFIO_LOCAL
+ aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck
#else
- aentry.gentry = gentry+1; // With no first time LocalFileCheck
+ aentry.gentry = gentry+1; // With no first time LocalFileCheck
#endif
- filelist_modify(&aentry);
- }
+ filelist_modify(&aentry);
+ }
- ofs = ofs2 + 17;
- }
+ ofs = ofs2 + 17;
+ }
- aFree(grf_filelist);
- } else {// ****** Grf Other version ******
- fclose(fp);
- ShowError("GRF version %04x not supported\n",getlong(grf_header+0x2a));
- return 4;
- }
+ aFree(grf_filelist);
+ } else {// ****** Grf Other version ******
+ fclose(fp);
+ ShowError("GRF version %04x not supported\n",getlong(grf_header+0x2a));
+ return 4;
+ }
- filelist_compact(); // Unnecessary area release of filelist
+ filelist_compact(); // Unnecessary area release of filelist
- return 0; // 0:no error
+ return 0; // 0:no error
}
-static bool grfio_parse_restable_row(const char* row)
+static bool grfio_parse_restable_row(const char *row)
{
- char w1[256], w2[256];
- char src[256], dst[256];
- char local[256];
- FILELIST* entry;
-
- if( sscanf(row, "%[^#\r\n]#%[^#\r\n]#", w1, w2) != 2 )
- return false;
-
- if( strstr(w2, ".gat") == NULL && strstr(w2, ".rsw") == NULL )
- return false; // we only need the maps' GAT and RSW files
-
- sprintf(src, "data\\%s", w1);
- sprintf(dst, "data\\%s", w2);
-
- entry = filelist_find(dst);
- if( entry != NULL )
- {// alias for GRF resource
- FILELIST fentry;
- memcpy(&fentry, entry, sizeof(FILELIST));
- safestrncpy(fentry.fn, src, sizeof(fentry.fn));
- fentry.fnd = aStrdup(dst);
- filelist_modify(&fentry);
- return true;
- }
-
- grfio_localpath_create(local, sizeof(local), dst);
- if( exists(local) )
- {// alias for local resource
- FILELIST fentry;
- memset(&fentry, 0, sizeof(fentry));
- safestrncpy(fentry.fn, src, sizeof(fentry.fn));
- fentry.fnd = aStrdup(dst);
- filelist_modify(&fentry);
- return true;
- }
-
- return false;
+ char w1[256], w2[256];
+ char src[256], dst[256];
+ char local[256];
+ FILELIST *entry;
+
+ if (sscanf(row, "%[^#\r\n]#%[^#\r\n]#", w1, w2) != 2)
+ return false;
+
+ if (strstr(w2, ".gat") == NULL && strstr(w2, ".rsw") == NULL)
+ return false; // we only need the maps' GAT and RSW files
+
+ sprintf(src, "data\\%s", w1);
+ sprintf(dst, "data\\%s", w2);
+
+ entry = filelist_find(dst);
+ if (entry != NULL) {
+ // alias for GRF resource
+ FILELIST fentry;
+ memcpy(&fentry, entry, sizeof(FILELIST));
+ safestrncpy(fentry.fn, src, sizeof(fentry.fn));
+ fentry.fnd = aStrdup(dst);
+ filelist_modify(&fentry);
+ return true;
+ }
+
+ grfio_localpath_create(local, sizeof(local), dst);
+ if (exists(local)) {
+ // alias for local resource
+ FILELIST fentry;
+ memset(&fentry, 0, sizeof(fentry));
+ safestrncpy(fentry.fn, src, sizeof(fentry.fn));
+ fentry.fnd = aStrdup(dst);
+ filelist_modify(&fentry);
+ return true;
+ }
+
+ return false;
}
/// Grfio Resource file check.
static void grfio_resourcecheck(void)
{
- char restable[256];
- char *ptr, *buf;
- int size;
- FILE* fp;
- int i = 0;
-
- // read resnametable from data directory and return if successful
- grfio_localpath_create(restable, sizeof(restable), "data\\resnametable.txt");
-
- fp = fopen(restable, "rb");
- if( fp != NULL )
- {
- char line[256];
- while( fgets(line, sizeof(line), fp) )
- {
- if( grfio_parse_restable_row(line) )
- ++i;
- }
-
- fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, "resnametable.txt");
- return; // we're done here!
- }
-
- // read resnametable from loaded GRF's, only if it cannot be loaded from the data directory
- buf = (char *)grfio_reads("data\\resnametable.txt", &size);
- if( buf != NULL )
- {
- buf[size] = '\0';
-
- ptr = buf;
- while( ptr - buf < size )
- {
- if( grfio_parse_restable_row(ptr) )
- ++i;
-
- ptr = strchr(ptr, '\n');
- if( ptr == NULL ) break;
- ptr++;
- }
-
- aFree(buf);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, "data\\resnametable.txt");
- return;
- }
+ char restable[256];
+ char *ptr, *buf;
+ int size;
+ FILE *fp;
+ int i = 0;
+
+ // read resnametable from data directory and return if successful
+ grfio_localpath_create(restable, sizeof(restable), "data\\resnametable.txt");
+
+ fp = fopen(restable, "rb");
+ if (fp != NULL) {
+ char line[256];
+ while (fgets(line, sizeof(line), fp)) {
+ if (grfio_parse_restable_row(line))
+ ++i;
+ }
+
+ fclose(fp);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, "resnametable.txt");
+ return; // we're done here!
+ }
+
+ // read resnametable from loaded GRF's, only if it cannot be loaded from the data directory
+ buf = (char *)grfio_reads("data\\resnametable.txt", &size);
+ if (buf != NULL) {
+ buf[size] = '\0';
+
+ ptr = buf;
+ while (ptr - buf < size) {
+ if (grfio_parse_restable_row(ptr))
+ ++i;
+
+ ptr = strchr(ptr, '\n');
+ if (ptr == NULL) break;
+ ptr++;
+ }
+
+ aFree(buf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, "data\\resnametable.txt");
+ return;
+ }
}
/// Reads a grf file and adds it to the list.
-static int grfio_add(const char* fname)
+static int grfio_add(const char *fname)
{
- if( gentry_entrys >= gentry_maxentry )
- {
- #define GENTRY_ADDS 4 // The number increment of gentry_table entries
- gentry_maxentry += GENTRY_ADDS;
- gentry_table = (char**)aRealloc(gentry_table, gentry_maxentry * sizeof(char*));
- memset(gentry_table + (gentry_maxentry - GENTRY_ADDS), 0, sizeof(char*) * GENTRY_ADDS);
- }
+ if (gentry_entrys >= gentry_maxentry) {
+#define GENTRY_ADDS 4 // The number increment of gentry_table entries
+ gentry_maxentry += GENTRY_ADDS;
+ gentry_table = (char **)aRealloc(gentry_table, gentry_maxentry * sizeof(char *));
+ memset(gentry_table + (gentry_maxentry - GENTRY_ADDS), 0, sizeof(char *) * GENTRY_ADDS);
+ }
- gentry_table[gentry_entrys++] = aStrdup(fname);
+ gentry_table[gentry_entrys++] = aStrdup(fname);
- return grfio_entryread(fname, gentry_entrys - 1);
+ return grfio_entryread(fname, gentry_entrys - 1);
}
/// Finalizes grfio.
void grfio_final(void)
{
- if (filelist != NULL) {
- int i;
- for (i = 0; i < filelist_entrys; i++)
- if (filelist[i].fnd != NULL)
- aFree(filelist[i].fnd);
-
- aFree(filelist);
- filelist = NULL;
- }
- filelist_entrys = filelist_maxentry = 0;
-
- if (gentry_table != NULL) {
- int i;
- for (i = 0; i < gentry_entrys; i++)
- if (gentry_table[i] != NULL)
- aFree(gentry_table[i]);
-
- aFree(gentry_table);
- gentry_table = NULL;
- }
- gentry_entrys = gentry_maxentry = 0;
+ if (filelist != NULL) {
+ int i;
+ for (i = 0; i < filelist_entrys; i++)
+ if (filelist[i].fnd != NULL)
+ aFree(filelist[i].fnd);
+
+ aFree(filelist);
+ filelist = NULL;
+ }
+ filelist_entrys = filelist_maxentry = 0;
+
+ if (gentry_table != NULL) {
+ int i;
+ for (i = 0; i < gentry_entrys; i++)
+ if (gentry_table[i] != NULL)
+ aFree(gentry_table[i]);
+
+ aFree(gentry_table);
+ gentry_table = NULL;
+ }
+ gentry_entrys = gentry_maxentry = 0;
}
/// Initializes grfio.
-void grfio_init(const char* fname)
+void grfio_init(const char *fname)
{
- FILE* data_conf;
- int grf_num = 0;
-
- hashinit(); // hash table initialization
-
- data_conf = fopen(fname, "r");
- if( data_conf != NULL )
- {
- char line[1024];
- while( fgets(line, sizeof(line), data_conf) )
- {
- char w1[1024], w2[1024];
-
- if( line[0] == '/' && line[1] == '/' )
- continue; // skip comments
-
- if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2 )
- continue; // skip unrecognized lines
-
- // Entry table reading
- if( strcmp(w1, "grf") == 0 ) // GRF file
- {
- if( grfio_add(w2) == 0 )
- ++grf_num;
- }
- else if( strcmp(w1,"data_dir") == 0 ) // Data directory
- {
- safestrncpy(data_dir, w2, sizeof(data_dir));
- }
- }
-
- fclose(data_conf);
- ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", fname);
- }
-
- if( grf_num == 0 )
- ShowInfo("No GRF loaded, using default data directory\n");
-
- // Unneccessary area release of filelist
- filelist_compact();
-
- // Resource check
- grfio_resourcecheck();
+ FILE *data_conf;
+ int grf_num = 0;
+
+ hashinit(); // hash table initialization
+
+ data_conf = fopen(fname, "r");
+ if (data_conf != NULL) {
+ char line[1024];
+ while (fgets(line, sizeof(line), data_conf)) {
+ char w1[1024], w2[1024];
+
+ if (line[0] == '/' && line[1] == '/')
+ continue; // skip comments
+
+ if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+ continue; // skip unrecognized lines
+
+ // Entry table reading
+ if (strcmp(w1, "grf") == 0) { // GRF file
+ if (grfio_add(w2) == 0)
+ ++grf_num;
+ } else if (strcmp(w1,"data_dir") == 0) { // Data directory
+ safestrncpy(data_dir, w2, sizeof(data_dir));
+ }
+ }
+
+ fclose(data_conf);
+ ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", fname);
+ }
+
+ if (grf_num == 0)
+ ShowInfo("No GRF loaded, using default data directory\n");
+
+ // Unneccessary area release of filelist
+ filelist_compact();
+
+ // Resource check
+ grfio_resourcecheck();
}
diff --git a/src/common/grfio.h b/src/common/grfio.h
index c5a56a14e..ae2fbd67c 100644
--- a/src/common/grfio.h
+++ b/src/common/grfio.h
@@ -1,17 +1,17 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _GRFIO_H_
-#define _GRFIO_H_
+#ifndef _GRFIO_H_
+#define _GRFIO_H_
-void grfio_init(const char* fname);
+void grfio_init(const char *fname);
void grfio_final(void);
-void* grfio_reads(const char* fname, int* size);
-char* grfio_find_file(const char* fname);
+void *grfio_reads(const char *fname, int *size);
+char *grfio_find_file(const char *fname);
#define grfio_read(fn) grfio_reads(fn, NULL)
unsigned long grfio_crc32(const unsigned char *buf, unsigned int len);
-int decode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen);
-int encode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen);
+int decode_zip(void *dest, unsigned long *destLen, const void *source, unsigned long sourceLen);
+int encode_zip(void *dest, unsigned long *destLen, const void *source, unsigned long sourceLen);
#endif /* _GRFIO_H_ */
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 9976a28d5..396ec33cb 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -14,109 +14,109 @@
#if defined(MEMWATCH)
-# include <string.h>
-# include "memwatch.h"
-# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line))
-# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line))
-# define REALLOC(p,n,file,line,func) mwRealloc((p),(n),(file),(line))
-# define STRDUP(p,file,line,func) mwStrdup((p),(file),(line))
-# define FREE(p,file,line,func) mwFree((p),(file),(line))
-# define MEMORY_USAGE() 0
-# define MEMORY_VERIFY(ptr) mwIsSafeAddr(ptr, 1)
-# define MEMORY_CHECK() CHECK()
+# include <string.h>
+# include "memwatch.h"
+# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line))
+# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line))
+# define REALLOC(p,n,file,line,func) mwRealloc((p),(n),(file),(line))
+# define STRDUP(p,file,line,func) mwStrdup((p),(file),(line))
+# define FREE(p,file,line,func) mwFree((p),(file),(line))
+# define MEMORY_USAGE() 0
+# define MEMORY_VERIFY(ptr) mwIsSafeAddr(ptr, 1)
+# define MEMORY_CHECK() CHECK()
#elif defined(DMALLOC)
-# include <string.h>
-# include <stdlib.h>
-# include "dmalloc.h"
-# define MALLOC(n,file,line,func) dmalloc_malloc((file),(line),(n),DMALLOC_FUNC_MALLOC,0,0)
-# define CALLOC(m,n,file,line,func) dmalloc_malloc((file),(line),(m)*(n),DMALLOC_FUNC_CALLOC,0,0)
-# define REALLOC(p,n,file,line,func) dmalloc_realloc((file),(line),(p),(n),DMALLOC_FUNC_REALLOC,0)
-# define STRDUP(p,file,line,func) strdup(p)
-# define FREE(p,file,line,func) free(p)
-# define MEMORY_USAGE() dmalloc_memory_allocated()
-# define MEMORY_VERIFY(ptr) (dmalloc_verify(ptr) == DMALLOC_VERIFY_NOERROR)
-# define MEMORY_CHECK() dmalloc_log_stats(); dmalloc_log_unfreed()
+# include <string.h>
+# include <stdlib.h>
+# include "dmalloc.h"
+# define MALLOC(n,file,line,func) dmalloc_malloc((file),(line),(n),DMALLOC_FUNC_MALLOC,0,0)
+# define CALLOC(m,n,file,line,func) dmalloc_malloc((file),(line),(m)*(n),DMALLOC_FUNC_CALLOC,0,0)
+# define REALLOC(p,n,file,line,func) dmalloc_realloc((file),(line),(p),(n),DMALLOC_FUNC_REALLOC,0)
+# define STRDUP(p,file,line,func) strdup(p)
+# define FREE(p,file,line,func) free(p)
+# define MEMORY_USAGE() dmalloc_memory_allocated()
+# define MEMORY_VERIFY(ptr) (dmalloc_verify(ptr) == DMALLOC_VERIFY_NOERROR)
+# define MEMORY_CHECK() dmalloc_log_stats(); dmalloc_log_unfreed()
#elif defined(GCOLLECT)
-# include "gc.h"
-# ifdef GC_ADD_CALLER
-# define RETURN_ADDR 0,
-# else
-# define RETURN_ADDR
-# endif
-# define MALLOC(n,file,line,func) GC_debug_malloc((n), RETURN_ADDR (file),(line))
-# define CALLOC(m,n,file,line,func) GC_debug_malloc((m)*(n), RETURN_ADDR (file),(line))
-# define REALLOC(p,n,file,line,func) GC_debug_realloc((p),(n), RETURN_ADDR (file),(line))
-# define STRDUP(p,file,line,func) GC_debug_strdup((p), RETURN_ADDR (file),(line))
-# define FREE(p,file,line,func) GC_debug_free(p)
-# define MEMORY_USAGE() GC_get_heap_size()
-# define MEMORY_VERIFY(ptr) (GC_base(ptr) != NULL)
-# define MEMORY_CHECK() GC_gcollect()
+# include "gc.h"
+# ifdef GC_ADD_CALLER
+# define RETURN_ADDR 0,
+# else
+# define RETURN_ADDR
+# endif
+# define MALLOC(n,file,line,func) GC_debug_malloc((n), RETURN_ADDR (file),(line))
+# define CALLOC(m,n,file,line,func) GC_debug_malloc((m)*(n), RETURN_ADDR (file),(line))
+# define REALLOC(p,n,file,line,func) GC_debug_realloc((p),(n), RETURN_ADDR (file),(line))
+# define STRDUP(p,file,line,func) GC_debug_strdup((p), RETURN_ADDR (file),(line))
+# define FREE(p,file,line,func) GC_debug_free(p)
+# define MEMORY_USAGE() GC_get_heap_size()
+# define MEMORY_VERIFY(ptr) (GC_base(ptr) != NULL)
+# define MEMORY_CHECK() GC_gcollect()
#else
-# define MALLOC(n,file,line,func) malloc(n)
-# define CALLOC(m,n,file,line,func) calloc((m),(n))
-# define REALLOC(p,n,file,line,func) realloc((p),(n))
-# define STRDUP(p,file,line,func) strdup(p)
-# define FREE(p,file,line,func) free(p)
-# define MEMORY_USAGE() 0
-# define MEMORY_VERIFY(ptr) true
-# define MEMORY_CHECK()
+# define MALLOC(n,file,line,func) malloc(n)
+# define CALLOC(m,n,file,line,func) calloc((m),(n))
+# define REALLOC(p,n,file,line,func) realloc((p),(n))
+# define STRDUP(p,file,line,func) strdup(p)
+# define FREE(p,file,line,func) free(p)
+# define MEMORY_USAGE() 0
+# define MEMORY_VERIFY(ptr) true
+# define MEMORY_CHECK()
#endif
-void* aMalloc_(size_t size, const char *file, int line, const char *func)
+void *aMalloc_(size_t size, const char *file, int line, const char *func)
{
- void *ret = MALLOC(size, file, line, func);
- // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size);
- if (ret == NULL){
- ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func);
- exit(EXIT_FAILURE);
- }
-
- return ret;
+ void *ret = MALLOC(size, file, line, func);
+ // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size);
+ if (ret == NULL) {
+ ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func);
+ exit(EXIT_FAILURE);
+ }
+
+ return ret;
}
-void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func)
+void *aCalloc_(size_t num, size_t size, const char *file, int line, const char *func)
{
- void *ret = CALLOC(num, size, file, line, func);
- // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size);
- if (ret == NULL){
- ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func);
- exit(EXIT_FAILURE);
- }
- return ret;
+ void *ret = CALLOC(num, size, file, line, func);
+ // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size);
+ if (ret == NULL) {
+ ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func);
+ exit(EXIT_FAILURE);
+ }
+ return ret;
}
-void* aRealloc_(void *p, size_t size, const char *file, int line, const char *func)
+void *aRealloc_(void *p, size_t size, const char *file, int line, const char *func)
{
- void *ret = REALLOC(p, size, file, line, func);
- // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size);
- if (ret == NULL){
- ShowFatalError("%s:%d: in func %s: aRealloc error out of memory!\n",file,line,func);
- exit(EXIT_FAILURE);
- }
- return ret;
+ void *ret = REALLOC(p, size, file, line, func);
+ // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size);
+ if (ret == NULL) {
+ ShowFatalError("%s:%d: in func %s: aRealloc error out of memory!\n",file,line,func);
+ exit(EXIT_FAILURE);
+ }
+ return ret;
}
-char* aStrdup_(const char *p, const char *file, int line, const char *func)
+char *aStrdup_(const char *p, const char *file, int line, const char *func)
{
- char *ret = STRDUP(p, file, line, func);
- // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p);
- if (ret == NULL){
- ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func);
- exit(EXIT_FAILURE);
- }
- return ret;
+ char *ret = STRDUP(p, file, line, func);
+ // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p);
+ if (ret == NULL) {
+ ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func);
+ exit(EXIT_FAILURE);
+ }
+ return ret;
}
void aFree_(void *p, const char *file, int line, const char *func)
{
- // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p);
- if (p)
- FREE(p, file, line, func);
+ // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p);
+ if (p)
+ FREE(p, file, line, func);
- p = NULL;
+ p = NULL;
}
@@ -146,405 +146,397 @@ void aFree_(void *p, const char *file, int line, const char *func)
*/
/* ƒuƒƒbƒN‚̃Aƒ‰ƒCƒƒ“ƒg */
-#define BLOCK_ALIGNMENT1 16
-#define BLOCK_ALIGNMENT2 64
+#define BLOCK_ALIGNMENT1 16
+#define BLOCK_ALIGNMENT2 64
/* ƒuƒƒbƒN‚É“ü‚éƒf[ƒ^—Ê */
-#define BLOCK_DATA_COUNT1 128
-#define BLOCK_DATA_COUNT2 608
+#define BLOCK_DATA_COUNT1 128
+#define BLOCK_DATA_COUNT2 608
/* ƒuƒƒbƒN‚Ì‘å‚«‚³: 16*128 + 64*576 = 40KB */
-#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 )
-#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 )
-#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 )
+#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 )
+#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 )
+#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 )
/* ˆê“x‚ÉŠm•Û‚·‚éƒuƒƒbƒN‚Ì”B */
-#define BLOCK_ALLOC 104
+#define BLOCK_ALLOC 104
/* ƒuƒƒbƒN */
struct block {
- struct block* block_next; /* ŽŸ‚ÉŠm•Û‚µ‚½—̈æ */
- struct block* unfill_prev; /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */
- struct block* unfill_next; /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */
- unsigned short unit_size; /* ƒ†ƒjƒbƒg‚Ì‘å‚«‚³ */
- unsigned short unit_hash; /* ƒ†ƒjƒbƒg‚̃nƒbƒVƒ… */
- unsigned short unit_count; /* ƒ†ƒjƒbƒg‚̌” */
- unsigned short unit_used; /* Žg—pƒ†ƒjƒbƒg” */
- unsigned short unit_unfill; /* –¢Žg—pƒ†ƒjƒbƒg‚ÌêŠ */
- unsigned short unit_maxused; /* Žg—pƒ†ƒjƒbƒg‚ÌÅ‘å’l */
- char data[ BLOCK_DATA_SIZE ];
+ struct block *block_next; /* ŽŸ‚ÉŠm•Û‚µ‚½—̈æ */
+ struct block *unfill_prev; /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */
+ struct block *unfill_next; /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */
+ unsigned short unit_size; /* ƒ†ƒjƒbƒg‚Ì‘å‚«‚³ */
+ unsigned short unit_hash; /* ƒ†ƒjƒbƒg‚̃nƒbƒVƒ… */
+ unsigned short unit_count; /* ƒ†ƒjƒbƒg‚̌” */
+ unsigned short unit_used; /* Žg—pƒ†ƒjƒbƒg” */
+ unsigned short unit_unfill; /* –¢Žg—pƒ†ƒjƒbƒg‚ÌêŠ */
+ unsigned short unit_maxused; /* Žg—pƒ†ƒjƒbƒg‚ÌÅ‘å’l */
+ char data[ BLOCK_DATA_SIZE ];
};
struct unit_head {
- struct block *block;
- const char* file;
- unsigned short line;
- unsigned short size;
- long checksum;
+ struct block *block;
+ const char *file;
+ unsigned short line;
+ unsigned short size;
+ long checksum;
};
-static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1];
-static struct block* block_first, *block_last, block_head;
+static struct block *hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1];
+static struct block *block_first, *block_last, block_head;
/* ƒƒ‚ƒŠ‚ðŽg‚¢‰ñ‚¹‚È‚¢—̈æ—p‚̃f[ƒ^ */
struct unit_head_large {
- size_t size;
- struct unit_head_large* prev;
- struct unit_head_large* next;
- struct unit_head unit_head;
+ size_t size;
+ struct unit_head_large *prev;
+ struct unit_head_large *next;
+ struct unit_head unit_head;
};
static struct unit_head_large *unit_head_large_first = NULL;
-static struct block* block_malloc(unsigned short hash);
-static void block_free(struct block* p);
+static struct block *block_malloc(unsigned short hash);
+static void block_free(struct block *p);
static size_t memmgr_usage_bytes;
#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ]))
#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0)
-static unsigned short size2hash( size_t size )
+static unsigned short size2hash(size_t size)
{
- if( size <= BLOCK_DATA_SIZE1 ) {
- return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1;
- } else if( size <= BLOCK_DATA_SIZE ){
- return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2
- + BLOCK_DATA_COUNT1;
- } else {
- return 0xffff; // ƒuƒƒbƒN’·‚ð’´‚¦‚éê‡‚Í hash ‚É‚µ‚È‚¢
- }
+ if (size <= BLOCK_DATA_SIZE1) {
+ return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1;
+ } else if (size <= BLOCK_DATA_SIZE) {
+ return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2
+ + BLOCK_DATA_COUNT1;
+ } else {
+ return 0xffff; // ƒuƒƒbƒN’·‚ð’´‚¦‚éê‡‚Í hash ‚É‚µ‚È‚¢
+ }
}
-static size_t hash2size( unsigned short hash )
+static size_t hash2size(unsigned short hash)
{
- if( hash <= BLOCK_DATA_COUNT1) {
- return hash * BLOCK_ALIGNMENT1;
- } else {
- return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1;
- }
+ if (hash <= BLOCK_DATA_COUNT1) {
+ return hash * BLOCK_ALIGNMENT1;
+ } else {
+ return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1;
+ }
}
-void* _mmalloc(size_t size, const char *file, int line, const char *func )
+void *_mmalloc(size_t size, const char *file, int line, const char *func)
{
- struct block *block;
- short size_hash = size2hash( size );
- struct unit_head *head;
-
- if (((long) size) < 0) {
- ShowError("_mmalloc: %d\n", size);
- return NULL;
- }
-
- if(size == 0) {
- return NULL;
- }
- memmgr_usage_bytes += size;
-
- /* ƒuƒƒbƒN’·‚ð’´‚¦‚é—̈æ‚ÌŠm•Û‚É‚ÍAmalloc() ‚ð—p‚¢‚é */
- /* ‚»‚ÌÛAunit_head.block ‚É NULL ‚ð‘ã“ü‚µ‚Ä‹æ•Ê‚·‚é */
- if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
- struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
- if(p != NULL) {
- p->size = size;
- p->unit_head.block = NULL;
- p->unit_head.size = 0;
- p->unit_head.file = file;
- p->unit_head.line = line;
- p->prev = NULL;
- if (unit_head_large_first == NULL)
- p->next = NULL;
- else {
- unit_head_large_first->prev = p;
- p->next = unit_head_large_first;
- }
- unit_head_large_first = p;
- *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf;
- return (char *)p + sizeof(struct unit_head_large) - sizeof(long);
- } else {
- ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line);
- exit(EXIT_FAILURE);
- }
- }
-
- /* “¯ˆêƒTƒCƒY‚̃uƒƒbƒN‚ªŠm•Û‚³‚ê‚Ä‚¢‚È‚¢ŽžAV‚½‚ÉŠm•Û‚·‚é */
- if(hash_unfill[size_hash]) {
- block = hash_unfill[size_hash];
- } else {
- block = block_malloc(size_hash);
- }
-
- if( block->unit_unfill == 0xFFFF ) {
- // freeςݗ̈悪Žc‚Á‚Ä‚¢‚È‚¢
- memmgr_assert(block->unit_used < block->unit_count);
- memmgr_assert(block->unit_used == block->unit_maxused);
- head = block2unit(block, block->unit_maxused);
- block->unit_used++;
- block->unit_maxused++;
- } else {
- head = block2unit(block, block->unit_unfill);
- block->unit_unfill = head->size;
- block->unit_used++;
- }
-
- if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) {
- // ƒ†ƒjƒbƒg‚ðŽg‚¢‰Ê‚½‚µ‚½‚Ì‚ÅAunfillƒŠƒXƒg‚©‚çíœ
- if( block->unfill_prev == &block_head) {
- hash_unfill[ size_hash ] = block->unfill_next;
- } else {
- block->unfill_prev->unfill_next = block->unfill_next;
- }
- if( block->unfill_next ) {
- block->unfill_next->unfill_prev = block->unfill_prev;
- }
- block->unfill_prev = NULL;
- }
+ struct block *block;
+ short size_hash = size2hash(size);
+ struct unit_head *head;
+
+ if (((long) size) < 0) {
+ ShowError("_mmalloc: %d\n", size);
+ return NULL;
+ }
+
+ if (size == 0) {
+ return NULL;
+ }
+ memmgr_usage_bytes += size;
+
+ /* ƒuƒƒbƒN’·‚ð’´‚¦‚é—̈æ‚ÌŠm•Û‚É‚ÍAmalloc() ‚ð—p‚¢‚é */
+ /* ‚»‚ÌÛAunit_head.block ‚É NULL ‚ð‘ã“ü‚µ‚Ä‹æ•Ê‚·‚é */
+ if (hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
+ struct unit_head_large *p = (struct unit_head_large *)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
+ if (p != NULL) {
+ p->size = size;
+ p->unit_head.block = NULL;
+ p->unit_head.size = 0;
+ p->unit_head.file = file;
+ p->unit_head.line = line;
+ p->prev = NULL;
+ if (unit_head_large_first == NULL)
+ p->next = NULL;
+ else {
+ unit_head_large_first->prev = p;
+ p->next = unit_head_large_first;
+ }
+ unit_head_large_first = p;
+ *(long *)((char *)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf;
+ return (char *)p + sizeof(struct unit_head_large) - sizeof(long);
+ } else {
+ ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* “¯ˆêƒTƒCƒY‚̃uƒƒbƒN‚ªŠm•Û‚³‚ê‚Ä‚¢‚È‚¢ŽžAV‚½‚ÉŠm•Û‚·‚é */
+ if (hash_unfill[size_hash]) {
+ block = hash_unfill[size_hash];
+ } else {
+ block = block_malloc(size_hash);
+ }
+
+ if (block->unit_unfill == 0xFFFF) {
+ // freeςݗ̈悪Žc‚Á‚Ä‚¢‚È‚¢
+ memmgr_assert(block->unit_used < block->unit_count);
+ memmgr_assert(block->unit_used == block->unit_maxused);
+ head = block2unit(block, block->unit_maxused);
+ block->unit_used++;
+ block->unit_maxused++;
+ } else {
+ head = block2unit(block, block->unit_unfill);
+ block->unit_unfill = head->size;
+ block->unit_used++;
+ }
+
+ if (block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) {
+ // ƒ†ƒjƒbƒg‚ðŽg‚¢‰Ê‚½‚µ‚½‚Ì‚ÅAunfillƒŠƒXƒg‚©‚çíœ
+ if (block->unfill_prev == &block_head) {
+ hash_unfill[ size_hash ] = block->unfill_next;
+ } else {
+ block->unfill_prev->unfill_next = block->unfill_next;
+ }
+ if (block->unfill_next) {
+ block->unfill_next->unfill_prev = block->unfill_prev;
+ }
+ block->unfill_prev = NULL;
+ }
#ifdef DEBUG_MEMMGR
- {
- size_t i, sz = hash2size( size_hash );
- for( i=0; i<sz; i++ )
- {
- if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd )
- {
- if( head->line != 0xfdfd )
- {
- ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line);
- }
- else
- {
- ShowError("Memory manager: not-allocated-data is changed.\n");
- }
- break;
- }
- }
- memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz );
- }
+ {
+ size_t i, sz = hash2size(size_hash);
+ for (i=0; i<sz; i++) {
+ if (((unsigned char *)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd) {
+ if (head->line != 0xfdfd) {
+ ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line);
+ } else {
+ ShowError("Memory manager: not-allocated-data is changed.\n");
+ }
+ break;
+ }
+ }
+ memset((char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz);
+ }
#endif
- head->block = block;
- head->file = file;
- head->line = line;
- head->size = (unsigned short)size;
- *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf;
- return (char *)head + sizeof(struct unit_head) - sizeof(long);
+ head->block = block;
+ head->file = file;
+ head->line = line;
+ head->size = (unsigned short)size;
+ *(long *)((char *)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf;
+ return (char *)head + sizeof(struct unit_head) - sizeof(long);
}
-void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func )
+void *_mcalloc(size_t num, size_t size, const char *file, int line, const char *func)
{
- void *p = _mmalloc(num * size,file,line,func);
- memset(p,0,num * size);
- return p;
+ void *p = _mmalloc(num * size,file,line,func);
+ memset(p,0,num * size);
+ return p;
}
-void* _mrealloc(void *memblock, size_t size, const char *file, int line, const char *func )
+void *_mrealloc(void *memblock, size_t size, const char *file, int line, const char *func)
{
- size_t old_size;
- if(memblock == NULL) {
- return _mmalloc(size,file,line,func);
- }
-
- old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size;
- if( old_size == 0 ) {
- old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size;
- }
- if(old_size > size) {
- // ƒTƒCƒYk¬ -> ‚»‚Ì‚Ü‚Ü•Ô‚·iŽè”²‚«j
- return memblock;
- } else {
- // ƒTƒCƒYŠg‘å
- void *p = _mmalloc(size,file,line,func);
- if(p != NULL) {
- memcpy(p,memblock,old_size);
- }
- _mfree(memblock,file,line,func);
- return p;
- }
+ size_t old_size;
+ if (memblock == NULL) {
+ return _mmalloc(size,file,line,func);
+ }
+
+ old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size;
+ if (old_size == 0) {
+ old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size;
+ }
+ if (old_size > size) {
+ // ƒTƒCƒYk¬ -> ‚»‚Ì‚Ü‚Ü•Ô‚·iŽè”²‚«j
+ return memblock;
+ } else {
+ // ƒTƒCƒYŠg‘å
+ void *p = _mmalloc(size,file,line,func);
+ if (p != NULL) {
+ memcpy(p,memblock,old_size);
+ }
+ _mfree(memblock,file,line,func);
+ return p;
+ }
}
-char* _mstrdup(const char *p, const char *file, int line, const char *func )
+char *_mstrdup(const char *p, const char *file, int line, const char *func)
{
- if(p == NULL) {
- return NULL;
- } else {
- size_t len = strlen(p);
- char *string = (char *)_mmalloc(len + 1,file,line,func);
- memcpy(string,p,len+1);
- return string;
- }
+ if (p == NULL) {
+ return NULL;
+ } else {
+ size_t len = strlen(p);
+ char *string = (char *)_mmalloc(len + 1,file,line,func);
+ memcpy(string,p,len+1);
+ return string;
+ }
}
-void _mfree(void *ptr, const char *file, int line, const char *func )
+void _mfree(void *ptr, const char *file, int line, const char *func)
{
- struct unit_head *head;
-
- if (ptr == NULL)
- return;
-
- head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long));
- if(head->size == 0) {
- /* malloc() ‚Å’¼‚ÉŠm•Û‚³‚ꂽ—̈æ */
- struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long));
- if(
- *(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size)
- != 0xdeadbeaf)
- {
- ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
- } else {
- head->size = 0xFFFF;
- if(head_large->prev) {
- head_large->prev->next = head_large->next;
- } else {
- unit_head_large_first = head_large->next;
- }
- if(head_large->next) {
- head_large->next->prev = head_large->prev;
- }
- memmgr_usage_bytes -= head_large->size;
+ struct unit_head *head;
+
+ if (ptr == NULL)
+ return;
+
+ head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long));
+ if (head->size == 0) {
+ /* malloc() ‚Å’¼‚ÉŠm•Û‚³‚ꂽ—̈æ */
+ struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long));
+ if (
+ *(long *)((char *)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size)
+ != 0xdeadbeaf) {
+ ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
+ } else {
+ head->size = 0xFFFF;
+ if (head_large->prev) {
+ head_large->prev->next = head_large->next;
+ } else {
+ unit_head_large_first = head_large->next;
+ }
+ if (head_large->next) {
+ head_large->next->prev = head_large->prev;
+ }
+ memmgr_usage_bytes -= head_large->size;
#ifdef DEBUG_MEMMGR
- // set freed memory to 0xfd
- memset(ptr, 0xfd, head_large->size);
+ // set freed memory to 0xfd
+ memset(ptr, 0xfd, head_large->size);
#endif
- FREE(head_large,file,line,func);
- }
- } else {
- /* ƒ†ƒjƒbƒg‰ð•ú */
- struct block *block = head->block;
- if( (char*)head - (char*)block > sizeof(struct block) ) {
- ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line);
- } else if(head->block == NULL) {
- ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func);
- } else if(*(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) {
- ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
- } else {
- memmgr_usage_bytes -= head->size;
- head->block = NULL;
+ FREE(head_large,file,line,func);
+ }
+ } else {
+ /* ƒ†ƒjƒbƒg‰ð•ú */
+ struct block *block = head->block;
+ if ((char *)head - (char *)block > sizeof(struct block)) {
+ ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line);
+ } else if (head->block == NULL) {
+ ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func);
+ } else if (*(long *)((char *)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) {
+ ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
+ } else {
+ memmgr_usage_bytes -= head->size;
+ head->block = NULL;
#ifdef DEBUG_MEMMGR
- memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long) );
- head->file = file;
- head->line = line;
+ memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long));
+ head->file = file;
+ head->line = line;
#endif
- memmgr_assert( block->unit_used > 0 );
- if(--block->unit_used == 0) {
- /* ƒuƒƒbƒN‚̉ð•ú */
- block_free(block);
- } else {
- if( block->unfill_prev == NULL) {
- // unfill ƒŠƒXƒg‚ɒljÁ
- if( hash_unfill[ block->unit_hash ] ) {
- hash_unfill[ block->unit_hash ]->unfill_prev = block;
- }
- block->unfill_prev = &block_head;
- block->unfill_next = hash_unfill[ block->unit_hash ];
- hash_unfill[ block->unit_hash ] = block;
- }
- head->size = block->unit_unfill;
- block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size);
- }
- }
- }
+ memmgr_assert(block->unit_used > 0);
+ if (--block->unit_used == 0) {
+ /* ƒuƒƒbƒN‚̉ð•ú */
+ block_free(block);
+ } else {
+ if (block->unfill_prev == NULL) {
+ // unfill ƒŠƒXƒg‚ɒljÁ
+ if (hash_unfill[ block->unit_hash ]) {
+ hash_unfill[ block->unit_hash ]->unfill_prev = block;
+ }
+ block->unfill_prev = &block_head;
+ block->unfill_next = hash_unfill[ block->unit_hash ];
+ hash_unfill[ block->unit_hash ] = block;
+ }
+ head->size = block->unit_unfill;
+ block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size);
+ }
+ }
+ }
}
/* ƒuƒƒbƒN‚ðŠm•Û‚·‚é */
-static struct block* block_malloc(unsigned short hash)
-{
- int i;
- struct block *p;
- if(hash_unfill[0] != NULL) {
- /* ƒuƒƒbƒN—p‚̗̈æ‚ÍŠm•ÛÏ‚Ý */
- p = hash_unfill[0];
- hash_unfill[0] = hash_unfill[0]->unfill_next;
- } else {
- /* ƒuƒƒbƒN—p‚̗̈æ‚ðV‚½‚ÉŠm•Û‚·‚é */
- p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ );
- if(p == NULL) {
- ShowFatalError("Memory manager::block_alloc failed.\n");
- exit(EXIT_FAILURE);
- }
-
- if(block_first == NULL) {
- /* ‰‰ñŠm•Û */
- block_first = p;
- } else {
- block_last->block_next = p;
- }
- block_last = &p[BLOCK_ALLOC - 1];
- block_last->block_next = NULL;
- /* ƒuƒƒbƒN‚ð˜AŒ‹‚³‚¹‚é */
- for(i=0;i<BLOCK_ALLOC;i++) {
- if(i != 0) {
- // p[0] ‚Í‚±‚ê‚©‚çŽg‚¤‚̂ŃŠƒ“ƒN‚ɂ͉Á‚¦‚È‚¢
- p[i].unfill_next = hash_unfill[0];
- hash_unfill[0] = &p[i];
- p[i].unfill_prev = NULL;
- p[i].unit_used = 0;
- }
- if(i != BLOCK_ALLOC -1) {
- p[i].block_next = &p[i+1];
- }
- }
- }
-
- // unfill ‚ɒljÁ
- memmgr_assert(hash_unfill[ hash ] == NULL);
- hash_unfill[ hash ] = p;
- p->unfill_prev = &block_head;
- p->unfill_next = NULL;
- p->unit_size = (unsigned short)(hash2size( hash ) + sizeof(struct unit_head));
- p->unit_hash = hash;
- p->unit_count = BLOCK_DATA_SIZE / p->unit_size;
- p->unit_used = 0;
- p->unit_unfill = 0xFFFF;
- p->unit_maxused = 0;
+static struct block *block_malloc(unsigned short hash) {
+ int i;
+ struct block *p;
+ if (hash_unfill[0] != NULL) {
+ /* ƒuƒƒbƒN—p‚̗̈æ‚ÍŠm•ÛÏ‚Ý */
+ p = hash_unfill[0];
+ hash_unfill[0] = hash_unfill[0]->unfill_next;
+ } else {
+ /* ƒuƒƒbƒN—p‚̗̈æ‚ðV‚½‚ÉŠm•Û‚·‚é */
+ p = (struct block *)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__);
+ if (p == NULL) {
+ ShowFatalError("Memory manager::block_alloc failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (block_first == NULL) {
+ /* ‰‰ñŠm•Û */
+ block_first = p;
+ } else {
+ block_last->block_next = p;
+ }
+ block_last = &p[BLOCK_ALLOC - 1];
+ block_last->block_next = NULL;
+ /* ƒuƒƒbƒN‚ð˜AŒ‹‚³‚¹‚é */
+ for (i=0; i<BLOCK_ALLOC; i++) {
+ if (i != 0) {
+ // p[0] ‚Í‚±‚ê‚©‚çŽg‚¤‚̂ŃŠƒ“ƒN‚ɂ͉Á‚¦‚È‚¢
+ p[i].unfill_next = hash_unfill[0];
+ hash_unfill[0] = &p[i];
+ p[i].unfill_prev = NULL;
+ p[i].unit_used = 0;
+ }
+ if (i != BLOCK_ALLOC -1) {
+ p[i].block_next = &p[i+1];
+ }
+ }
+ }
+
+ // unfill ‚ɒljÁ
+ memmgr_assert(hash_unfill[ hash ] == NULL);
+ hash_unfill[ hash ] = p;
+ p->unfill_prev = &block_head;
+ p->unfill_next = NULL;
+ p->unit_size = (unsigned short)(hash2size(hash) + sizeof(struct unit_head));
+ p->unit_hash = hash;
+ p->unit_count = BLOCK_DATA_SIZE / p->unit_size;
+ p->unit_used = 0;
+ p->unit_unfill = 0xFFFF;
+ p->unit_maxused = 0;
#ifdef DEBUG_MEMMGR
- memset( p->data, 0xfd, sizeof(p->data) );
+ memset(p->data, 0xfd, sizeof(p->data));
#endif
- return p;
+ return p;
}
-static void block_free(struct block* p)
+static void block_free(struct block *p)
{
- if( p->unfill_prev ) {
- if( p->unfill_prev == &block_head) {
- hash_unfill[ p->unit_hash ] = p->unfill_next;
- } else {
- p->unfill_prev->unfill_next = p->unfill_next;
- }
- if( p->unfill_next ) {
- p->unfill_next->unfill_prev = p->unfill_prev;
- }
- p->unfill_prev = NULL;
- }
-
- p->unfill_next = hash_unfill[0];
- hash_unfill[0] = p;
+ if (p->unfill_prev) {
+ if (p->unfill_prev == &block_head) {
+ hash_unfill[ p->unit_hash ] = p->unfill_next;
+ } else {
+ p->unfill_prev->unfill_next = p->unfill_next;
+ }
+ if (p->unfill_next) {
+ p->unfill_next->unfill_prev = p->unfill_prev;
+ }
+ p->unfill_prev = NULL;
+ }
+
+ p->unfill_next = hash_unfill[0];
+ hash_unfill[0] = p;
}
-size_t memmgr_usage (void)
+size_t memmgr_usage(void)
{
- return memmgr_usage_bytes / 1024;
+ return memmgr_usage_bytes / 1024;
}
#ifdef LOG_MEMMGR
static char memmer_logfile[128];
static FILE *log_fp;
-static void memmgr_log (char *buf)
+static void memmgr_log(char *buf)
{
- if( !log_fp )
- {
- time_t raw;
- struct tm* t;
-
- log_fp = fopen(memmer_logfile,"at");
- if (!log_fp) log_fp = stdout;
-
- time(&raw);
- t = localtime(&raw);
- fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n",
- (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision());
- }
- fprintf(log_fp, "%s", buf);
- return;
+ if (!log_fp) {
+ time_t raw;
+ struct tm *t;
+
+ log_fp = fopen(memmer_logfile,"at");
+ if (!log_fp) log_fp = stdout;
+
+ time(&raw);
+ t = localtime(&raw);
+ fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n",
+ (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision());
+ }
+ fprintf(log_fp, "%s", buf);
+ return;
}
#endif /* LOG_MEMMGR */
@@ -553,107 +545,105 @@ static void memmgr_log (char *buf)
///
/// @param ptr Pointer to the memory
/// @return true if the memory is active
-bool memmgr_verify(void* ptr)
+bool memmgr_verify(void *ptr)
{
- struct block* block = block_first;
- struct unit_head_large* large = unit_head_large_first;
-
- if( ptr == NULL )
- return false;// never valid
-
- // search small blocks
- while( block )
- {
- if( (char*)ptr >= (char*)block && (char*)ptr < ((char*)block) + sizeof(struct block) )
- {// found memory block
- if( block->unit_used && (char*)ptr >= block->data )
- {// memory block is being used and ptr points to a sub-unit
- size_t i = (size_t)((char*)ptr - block->data)/block->unit_size;
- struct unit_head* head = block2unit(block, i);
- if( i < block->unit_maxused && head->block != NULL )
- {// memory unit is allocated, check if ptr points to the usable part
- return ( (char*)ptr >= ((char*)head) + sizeof(struct unit_head) - sizeof(long)
- && (char*)ptr < ((char*)head) + sizeof(struct unit_head) - sizeof(long) + head->size );
- }
- }
- return false;
- }
- block = block->block_next;
- }
-
- // search large blocks
- while( large )
- {
- if( (char*)ptr >= (char*)large && (char*)ptr < ((char*)large) + large->size )
- {// found memory block, check if ptr points to the usable part
- return ( (char*)ptr >= ((char*)large) + sizeof(struct unit_head_large) - sizeof(long)
- && (char*)ptr < ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size );
- }
- large = large->next;
- }
- return false;
+ struct block *block = block_first;
+ struct unit_head_large *large = unit_head_large_first;
+
+ if (ptr == NULL)
+ return false;// never valid
+
+ // search small blocks
+ while (block) {
+ if ((char *)ptr >= (char *)block && (char *)ptr < ((char *)block) + sizeof(struct block)) {
+ // found memory block
+ if (block->unit_used && (char *)ptr >= block->data) {
+ // memory block is being used and ptr points to a sub-unit
+ size_t i = (size_t)((char *)ptr - block->data)/block->unit_size;
+ struct unit_head *head = block2unit(block, i);
+ if (i < block->unit_maxused && head->block != NULL) {
+ // memory unit is allocated, check if ptr points to the usable part
+ return ((char *)ptr >= ((char *)head) + sizeof(struct unit_head) - sizeof(long)
+ && (char *)ptr < ((char *)head) + sizeof(struct unit_head) - sizeof(long) + head->size);
+ }
+ }
+ return false;
+ }
+ block = block->block_next;
+ }
+
+ // search large blocks
+ while (large) {
+ if ((char *)ptr >= (char *)large && (char *)ptr < ((char *)large) + large->size) {
+ // found memory block, check if ptr points to the usable part
+ return ((char *)ptr >= ((char *)large) + sizeof(struct unit_head_large) - sizeof(long)
+ && (char *)ptr < ((char *)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size);
+ }
+ large = large->next;
+ }
+ return false;
}
-static void memmgr_final (void)
+static void memmgr_final(void)
{
- struct block *block = block_first;
- struct unit_head_large *large = unit_head_large_first;
+ struct block *block = block_first;
+ struct unit_head_large *large = unit_head_large_first;
#ifdef LOG_MEMMGR
- int count = 0;
+ int count = 0;
#endif /* LOG_MEMMGR */
- while (block) {
- if (block->unit_used) {
- int i;
- for (i = 0; i < block->unit_maxused; i++) {
- struct unit_head *head = block2unit(block, i);
- if(head->block != NULL) {
- char* ptr = (char *)head + sizeof(struct unit_head) - sizeof(long);
+ while (block) {
+ if (block->unit_used) {
+ int i;
+ for (i = 0; i < block->unit_maxused; i++) {
+ struct unit_head *head = block2unit(block, i);
+ if (head->block != NULL) {
+ char *ptr = (char *)head + sizeof(struct unit_head) - sizeof(long);
#ifdef LOG_MEMMGR
- char buf[1024];
- sprintf (buf,
- "%04d : %s line %d size %lu address 0x%p\n", ++count,
- head->file, head->line, (unsigned long)head->size, ptr);
- memmgr_log (buf);
+ char buf[1024];
+ sprintf(buf,
+ "%04d : %s line %d size %lu address 0x%p\n", ++count,
+ head->file, head->line, (unsigned long)head->size, ptr);
+ memmgr_log(buf);
#endif /* LOG_MEMMGR */
- // get block pointer and free it [celest]
- _mfree(ptr, ALC_MARK);
- }
- }
- }
- block = block->block_next;
- }
-
- while(large) {
- struct unit_head_large *large2;
+ // get block pointer and free it [celest]
+ _mfree(ptr, ALC_MARK);
+ }
+ }
+ }
+ block = block->block_next;
+ }
+
+ while (large) {
+ struct unit_head_large *large2;
#ifdef LOG_MEMMGR
- char buf[1024];
- sprintf (buf,
- "%04d : %s line %d size %lu address 0x%p\n", ++count,
- large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum);
- memmgr_log (buf);
+ char buf[1024];
+ sprintf(buf,
+ "%04d : %s line %d size %lu address 0x%p\n", ++count,
+ large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum);
+ memmgr_log(buf);
#endif /* LOG_MEMMGR */
- large2 = large->next;
- FREE(large,file,line,func);
- large = large2;
- }
+ large2 = large->next;
+ FREE(large,file,line,func);
+ large = large2;
+ }
#ifdef LOG_MEMMGR
- if(count == 0) {
- ShowInfo("Memory manager: No memory leaks found.\n");
- } else {
- ShowWarning("Memory manager: Memory leaks found and fixed.\n");
- fclose(log_fp);
- }
+ if (count == 0) {
+ ShowInfo("Memory manager: No memory leaks found.\n");
+ } else {
+ ShowWarning("Memory manager: Memory leaks found and fixed.\n");
+ fclose(log_fp);
+ }
#endif /* LOG_MEMMGR */
}
-static void memmgr_init (void)
+static void memmgr_init(void)
{
#ifdef LOG_MEMMGR
- sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME);
- ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
- memset(hash_unfill, 0, sizeof(hash_unfill));
+ sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME);
+ ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
+ memset(hash_unfill, 0, sizeof(hash_unfill));
#endif /* LOG_MEMMGR */
}
#endif /* USE_MEMMGR */
@@ -668,51 +658,51 @@ static void memmgr_init (void)
/// Tests the memory for errors and memory leaks.
void malloc_memory_check(void)
{
- MEMORY_CHECK();
+ MEMORY_CHECK();
}
/// Returns true if a pointer is valid.
/// The check is best-effort, false positives are possible.
-bool malloc_verify_ptr(void* ptr)
+bool malloc_verify_ptr(void *ptr)
{
#ifdef USE_MEMMGR
- return memmgr_verify(ptr) && MEMORY_VERIFY(ptr);
+ return memmgr_verify(ptr) && MEMORY_VERIFY(ptr);
#else
- return MEMORY_VERIFY(ptr);
+ return MEMORY_VERIFY(ptr);
#endif
}
-size_t malloc_usage (void)
+size_t malloc_usage(void)
{
#ifdef USE_MEMMGR
- return memmgr_usage ();
+ return memmgr_usage();
#else
- return MEMORY_USAGE();
+ return MEMORY_USAGE();
#endif
}
-void malloc_final (void)
+void malloc_final(void)
{
#ifdef USE_MEMMGR
- memmgr_final ();
+ memmgr_final();
#endif
- MEMORY_CHECK();
+ MEMORY_CHECK();
}
-void malloc_init (void)
+void malloc_init(void)
{
#if defined(DMALLOC) && defined(CYGWIN)
- // http://dmalloc.com/docs/latest/online/dmalloc_19.html
- dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
+ // http://dmalloc.com/docs/latest/online/dmalloc_19.html
+ dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
#endif
#ifdef GCOLLECT
- // don't garbage collect, only report inaccessible memory that was not deallocated
- GC_find_leak = 1;
- GC_INIT();
+ // don't garbage collect, only report inaccessible memory that was not deallocated
+ GC_find_leak = 1;
+ GC_INIT();
#endif
#ifdef USE_MEMMGR
- memmgr_init ();
+ memmgr_init();
#endif
}
diff --git a/src/common/malloc.h b/src/common/malloc.h
index 6b4e8e5c4..58dcee6d7 100644
--- a/src/common/malloc.h
+++ b/src/common/malloc.h
@@ -33,31 +33,31 @@
#undef LOG_MEMMGR
#endif
-# define aMalloc(n) _mmalloc(n,ALC_MARK)
-# define aCalloc(m,n) _mcalloc(m,n,ALC_MARK)
-# define aRealloc(p,n) _mrealloc(p,n,ALC_MARK)
-# define aStrdup(p) _mstrdup(p,ALC_MARK)
-# define aFree(p) _mfree(p,ALC_MARK)
-
- void* _mmalloc (size_t size, const char *file, int line, const char *func);
- void* _mcalloc (size_t num, size_t size, const char *file, int line, const char *func);
- void* _mrealloc (void *p, size_t size, const char *file, int line, const char *func);
- char* _mstrdup (const char *p, const char *file, int line, const char *func);
- void _mfree (void *p, const char *file, int line, const char *func);
+# define aMalloc(n) _mmalloc(n,ALC_MARK)
+# define aCalloc(m,n) _mcalloc(m,n,ALC_MARK)
+# define aRealloc(p,n) _mrealloc(p,n,ALC_MARK)
+# define aStrdup(p) _mstrdup(p,ALC_MARK)
+# define aFree(p) _mfree(p,ALC_MARK)
+
+void *_mmalloc(size_t size, const char *file, int line, const char *func);
+void *_mcalloc(size_t num, size_t size, const char *file, int line, const char *func);
+void *_mrealloc(void *p, size_t size, const char *file, int line, const char *func);
+char *_mstrdup(const char *p, const char *file, int line, const char *func);
+void _mfree(void *p, const char *file, int line, const char *func);
#else
-# define aMalloc(n) aMalloc_((n),ALC_MARK)
-# define aCalloc(m,n) aCalloc_((m),(n),ALC_MARK)
-# define aRealloc(p,n) aRealloc_(p,n,ALC_MARK)
-# define aStrdup(p) aStrdup_(p,ALC_MARK)
-# define aFree(p) aFree_(p,ALC_MARK)
+# define aMalloc(n) aMalloc_((n),ALC_MARK)
+# define aCalloc(m,n) aCalloc_((m),(n),ALC_MARK)
+# define aRealloc(p,n) aRealloc_(p,n,ALC_MARK)
+# define aStrdup(p) aStrdup_(p,ALC_MARK)
+# define aFree(p) aFree_(p,ALC_MARK)
- void* aMalloc_ (size_t size, const char *file, int line, const char *func);
- void* aCalloc_ (size_t num, size_t size, const char *file, int line, const char *func);
- void* aRealloc_ (void *p, size_t size, const char *file, int line, const char *func);
- char* aStrdup_ (const char *p, const char *file, int line, const char *func);
- void aFree_ (void *p, const char *file, int line, const char *func);
+void *aMalloc_(size_t size, const char *file, int line, const char *func);
+void *aCalloc_(size_t num, size_t size, const char *file, int line, const char *func);
+void *aRealloc_(void *p, size_t size, const char *file, int line, const char *func);
+char *aStrdup_(const char *p, const char *file, int line, const char *func);
+void aFree_(void *p, const char *file, int line, const char *func);
#endif
@@ -66,13 +66,13 @@
#ifdef __GNUC__ // GCC has variable length arrays
- #define CREATE_BUFFER(name, type, size) type name[size]
- #define DELETE_BUFFER(name)
+#define CREATE_BUFFER(name, type, size) type name[size]
+#define DELETE_BUFFER(name)
#else // others don't, so we emulate them
- #define CREATE_BUFFER(name, type, size) type *name = (type *) aCalloc (size, sizeof(type))
- #define DELETE_BUFFER(name) aFree(name)
+#define CREATE_BUFFER(name, type, size) type *name = (type *) aCalloc (size, sizeof(type))
+#define DELETE_BUFFER(name) aFree(name)
#endif
@@ -84,9 +84,9 @@
////////////////////////////////////////////////
void malloc_memory_check(void);
-bool malloc_verify_ptr(void* ptr);
-size_t malloc_usage (void);
-void malloc_init (void);
-void malloc_final (void);
+bool malloc_verify_ptr(void *ptr);
+size_t malloc_usage(void);
+void malloc_init(void);
+void malloc_final(void);
#endif /* _MALLOC_H_ */
diff --git a/src/common/mapindex.c b/src/common/mapindex.c
index d46047833..62d14590e 100644
--- a/src/common/mapindex.c
+++ b/src/common/mapindex.c
@@ -12,7 +12,7 @@
#include <stdlib.h>
struct _indexes {
- char name[MAP_NAME_LENGTH]; //Stores map name
+ char name[MAP_NAME_LENGTH]; //Stores map name
} indexes[MAX_MAPINDEX];
int max_index = 0;
@@ -23,161 +23,158 @@ char mapindex_cfgfile[80] = "db/map_index.txt";
/// Retrieves the map name from 'string' (removing .gat extension if present).
/// Result gets placed either into 'buf' or in a static local buffer.
-const char* mapindex_getmapname(const char* string, char* output)
+const char *mapindex_getmapname(const char *string, char *output)
{
- static char buf[MAP_NAME_LENGTH];
- char* dest = (output != NULL) ? output : buf;
-
- size_t len = strnlen(string, MAP_NAME_LENGTH_EXT);
- if (len == MAP_NAME_LENGTH_EXT) {
- ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH_EXT, string);
- len--;
- }
- if (len >= 4 && stricmp(&string[len-4], ".gat") == 0)
- len -= 4; // strip .gat extension
-
- len = min(len, MAP_NAME_LENGTH-1);
- strncpy(dest, string, len+1);
- memset(&dest[len], '\0', MAP_NAME_LENGTH-len);
-
- return dest;
+ static char buf[MAP_NAME_LENGTH];
+ char *dest = (output != NULL) ? output : buf;
+
+ size_t len = strnlen(string, MAP_NAME_LENGTH_EXT);
+ if (len == MAP_NAME_LENGTH_EXT) {
+ ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH_EXT, string);
+ len--;
+ }
+ if (len >= 4 && stricmp(&string[len-4], ".gat") == 0)
+ len -= 4; // strip .gat extension
+
+ len = min(len, MAP_NAME_LENGTH-1);
+ strncpy(dest, string, len+1);
+ memset(&dest[len], '\0', MAP_NAME_LENGTH-len);
+
+ return dest;
}
/// Retrieves the map name from 'string' (adding .gat extension if not already present).
/// Result gets placed either into 'buf' or in a static local buffer.
-const char* mapindex_getmapname_ext(const char* string, char* output)
+const char *mapindex_getmapname_ext(const char *string, char *output)
{
- static char buf[MAP_NAME_LENGTH_EXT];
- char* dest = (output != NULL) ? output : buf;
+ static char buf[MAP_NAME_LENGTH_EXT];
+ char *dest = (output != NULL) ? output : buf;
- size_t len;
+ size_t len;
- strcpy(buf,string);
- sscanf(string,"%*[^#]%*[#]%s",buf);
+ strcpy(buf,string);
+ sscanf(string,"%*[^#]%*[#]%s",buf);
- len = safestrnlen(buf, MAP_NAME_LENGTH);
+ len = safestrnlen(buf, MAP_NAME_LENGTH);
- if (len == MAP_NAME_LENGTH) {
- ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH, buf);
- len--;
- }
- strncpy(dest, buf, len+1);
+ if (len == MAP_NAME_LENGTH) {
+ ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH, buf);
+ len--;
+ }
+ strncpy(dest, buf, len+1);
- if (len < 4 || stricmp(&dest[len-4], ".gat") != 0) {
- strcpy(&dest[len], ".gat");
- len += 4; // add .gat extension
- }
+ if (len < 4 || stricmp(&dest[len-4], ".gat") != 0) {
+ strcpy(&dest[len], ".gat");
+ len += 4; // add .gat extension
+ }
- memset(&dest[len], '\0', MAP_NAME_LENGTH_EXT-len);
-
- return dest;
+ memset(&dest[len], '\0', MAP_NAME_LENGTH_EXT-len);
+
+ return dest;
}
/// Adds a map to the specified index
/// Returns 1 if successful, 0 oherwise
-int mapindex_addmap(int index, const char* name)
+int mapindex_addmap(int index, const char *name)
{
- char map_name[MAP_NAME_LENGTH];
-
- if (index == -1){
- for (index = 1; index < max_index; index++)
- {
- //if (strcmp(indexes[index].name,"#CLEARED#")==0)
- if (indexes[index].name[0] == '\0')
- break;
- }
- }
-
- if (index < 0 || index >= MAX_MAPINDEX) {
- ShowError("(mapindex_add) Map index (%d) for \"%s\" out of range (max is %d)\n", index, name, MAX_MAPINDEX);
- return 0;
- }
-
- mapindex_getmapname(name, map_name);
-
- if (map_name[0] == '\0') {
- ShowError("(mapindex_add) Cannot add maps with no name.\n");
- return 0;
- }
-
- if (strlen(map_name) >= MAP_NAME_LENGTH) {
- ShowError("(mapindex_add) Map name %s is too long. Maps are limited to %d characters.\n", map_name, MAP_NAME_LENGTH);
- return 0;
- }
-
- if (mapindex_exists(index))
- ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name);
-
- safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
- if (max_index <= index)
- max_index = index+1;
-
- return index;
+ char map_name[MAP_NAME_LENGTH];
+
+ if (index == -1) {
+ for (index = 1; index < max_index; index++) {
+ //if (strcmp(indexes[index].name,"#CLEARED#")==0)
+ if (indexes[index].name[0] == '\0')
+ break;
+ }
+ }
+
+ if (index < 0 || index >= MAX_MAPINDEX) {
+ ShowError("(mapindex_add) Map index (%d) for \"%s\" out of range (max is %d)\n", index, name, MAX_MAPINDEX);
+ return 0;
+ }
+
+ mapindex_getmapname(name, map_name);
+
+ if (map_name[0] == '\0') {
+ ShowError("(mapindex_add) Cannot add maps with no name.\n");
+ return 0;
+ }
+
+ if (strlen(map_name) >= MAP_NAME_LENGTH) {
+ ShowError("(mapindex_add) Map name %s is too long. Maps are limited to %d characters.\n", map_name, MAP_NAME_LENGTH);
+ return 0;
+ }
+
+ if (mapindex_exists(index))
+ ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name);
+
+ safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
+ if (max_index <= index)
+ max_index = index+1;
+
+ return index;
}
-unsigned short mapindex_name2id(const char* name)
+unsigned short mapindex_name2id(const char *name)
{
- //TODO: Perhaps use a db to speed this up? [Skotlex]
- int i;
-
- char map_name[MAP_NAME_LENGTH];
- mapindex_getmapname(name, map_name);
-
- for (i = 1; i < max_index; i++)
- {
- if (strcmpi(indexes[i].name,map_name)==0)
- return i;
- }
- ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name);
- return 0;
+ //TODO: Perhaps use a db to speed this up? [Skotlex]
+ int i;
+
+ char map_name[MAP_NAME_LENGTH];
+ mapindex_getmapname(name, map_name);
+
+ for (i = 1; i < max_index; i++) {
+ if (strcmpi(indexes[i].name,map_name)==0)
+ return i;
+ }
+ ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name);
+ return 0;
}
-const char* mapindex_id2name(unsigned short id)
+const char *mapindex_id2name(unsigned short id)
{
- if (id > MAX_MAPINDEX || !mapindex_exists(id)) {
- ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", id);
- return indexes[0].name; // dummy empty string so that the callee doesn't crash
- }
- return indexes[id].name;
+ if (id > MAX_MAPINDEX || !mapindex_exists(id)) {
+ ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", id);
+ return indexes[0].name; // dummy empty string so that the callee doesn't crash
+ }
+ return indexes[id].name;
}
void mapindex_init(void)
{
- FILE *fp;
- char line[1024];
- int last_index = -1;
- int index;
- char map_name[1024];
-
- memset (&indexes, 0, sizeof (indexes));
- fp=fopen(mapindex_cfgfile,"r");
- if(fp==NULL){
- ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile);
- exit(EXIT_FAILURE); //Server can't really run without this file.
- }
- while(fgets(line, sizeof(line), fp))
- {
- if(line[0] == '/' && line[1] == '/')
- continue;
-
- switch (sscanf(line, "%1023s\t%d", map_name, &index))
- {
- case 1: //Map with no ID given, auto-assign
- index = last_index+1;
- case 2: //Map with ID given
- mapindex_addmap(index,map_name);
- break;
- default:
- continue;
- }
- last_index = index;
- }
- fclose(fp);
+ FILE *fp;
+ char line[1024];
+ int last_index = -1;
+ int index;
+ char map_name[1024];
+
+ memset(&indexes, 0, sizeof(indexes));
+ fp=fopen(mapindex_cfgfile,"r");
+ if (fp==NULL) {
+ ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile);
+ exit(EXIT_FAILURE); //Server can't really run without this file.
+ }
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '/' && line[1] == '/')
+ continue;
+
+ switch (sscanf(line, "%1023s\t%d", map_name, &index)) {
+ case 1: //Map with no ID given, auto-assign
+ index = last_index+1;
+ case 2: //Map with ID given
+ mapindex_addmap(index,map_name);
+ break;
+ default:
+ continue;
+ }
+ last_index = index;
+ }
+ fclose(fp);
}
-int mapindex_removemap(int index){
- indexes[index].name[0] = '\0';
- return 0;
+int mapindex_removemap(int index)
+{
+ indexes[index].name[0] = '\0';
+ return 0;
}
void mapindex_final(void)
diff --git a/src/common/mapindex.h b/src/common/mapindex.h
index 75cb254c0..4889d20f1 100644
--- a/src/common/mapindex.h
+++ b/src/common/mapindex.h
@@ -47,14 +47,14 @@ extern char mapindex_cfgfile[80];
#define MAP_MALAYA "malaya"
#define MAP_ECLAGE "eclage"
-const char* mapindex_getmapname(const char* string, char* output);
-const char* mapindex_getmapname_ext(const char* string, char* output);
-unsigned short mapindex_name2id(const char*);
-const char* mapindex_id2name(unsigned short);
+const char *mapindex_getmapname(const char *string, char *output);
+const char *mapindex_getmapname_ext(const char *string, char *output);
+unsigned short mapindex_name2id(const char *);
+const char *mapindex_id2name(unsigned short);
void mapindex_init(void);
void mapindex_final(void);
-int mapindex_addmap(int index, const char* name);
+int mapindex_addmap(int index, const char *name);
int mapindex_removemap(int index);
#endif /* _MAPINDEX_H_ */
diff --git a/src/common/md5calc.c b/src/common/md5calc.c
index 05fde42cc..bd4b59ad0 100644
--- a/src/common/md5calc.c
+++ b/src/common/md5calc.c
@@ -21,22 +21,22 @@ static unsigned int *pX;
// String Table
static const unsigned int T[] = {
- 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, //0
- 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, //4
- 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, //8
- 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, //12
- 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, //16
- 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, //20
- 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, //24
- 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, //28
- 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, //32
- 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, //36
- 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, //40
- 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, //44
- 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, //48
- 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, //52
- 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, //56
- 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 //60
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, //0
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, //4
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, //8
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, //12
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, //16
+ 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, //20
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, //24
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, //28
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, //32
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, //36
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, //40
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, //44
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, //48
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, //52
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, //56
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 //60
};
// ROTATE_LEFT The left is made to rotate x [ n-bit ]. This is diverted as it is from RFC.
@@ -45,196 +45,244 @@ static const unsigned int T[] = {
// The function used for other calculation
static unsigned int F(unsigned int X, unsigned int Y, unsigned int Z)
{
- return (X & Y) | (~X & Z);
+ return (X & Y) | (~X & Z);
}
static unsigned int G(unsigned int X, unsigned int Y, unsigned int Z)
{
- return (X & Z) | (Y & ~Z);
+ return (X & Z) | (Y & ~Z);
}
static unsigned int H(unsigned int X, unsigned int Y, unsigned int Z)
{
- return X ^ Y ^ Z;
+ return X ^ Y ^ Z;
}
static unsigned int I(unsigned int X, unsigned int Y, unsigned int Z)
{
- return Y ^ (X | ~Z);
+ return Y ^ (X | ~Z);
}
static unsigned int Round(unsigned int a, unsigned int b, unsigned int FGHI,
- unsigned int k, unsigned int s, unsigned int i)
+ unsigned int k, unsigned int s, unsigned int i)
{
- return b + ROTATE_LEFT(a + FGHI + pX[k] + T[i], s);
+ return b + ROTATE_LEFT(a + FGHI + pX[k] + T[i], s);
}
static void Round1(unsigned int *a, unsigned int b, unsigned int c,
- unsigned int d,unsigned int k, unsigned int s, unsigned int i)
+ unsigned int d,unsigned int k, unsigned int s, unsigned int i)
{
- *a = Round(*a, b, F(b,c,d), k, s, i);
+ *a = Round(*a, b, F(b,c,d), k, s, i);
}
static void Round2(unsigned int *a, unsigned int b, unsigned int c,
- unsigned int d,unsigned int k, unsigned int s, unsigned int i)
+ unsigned int d,unsigned int k, unsigned int s, unsigned int i)
{
- *a = Round(*a, b, G(b,c,d), k, s, i);
+ *a = Round(*a, b, G(b,c,d), k, s, i);
}
static void Round3(unsigned int *a, unsigned int b, unsigned int c,
- unsigned int d,unsigned int k, unsigned int s, unsigned int i)
+ unsigned int d,unsigned int k, unsigned int s, unsigned int i)
{
- *a = Round(*a, b, H(b,c,d), k, s, i);
+ *a = Round(*a, b, H(b,c,d), k, s, i);
}
static void Round4(unsigned int *a, unsigned int b, unsigned int c,
- unsigned int d,unsigned int k, unsigned int s, unsigned int i)
+ unsigned int d,unsigned int k, unsigned int s, unsigned int i)
{
- *a = Round(*a, b, I(b,c,d), k, s, i);
+ *a = Round(*a, b, I(b,c,d), k, s, i);
}
static void MD5_Round_Calculate(const unsigned char *block,
- unsigned int *A2, unsigned int *B2, unsigned int *C2, unsigned int *D2)
+ unsigned int *A2, unsigned int *B2, unsigned int *C2, unsigned int *D2)
{
- //create X It is since it is required.
- unsigned int X[16]; //512bit 64byte
- int j,k;
-
- //Save A as AA, B as BB, C as CC, and and D as DD (saving of A, B, C, and D)
- unsigned int A=*A2, B=*B2, C=*C2, D=*D2;
- unsigned int AA = A,BB = B,CC = C,DD = D;
-
- //It is a large region variable reluctantly because of calculation of a round. . . for Round1...4
- pX = X;
-
- //Copy block(padding_message) i into X
- for (j=0,k=0; j<64; j+=4,k++)
- X[k] = ( (unsigned int )block[j] ) // 8byte*4 -> 32byte conversion
- | ( ((unsigned int )block[j+1]) << 8 ) // A function called Decode as used in the field of RFC
- | ( ((unsigned int )block[j+2]) << 16 )
- | ( ((unsigned int )block[j+3]) << 24 );
-
-
- //Round 1
- Round1(&A,B,C,D, 0, 7, 0); Round1(&D,A,B,C, 1, 12, 1); Round1(&C,D,A,B, 2, 17, 2); Round1(&B,C,D,A, 3, 22, 3);
- Round1(&A,B,C,D, 4, 7, 4); Round1(&D,A,B,C, 5, 12, 5); Round1(&C,D,A,B, 6, 17, 6); Round1(&B,C,D,A, 7, 22, 7);
- Round1(&A,B,C,D, 8, 7, 8); Round1(&D,A,B,C, 9, 12, 9); Round1(&C,D,A,B, 10, 17, 10); Round1(&B,C,D,A, 11, 22, 11);
- Round1(&A,B,C,D, 12, 7, 12); Round1(&D,A,B,C, 13, 12, 13); Round1(&C,D,A,B, 14, 17, 14); Round1(&B,C,D,A, 15, 22, 15);
-
- //Round 2
- Round2(&A,B,C,D, 1, 5, 16); Round2(&D,A,B,C, 6, 9, 17); Round2(&C,D,A,B, 11, 14, 18); Round2(&B,C,D,A, 0, 20, 19);
- Round2(&A,B,C,D, 5, 5, 20); Round2(&D,A,B,C, 10, 9, 21); Round2(&C,D,A,B, 15, 14, 22); Round2(&B,C,D,A, 4, 20, 23);
- Round2(&A,B,C,D, 9, 5, 24); Round2(&D,A,B,C, 14, 9, 25); Round2(&C,D,A,B, 3, 14, 26); Round2(&B,C,D,A, 8, 20, 27);
- Round2(&A,B,C,D, 13, 5, 28); Round2(&D,A,B,C, 2, 9, 29); Round2(&C,D,A,B, 7, 14, 30); Round2(&B,C,D,A, 12, 20, 31);
-
- //Round 3
- Round3(&A,B,C,D, 5, 4, 32); Round3(&D,A,B,C, 8, 11, 33); Round3(&C,D,A,B, 11, 16, 34); Round3(&B,C,D,A, 14, 23, 35);
- Round3(&A,B,C,D, 1, 4, 36); Round3(&D,A,B,C, 4, 11, 37); Round3(&C,D,A,B, 7, 16, 38); Round3(&B,C,D,A, 10, 23, 39);
- Round3(&A,B,C,D, 13, 4, 40); Round3(&D,A,B,C, 0, 11, 41); Round3(&C,D,A,B, 3, 16, 42); Round3(&B,C,D,A, 6, 23, 43);
- Round3(&A,B,C,D, 9, 4, 44); Round3(&D,A,B,C, 12, 11, 45); Round3(&C,D,A,B, 15, 16, 46); Round3(&B,C,D,A, 2, 23, 47);
-
- //Round 4
- Round4(&A,B,C,D, 0, 6, 48); Round4(&D,A,B,C, 7, 10, 49); Round4(&C,D,A,B, 14, 15, 50); Round4(&B,C,D,A, 5, 21, 51);
- Round4(&A,B,C,D, 12, 6, 52); Round4(&D,A,B,C, 3, 10, 53); Round4(&C,D,A,B, 10, 15, 54); Round4(&B,C,D,A, 1, 21, 55);
- Round4(&A,B,C,D, 8, 6, 56); Round4(&D,A,B,C, 15, 10, 57); Round4(&C,D,A,B, 6, 15, 58); Round4(&B,C,D,A, 13, 21, 59);
- Round4(&A,B,C,D, 4, 6, 60); Round4(&D,A,B,C, 11, 10, 61); Round4(&C,D,A,B, 2, 15, 62); Round4(&B,C,D,A, 9, 21, 63);
-
- // Then perform the following additions. (let's add)
- *A2 = A + AA;
- *B2 = B + BB;
- *C2 = C + CC;
- *D2 = D + DD;
-
- //The clearance of confidential information
- memset(pX, 0, sizeof(X));
+ //create X It is since it is required.
+ unsigned int X[16]; //512bit 64byte
+ int j,k;
+
+ //Save A as AA, B as BB, C as CC, and and D as DD (saving of A, B, C, and D)
+ unsigned int A=*A2, B=*B2, C=*C2, D=*D2;
+ unsigned int AA = A,BB = B,CC = C,DD = D;
+
+ //It is a large region variable reluctantly because of calculation of a round. . . for Round1...4
+ pX = X;
+
+ //Copy block(padding_message) i into X
+ for (j=0,k=0; j<64; j+=4,k++)
+ X[k] = ((unsigned int)block[j]) // 8byte*4 -> 32byte conversion
+ | (((unsigned int)block[j+1]) << 8) // A function called Decode as used in the field of RFC
+ | (((unsigned int)block[j+2]) << 16)
+ | (((unsigned int)block[j+3]) << 24);
+
+
+ //Round 1
+ Round1(&A,B,C,D, 0, 7, 0);
+ Round1(&D,A,B,C, 1, 12, 1);
+ Round1(&C,D,A,B, 2, 17, 2);
+ Round1(&B,C,D,A, 3, 22, 3);
+ Round1(&A,B,C,D, 4, 7, 4);
+ Round1(&D,A,B,C, 5, 12, 5);
+ Round1(&C,D,A,B, 6, 17, 6);
+ Round1(&B,C,D,A, 7, 22, 7);
+ Round1(&A,B,C,D, 8, 7, 8);
+ Round1(&D,A,B,C, 9, 12, 9);
+ Round1(&C,D,A,B, 10, 17, 10);
+ Round1(&B,C,D,A, 11, 22, 11);
+ Round1(&A,B,C,D, 12, 7, 12);
+ Round1(&D,A,B,C, 13, 12, 13);
+ Round1(&C,D,A,B, 14, 17, 14);
+ Round1(&B,C,D,A, 15, 22, 15);
+
+ //Round 2
+ Round2(&A,B,C,D, 1, 5, 16);
+ Round2(&D,A,B,C, 6, 9, 17);
+ Round2(&C,D,A,B, 11, 14, 18);
+ Round2(&B,C,D,A, 0, 20, 19);
+ Round2(&A,B,C,D, 5, 5, 20);
+ Round2(&D,A,B,C, 10, 9, 21);
+ Round2(&C,D,A,B, 15, 14, 22);
+ Round2(&B,C,D,A, 4, 20, 23);
+ Round2(&A,B,C,D, 9, 5, 24);
+ Round2(&D,A,B,C, 14, 9, 25);
+ Round2(&C,D,A,B, 3, 14, 26);
+ Round2(&B,C,D,A, 8, 20, 27);
+ Round2(&A,B,C,D, 13, 5, 28);
+ Round2(&D,A,B,C, 2, 9, 29);
+ Round2(&C,D,A,B, 7, 14, 30);
+ Round2(&B,C,D,A, 12, 20, 31);
+
+ //Round 3
+ Round3(&A,B,C,D, 5, 4, 32);
+ Round3(&D,A,B,C, 8, 11, 33);
+ Round3(&C,D,A,B, 11, 16, 34);
+ Round3(&B,C,D,A, 14, 23, 35);
+ Round3(&A,B,C,D, 1, 4, 36);
+ Round3(&D,A,B,C, 4, 11, 37);
+ Round3(&C,D,A,B, 7, 16, 38);
+ Round3(&B,C,D,A, 10, 23, 39);
+ Round3(&A,B,C,D, 13, 4, 40);
+ Round3(&D,A,B,C, 0, 11, 41);
+ Round3(&C,D,A,B, 3, 16, 42);
+ Round3(&B,C,D,A, 6, 23, 43);
+ Round3(&A,B,C,D, 9, 4, 44);
+ Round3(&D,A,B,C, 12, 11, 45);
+ Round3(&C,D,A,B, 15, 16, 46);
+ Round3(&B,C,D,A, 2, 23, 47);
+
+ //Round 4
+ Round4(&A,B,C,D, 0, 6, 48);
+ Round4(&D,A,B,C, 7, 10, 49);
+ Round4(&C,D,A,B, 14, 15, 50);
+ Round4(&B,C,D,A, 5, 21, 51);
+ Round4(&A,B,C,D, 12, 6, 52);
+ Round4(&D,A,B,C, 3, 10, 53);
+ Round4(&C,D,A,B, 10, 15, 54);
+ Round4(&B,C,D,A, 1, 21, 55);
+ Round4(&A,B,C,D, 8, 6, 56);
+ Round4(&D,A,B,C, 15, 10, 57);
+ Round4(&C,D,A,B, 6, 15, 58);
+ Round4(&B,C,D,A, 13, 21, 59);
+ Round4(&A,B,C,D, 4, 6, 60);
+ Round4(&D,A,B,C, 11, 10, 61);
+ Round4(&C,D,A,B, 2, 15, 62);
+ Round4(&B,C,D,A, 9, 21, 63);
+
+ // Then perform the following additions. (let's add)
+ *A2 = A + AA;
+ *B2 = B + BB;
+ *C2 = C + CC;
+ *D2 = D + DD;
+
+ //The clearance of confidential information
+ memset(pX, 0, sizeof(X));
}
-static void MD5_String2binary(const char * string, unsigned char * output)
+static void MD5_String2binary(const char *string, unsigned char *output)
{
-//var
- /*8bit*/
- unsigned char padding_message[64]; //Extended message 512bit 64byte
- unsigned char *pstring; //The position of string in the present scanning notes is held.
-
- /*32bit*/
- unsigned int string_byte_len, //The byte chief of string is held.
- string_bit_len, //The bit length of string is held.
- copy_len, //The number of bytes which is used by 1-3 and which remained
- msg_digest[4]; //Message digest 128bit 4byte
- unsigned int *A = &msg_digest[0], //The message digest in accordance with RFC (reference)
- *B = &msg_digest[1],
- *C = &msg_digest[2],
- *D = &msg_digest[3];
- int i;
-
-//prog
- //Step 3.Initialize MD Buffer (although it is the initialization; step 3 of A, B, C, and D -- unavoidable -- a head)
- *A = 0x67452301;
- *B = 0xefcdab89;
- *C = 0x98badcfe;
- *D = 0x10325476;
-
- //Step 1.Append Padding Bits (extension of a mark bit)
- //1-1
- string_byte_len = (unsigned int)strlen(string); //The byte chief of a character sequence is acquired.
- pstring = (unsigned char *)string; //The position of the present character sequence is set.
-
- //1-2 Repeat calculation until length becomes less than 64 bytes.
- for (i=string_byte_len; 64<=i; i-=64,pstring+=64)
+ //var
+ /*8bit*/
+ unsigned char padding_message[64]; //Extended message 512bit 64byte
+ unsigned char *pstring; //The position of string in the present scanning notes is held.
+
+ /*32bit*/
+ unsigned int string_byte_len, //The byte chief of string is held.
+ string_bit_len, //The bit length of string is held.
+ copy_len, //The number of bytes which is used by 1-3 and which remained
+ msg_digest[4]; //Message digest 128bit 4byte
+ unsigned int *A = &msg_digest[0], //The message digest in accordance with RFC (reference)
+ *B = &msg_digest[1],
+ *C = &msg_digest[2],
+ *D = &msg_digest[3];
+ int i;
+
+ //prog
+ //Step 3.Initialize MD Buffer (although it is the initialization; step 3 of A, B, C, and D -- unavoidable -- a head)
+ *A = 0x67452301;
+ *B = 0xefcdab89;
+ *C = 0x98badcfe;
+ *D = 0x10325476;
+
+ //Step 1.Append Padding Bits (extension of a mark bit)
+ //1-1
+ string_byte_len = (unsigned int)strlen(string); //The byte chief of a character sequence is acquired.
+ pstring = (unsigned char *)string; //The position of the present character sequence is set.
+
+ //1-2 Repeat calculation until length becomes less than 64 bytes.
+ for (i=string_byte_len; 64<=i; i-=64,pstring+=64)
MD5_Round_Calculate(pstring, A,B,C,D);
- //1-3
- copy_len = string_byte_len % 64; //The number of bytes which remained is computed.
- strncpy((char *)padding_message, (char *)pstring, copy_len); //A message is copied to an extended bit sequence.
- memset(padding_message+copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length.
- padding_message[copy_len] |= 0x80; //The next of a message is 1.
-
- //1-4
- //If 56 bytes or more (less than 64 bytes) of remainder becomes, it will calculate by extending to 64 bytes.
- if (56 <= copy_len) {
- MD5_Round_Calculate(padding_message, A,B,C,D);
- memset(padding_message, 0, 56); //56 bytes is newly fill uped with 0.
- }
-
- //Step 2.Append Length (the information on length is added)
- string_bit_len = string_byte_len * 8; //From the byte chief to bit length (32 bytes of low rank)
- memcpy(&padding_message[56], &string_bit_len, 4); //32 bytes of low rank is set.
-
- //When bit length cannot be expressed in 32 bytes of low rank, it is a beam raising to a higher rank.
- if (UINT_MAX / 8 < string_byte_len) {
- unsigned int high = (string_byte_len - UINT_MAX / 8) * 8;
- memcpy(&padding_message[60], &high, 4);
- } else
- memset(&padding_message[60], 0, 4); //In this case, it is good for a higher rank at 0.
-
- //Step 4.Process Message in 16-Word Blocks (calculation of MD5)
- MD5_Round_Calculate(padding_message, A,B,C,D);
-
- //Step 5.Output (output)
- memcpy(output,msg_digest,16);
+ //1-3
+ copy_len = string_byte_len % 64; //The number of bytes which remained is computed.
+ strncpy((char *)padding_message, (char *)pstring, copy_len); //A message is copied to an extended bit sequence.
+ memset(padding_message+copy_len, 0, 64 - copy_len); //It buries by 0 until it becomes extended bit length.
+ padding_message[copy_len] |= 0x80; //The next of a message is 1.
+
+ //1-4
+ //If 56 bytes or more (less than 64 bytes) of remainder becomes, it will calculate by extending to 64 bytes.
+ if (56 <= copy_len) {
+ MD5_Round_Calculate(padding_message, A,B,C,D);
+ memset(padding_message, 0, 56); //56 bytes is newly fill uped with 0.
+ }
+
+ //Step 2.Append Length (the information on length is added)
+ string_bit_len = string_byte_len * 8; //From the byte chief to bit length (32 bytes of low rank)
+ memcpy(&padding_message[56], &string_bit_len, 4); //32 bytes of low rank is set.
+
+ //When bit length cannot be expressed in 32 bytes of low rank, it is a beam raising to a higher rank.
+ if (UINT_MAX / 8 < string_byte_len) {
+ unsigned int high = (string_byte_len - UINT_MAX / 8) * 8;
+ memcpy(&padding_message[60], &high, 4);
+ } else
+ memset(&padding_message[60], 0, 4); //In this case, it is good for a higher rank at 0.
+
+ //Step 4.Process Message in 16-Word Blocks (calculation of MD5)
+ MD5_Round_Calculate(padding_message, A,B,C,D);
+
+ //Step 5.Output (output)
+ memcpy(output,msg_digest,16);
}
//-------------------------------------------------------------------
// The function for the exteriors
/** output is the coded binary in the character sequence which wants to code string. */
-void MD5_Binary(const char * string, unsigned char * output)
+void MD5_Binary(const char *string, unsigned char *output)
{
- MD5_String2binary(string,output);
+ MD5_String2binary(string,output);
}
/** output is the coded character sequence in the character sequence which wants to code string. */
-void MD5_String(const char * string, char * output)
+void MD5_String(const char *string, char *output)
{
- unsigned char digest[16];
-
- MD5_String2binary(string,digest);
- sprintf(output, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- digest[ 0], digest[ 1], digest[ 2], digest[ 3],
- digest[ 4], digest[ 5], digest[ 6], digest[ 7],
- digest[ 8], digest[ 9], digest[10], digest[11],
- digest[12], digest[13], digest[14], digest[15]);
+ unsigned char digest[16];
+
+ MD5_String2binary(string,digest);
+ sprintf(output, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ digest[ 0], digest[ 1], digest[ 2], digest[ 3],
+ digest[ 4], digest[ 5], digest[ 6], digest[ 7],
+ digest[ 8], digest[ 9], digest[10], digest[11],
+ digest[12], digest[13], digest[14], digest[15]);
}
/** output is a sequence of non-zero characters to be used as password salt. */
-void MD5_Salt(unsigned int len, char * output)
+void MD5_Salt(unsigned int len, char *output)
{
- unsigned int i;
- for( i = 0; i < len; ++i )
- output[i] = (char)(1 + rnd() % 255);
+ unsigned int i;
+ for (i = 0; i < len; ++i)
+ output[i] = (char)(1 + rnd() % 255);
}
diff --git a/src/common/md5calc.h b/src/common/md5calc.h
index 323affa2c..4a112a660 100644
--- a/src/common/md5calc.h
+++ b/src/common/md5calc.h
@@ -1,8 +1,8 @@
#ifndef _MD5CALC_H_
#define _MD5CALC_H_
-void MD5_String(const char * string, char * output);
-void MD5_Binary(const char * string, unsigned char * output);
-void MD5_Salt(unsigned int len, char * output);
+void MD5_String(const char *string, char *output);
+void MD5_Binary(const char *string, unsigned char *output);
+void MD5_Salt(unsigned int len, char *output);
#endif /* _MD5CALC_H_ */
diff --git a/src/common/mempool.c b/src/common/mempool.c
index 35b03034d..62db7b9e3 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -30,9 +30,9 @@
#include "../common/malloc.h"
#include "../common/mutex.h"
-#define ALIGN16 ra_align(16)
+#define ALIGN16 ra_align(16)
#define ALIGN_TO(x, a) (x + ( a - ( x % a) ) )
-#define ALIGN_TO_16(x) ALIGN_TO(x, 16)
+#define ALIGN_TO_16(x) ALIGN_TO(x, 16)
#undef MEMPOOL_DEBUG
#define MEMPOOLASSERT
@@ -40,523 +40,532 @@
#define NODE_TO_DATA(x) ( ((char*)x) + sizeof(struct node) )
#define DATA_TO_NODE(x) ( (struct node*)(((char*)x) - sizeof(struct node)) )
-struct ra_align(16) node{
- void *next;
- void *segment;
+struct ra_align(16) node {
+ void *next;
+ void *segment;
#ifdef MEMPOOLASSERT
- bool used;
- uint64 magic;
- #define NODE_MAGIC 0xBEEF00EAEACAFE07ll
+ bool used;
+ uint64 magic;
+#define NODE_MAGIC 0xBEEF00EAEACAFE07ll
#endif
};
// The Pointer to this struct is the base address of the segment itself.
-struct pool_segment{
- mempool pool; // pool, this segment belongs to
- struct pool_segment *next;
- int64 num_nodes_total;
- int64 num_bytes;
+struct pool_segment {
+ mempool pool; // pool, this segment belongs to
+ struct pool_segment *next;
+ int64 num_nodes_total;
+ int64 num_bytes;
};
-struct mempool{
- // Settings
- char *name;
- uint64 elem_size;
- uint64 elem_realloc_step;
- int64 elem_realloc_thresh;
-
- // Callbacks that get called for every node that gets allocated
- // Example usage: initialization of mutex/lock for each node.
- memPoolOnNodeAllocationProc onalloc;
- memPoolOnNodeDeallocationProc ondealloc;
-
- // Locks
- SPIN_LOCK segmentLock;
- SPIN_LOCK nodeLock;
-
-
- // Internal
- struct pool_segment *segments;
- struct node *free_list;
-
- volatile int64 num_nodes_total;
- volatile int64 num_nodes_free;
-
- volatile int64 num_segments;
- volatile int64 num_bytes_total;
-
- volatile int64 peak_nodes_used; // Peak Node Usage
- volatile int64 num_realloc_events; // Number of reallocations done. (allocate additional nodes)
-
- // list (used for global management such as allocator..)
- struct mempool *next;
+struct mempool {
+ // Settings
+ char *name;
+ uint64 elem_size;
+ uint64 elem_realloc_step;
+ int64 elem_realloc_thresh;
+
+ // Callbacks that get called for every node that gets allocated
+ // Example usage: initialization of mutex/lock for each node.
+ memPoolOnNodeAllocationProc onalloc;
+ memPoolOnNodeDeallocationProc ondealloc;
+
+ // Locks
+ SPIN_LOCK segmentLock;
+ SPIN_LOCK nodeLock;
+
+
+ // Internal
+ struct pool_segment *segments;
+ struct node *free_list;
+
+ volatile int64 num_nodes_total;
+ volatile int64 num_nodes_free;
+
+ volatile int64 num_segments;
+ volatile int64 num_bytes_total;
+
+ volatile int64 peak_nodes_used; // Peak Node Usage
+ volatile int64 num_realloc_events; // Number of reallocations done. (allocate additional nodes)
+
+ // list (used for global management such as allocator..)
+ struct mempool *next;
} ra_align(8); // Dont touch the alignment, otherwise interlocked functions are broken ..
-///
+///
// Implementation:
//
static void segment_allocate_add(mempool p, uint64 count);
static SPIN_LOCK l_mempoolListLock;
-static mempool l_mempoolList = NULL;
+static mempool l_mempoolList = NULL;
static rAthread l_async_thread = NULL;
-static ramutex l_async_lock = NULL;
-static racond l_async_cond = NULL;
+static ramutex l_async_lock = NULL;
+static racond l_async_cond = NULL;
static volatile int32 l_async_terminate = 0;
-static void *mempool_async_allocator(void *x){
- mempool p;
-
-
- while(1){
- if(l_async_terminate > 0)
- break;
-
- EnterSpinLock(&l_mempoolListLock);
-
- for(p = l_mempoolList; p != NULL; p = p->next){
-
- if(p->num_nodes_free < p->elem_realloc_thresh){
- // add new segment.
- segment_allocate_add(p, p->elem_realloc_step);
- // increase stats counter
- InterlockedIncrement64(&p->num_realloc_events);
- }
-
- }
-
- LeaveSpinLock(&l_mempoolListLock);
-
- ramutex_lock( l_async_lock );
- racond_wait( l_async_cond, l_async_lock, -1 );
- ramutex_unlock( l_async_lock );
- }
-
-
- return NULL;
+static void *mempool_async_allocator(void *x)
+{
+ mempool p;
+
+
+ while (1) {
+ if (l_async_terminate > 0)
+ break;
+
+ EnterSpinLock(&l_mempoolListLock);
+
+ for (p = l_mempoolList; p != NULL; p = p->next) {
+
+ if (p->num_nodes_free < p->elem_realloc_thresh) {
+ // add new segment.
+ segment_allocate_add(p, p->elem_realloc_step);
+ // increase stats counter
+ InterlockedIncrement64(&p->num_realloc_events);
+ }
+
+ }
+
+ LeaveSpinLock(&l_mempoolListLock);
+
+ ramutex_lock(l_async_lock);
+ racond_wait(l_async_cond, l_async_lock, -1);
+ ramutex_unlock(l_async_lock);
+ }
+
+
+ return NULL;
}//end: mempool_async_allocator()
-void mempool_init(){
-
- if(sizeof(struct node)%16 != 0 ){
- ShowFatalError("mempool_init: struct node alignment failure. %u != multiple of 16\n", sizeof(struct node));
- exit(EXIT_FAILURE);
- }
-
- // Global List start
- InitializeSpinLock(&l_mempoolListLock);
- l_mempoolList = NULL;
-
- // Initialize mutex + stuff needed for async allocator worker.
- l_async_terminate = 0;
- l_async_lock = ramutex_create();
- l_async_cond = racond_create();
-
- l_async_thread = rathread_createEx(mempool_async_allocator, NULL, 1024*1024, RAT_PRIO_NORMAL);
- if(l_async_thread == NULL){
- ShowFatalError("mempool_init: cannot spawn Async Allocator Thread.\n");
- exit(EXIT_FAILURE);
- }
+void mempool_init()
+{
+
+ if (sizeof(struct node)%16 != 0) {
+ ShowFatalError("mempool_init: struct node alignment failure. %u != multiple of 16\n", sizeof(struct node));
+ exit(EXIT_FAILURE);
+ }
+
+ // Global List start
+ InitializeSpinLock(&l_mempoolListLock);
+ l_mempoolList = NULL;
+
+ // Initialize mutex + stuff needed for async allocator worker.
+ l_async_terminate = 0;
+ l_async_lock = ramutex_create();
+ l_async_cond = racond_create();
+
+ l_async_thread = rathread_createEx(mempool_async_allocator, NULL, 1024*1024, RAT_PRIO_NORMAL);
+ if (l_async_thread == NULL) {
+ ShowFatalError("mempool_init: cannot spawn Async Allocator Thread.\n");
+ exit(EXIT_FAILURE);
+ }
}//end: mempool_init()
-void mempool_final(){
- mempool p, pn;
-
- ShowStatus("Mempool: Terminating async. allocation worker and remaining pools.\n");
-
- // Terminate worker / wait until its terminated.
- InterlockedIncrement(&l_async_terminate);
- racond_signal(l_async_cond);
- rathread_wait(l_async_thread, NULL);
-
- // Destroy cond var and mutex.
- racond_destroy( l_async_cond );
- ramutex_destroy( l_async_lock );
-
- // Free remaining mempools
- // ((bugged code! this should halppen, every mempool should
- // be freed by the subsystem that has allocated it.)
- //
- EnterSpinLock(&l_mempoolListLock);
- p = l_mempoolList;
- while(1){
- if(p == NULL)
- break;
-
- pn = p->next;
-
- ShowWarning("Mempool [%s] was not properly destroyed - forcing destroy.\n", p->name);
- mempool_destroy(p);
-
- p = pn;
- }
- LeaveSpinLock(&l_mempoolListLock);
-
+void mempool_final()
+{
+ mempool p, pn;
+
+ ShowStatus("Mempool: Terminating async. allocation worker and remaining pools.\n");
+
+ // Terminate worker / wait until its terminated.
+ InterlockedIncrement(&l_async_terminate);
+ racond_signal(l_async_cond);
+ rathread_wait(l_async_thread, NULL);
+
+ // Destroy cond var and mutex.
+ racond_destroy(l_async_cond);
+ ramutex_destroy(l_async_lock);
+
+ // Free remaining mempools
+ // ((bugged code! this should halppen, every mempool should
+ // be freed by the subsystem that has allocated it.)
+ //
+ EnterSpinLock(&l_mempoolListLock);
+ p = l_mempoolList;
+ while (1) {
+ if (p == NULL)
+ break;
+
+ pn = p->next;
+
+ ShowWarning("Mempool [%s] was not properly destroyed - forcing destroy.\n", p->name);
+ mempool_destroy(p);
+
+ p = pn;
+ }
+ LeaveSpinLock(&l_mempoolListLock);
+
}//end: mempool_final()
-static void segment_allocate_add(mempool p, uint64 count){
-
- // Required Memory:
- // sz( segment )
- // count * sz( real_node_size )
- //
- // where real node size is:
- // ALIGN_TO_16( sz( node ) ) + p->elem_size
- // so the nodes usable address is nodebase + ALIGN_TO_16(sz(node))
- //
- size_t total_sz;
- struct pool_segment *seg = NULL;
- struct node *nodeList = NULL;
- struct node *node = NULL;
- char *ptr = NULL;
- uint64 i;
-
- total_sz = ALIGN_TO_16( sizeof(struct pool_segment) )
- + ( (size_t)count * (sizeof(struct node) + (size_t)p->elem_size) ) ;
+static void segment_allocate_add(mempool p, uint64 count)
+{
+
+ // Required Memory:
+ // sz( segment )
+ // count * sz( real_node_size )
+ //
+ // where real node size is:
+ // ALIGN_TO_16( sz( node ) ) + p->elem_size
+ // so the nodes usable address is nodebase + ALIGN_TO_16(sz(node))
+ //
+ size_t total_sz;
+ struct pool_segment *seg = NULL;
+ struct node *nodeList = NULL;
+ struct node *node = NULL;
+ char *ptr = NULL;
+ uint64 i;
+
+ total_sz = ALIGN_TO_16(sizeof(struct pool_segment))
+ + ((size_t)count * (sizeof(struct node) + (size_t)p->elem_size)) ;
#ifdef MEMPOOL_DEBUG
- ShowDebug("Mempool [%s] Segment AllocateAdd (num: %u, total size: %0.2fMiB)\n", p->name, count, (float)total_sz/1024.f/1024.f);
+ ShowDebug("Mempool [%s] Segment AllocateAdd (num: %u, total size: %0.2fMiB)\n", p->name, count, (float)total_sz/1024.f/1024.f);
#endif
- // allocate! (spin forever until weve got the memory.)
- i=0;
- while(1){
- ptr = (char*)aMalloc(total_sz);
- if(ptr != NULL) break;
-
- i++; // increase failcount.
- if(!(i & 7)){
- ShowWarning("Mempool [%s] Segment AllocateAdd => System seems to be Out of Memory (%0.2f MiB). Try #%u\n", (float)total_sz/1024.f/1024.f, i);
+ // allocate! (spin forever until weve got the memory.)
+ i=0;
+ while (1) {
+ ptr = (char *)aMalloc(total_sz);
+ if (ptr != NULL) break;
+
+ i++; // increase failcount.
+ if (!(i & 7)) {
+ ShowWarning("Mempool [%s] Segment AllocateAdd => System seems to be Out of Memory (%0.2f MiB). Try #%u\n", (float)total_sz/1024.f/1024.f, i);
#ifdef WIN32
- Sleep(1000);
+ Sleep(1000);
#else
- sleep(1);
+ sleep(1);
#endif
- }else{
- rathread_yield(); /// allow/force vuln. ctxswitch
- }
- }//endwhile: allocation spinloop.
-
- // Clear Memory.
- memset(ptr, 0x00, total_sz);
-
- // Initialize segment struct.
- seg = (struct pool_segment*)ptr;
- ptr += ALIGN_TO_16(sizeof(struct pool_segment));
-
- seg->pool = p;
- seg->num_nodes_total = count;
- seg->num_bytes = total_sz;
-
-
- // Initialze nodes!
- nodeList = NULL;
- for(i = 0; i < count; i++){
- node = (struct node*)ptr;
- ptr += sizeof(struct node);
- ptr += p->elem_size;
-
- node->segment = seg;
+ } else {
+ rathread_yield(); /// allow/force vuln. ctxswitch
+ }
+ }//endwhile: allocation spinloop.
+
+ // Clear Memory.
+ memset(ptr, 0x00, total_sz);
+
+ // Initialize segment struct.
+ seg = (struct pool_segment *)ptr;
+ ptr += ALIGN_TO_16(sizeof(struct pool_segment));
+
+ seg->pool = p;
+ seg->num_nodes_total = count;
+ seg->num_bytes = total_sz;
+
+
+ // Initialze nodes!
+ nodeList = NULL;
+ for (i = 0; i < count; i++) {
+ node = (struct node *)ptr;
+ ptr += sizeof(struct node);
+ ptr += p->elem_size;
+
+ node->segment = seg;
#ifdef MEMPOOLASSERT
- node->used = false;
- node->magic = NODE_MAGIC;
+ node->used = false;
+ node->magic = NODE_MAGIC;
#endif
- if(p->onalloc != NULL) p->onalloc( NODE_TO_DATA(node) );
-
- node->next = nodeList;
- nodeList = node;
- }
-
-
-
- // Link in Segment.
- EnterSpinLock(&p->segmentLock);
- seg->next = p->segments;
- p->segments = seg;
- LeaveSpinLock(&p->segmentLock);
-
- // Link in Nodes
- EnterSpinLock(&p->nodeLock);
- nodeList->next = p->free_list;
- p->free_list = nodeList;
- LeaveSpinLock(&p->nodeLock);
-
-
- // Increase Stats:
- InterlockedExchangeAdd64(&p->num_nodes_total, count);
- InterlockedExchangeAdd64(&p->num_nodes_free, count);
- InterlockedIncrement64(&p->num_segments);
- InterlockedExchangeAdd64(&p->num_bytes_total, total_sz);
-
+ if (p->onalloc != NULL) p->onalloc(NODE_TO_DATA(node));
+
+ node->next = nodeList;
+ nodeList = node;
+ }
+
+
+
+ // Link in Segment.
+ EnterSpinLock(&p->segmentLock);
+ seg->next = p->segments;
+ p->segments = seg;
+ LeaveSpinLock(&p->segmentLock);
+
+ // Link in Nodes
+ EnterSpinLock(&p->nodeLock);
+ nodeList->next = p->free_list;
+ p->free_list = nodeList;
+ LeaveSpinLock(&p->nodeLock);
+
+
+ // Increase Stats:
+ InterlockedExchangeAdd64(&p->num_nodes_total, count);
+ InterlockedExchangeAdd64(&p->num_nodes_free, count);
+ InterlockedIncrement64(&p->num_segments);
+ InterlockedExchangeAdd64(&p->num_bytes_total, total_sz);
+
}//end: segment_allocate_add()
mempool mempool_create(const char *name,
- uint64 elem_size,
- uint64 initial_count,
- uint64 realloc_count,
- memPoolOnNodeAllocationProc onNodeAlloc,
- memPoolOnNodeDeallocationProc onNodeDealloc){
- //..
- uint64 realloc_thresh;
- mempool pool;
- pool = (mempool)aCalloc( 1, sizeof(struct mempool) );
-
- if(pool == NULL){
- ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool) );
- exit(EXIT_FAILURE);
- }
-
- // Check minimum initial count / realloc count requirements.
- if(initial_count < 50)
- initial_count = 50;
- if(realloc_count < 50)
- realloc_count = 50;
-
- // Set Reallocation threshold to 5% of realloc_count, at least 10.
- realloc_thresh = (realloc_count/100)*5; //
- if(realloc_thresh < 10)
- realloc_thresh = 10;
-
- // Initialize members..
- pool->name = aStrdup(name);
- pool->elem_size = ALIGN_TO_16(elem_size);
- pool->elem_realloc_step = realloc_count;
- pool->elem_realloc_thresh = realloc_thresh;
- pool->onalloc = onNodeAlloc;
- pool->ondealloc = onNodeDealloc;
-
- InitializeSpinLock(&pool->segmentLock);
- InitializeSpinLock(&pool->nodeLock);
-
- // Initial Statistic values:
- pool->num_nodes_total = 0;
- pool->num_nodes_free = 0;
- pool->num_segments = 0;
- pool->num_bytes_total = 0;
- pool->peak_nodes_used = 0;
- pool->num_realloc_events = 0;
-
- //
+ uint64 elem_size,
+ uint64 initial_count,
+ uint64 realloc_count,
+ memPoolOnNodeAllocationProc onNodeAlloc,
+ memPoolOnNodeDeallocationProc onNodeDealloc)
+{
+ //..
+ uint64 realloc_thresh;
+ mempool pool;
+ pool = (mempool)aCalloc(1, sizeof(struct mempool));
+
+ if (pool == NULL) {
+ ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool));
+ exit(EXIT_FAILURE);
+ }
+
+ // Check minimum initial count / realloc count requirements.
+ if (initial_count < 50)
+ initial_count = 50;
+ if (realloc_count < 50)
+ realloc_count = 50;
+
+ // Set Reallocation threshold to 5% of realloc_count, at least 10.
+ realloc_thresh = (realloc_count/100)*5; //
+ if (realloc_thresh < 10)
+ realloc_thresh = 10;
+
+ // Initialize members..
+ pool->name = aStrdup(name);
+ pool->elem_size = ALIGN_TO_16(elem_size);
+ pool->elem_realloc_step = realloc_count;
+ pool->elem_realloc_thresh = realloc_thresh;
+ pool->onalloc = onNodeAlloc;
+ pool->ondealloc = onNodeDealloc;
+
+ InitializeSpinLock(&pool->segmentLock);
+ InitializeSpinLock(&pool->nodeLock);
+
+ // Initial Statistic values:
+ pool->num_nodes_total = 0;
+ pool->num_nodes_free = 0;
+ pool->num_segments = 0;
+ pool->num_bytes_total = 0;
+ pool->peak_nodes_used = 0;
+ pool->num_realloc_events = 0;
+
+ //
#ifdef MEMPOOL_DEBUG
- ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step);
+ ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step);
#endif
- // Allocate first segment directly :)
- segment_allocate_add(pool, initial_count);
-
+ // Allocate first segment directly :)
+ segment_allocate_add(pool, initial_count);
+
+
+ // Add Pool to the global pool list
+ EnterSpinLock(&l_mempoolListLock);
+ pool->next = l_mempoolList;
+ l_mempoolList = pool;
+ LeaveSpinLock(&l_mempoolListLock);
- // Add Pool to the global pool list
- EnterSpinLock(&l_mempoolListLock);
- pool->next = l_mempoolList;
- l_mempoolList = pool;
- LeaveSpinLock(&l_mempoolListLock);
-
- return pool;
+ return pool;
}//end: mempool_create()
-void mempool_destroy(mempool p){
- struct pool_segment *seg, *segnext;
- struct node *niter;
- mempool piter, pprev;
- char *ptr;
- int64 i;
+void mempool_destroy(mempool p)
+{
+ struct pool_segment *seg, *segnext;
+ struct node *niter;
+ mempool piter, pprev;
+ char *ptr;
+ int64 i;
#ifdef MEMPOOL_DEBUG
ShowDebug("Mempool [%s] Destroy\n", p->name);
#endif
-
- // Unlink from global list.
- EnterSpinLock(&l_mempoolListLock);
- piter = l_mempoolList;
- pprev = l_mempoolList;
- while(1){
- if(piter == NULL)
- break;
-
-
- if(piter == p){
- // unlink from list,
- //
- if(pprev == l_mempoolList){
- // this (p) is list begin. so set next as head.
- l_mempoolList = p->next;
- }else{
- // replace prevs next wuth our next.
- pprev->next = p->next;
- }
- break;
- }
-
- pprev = piter;
- piter = piter->next;
- }
-
- p->next = NULL;
- LeaveSpinLock(&l_mempoolListLock);
-
-
- // Get both locks.
- EnterSpinLock(&p->segmentLock);
- EnterSpinLock(&p->nodeLock);
-
-
- if(p->num_nodes_free != p->num_nodes_total)
- ShowWarning("Mempool [%s] Destroy - %u nodes are not freed properly!\n", p->name, (p->num_nodes_total - p->num_nodes_free) );
-
- // Free All Segments (this will also free all nodes)
- // The segment pointer is the base pointer to the whole segment.
- seg = p->segments;
- while(1){
- if(seg == NULL)
- break;
-
- segnext = seg->next;
-
- // ..
- if(p->ondealloc != NULL){
- // walk over the segment, and call dealloc callback!
- ptr = (char*)seg;
- ptr += ALIGN_TO_16(sizeof(struct pool_segment));
- for(i = 0; i < seg->num_nodes_total; i++){
- niter = (struct node*)ptr;
- ptr += sizeof(struct node);
- ptr += p->elem_size;
+
+ // Unlink from global list.
+ EnterSpinLock(&l_mempoolListLock);
+ piter = l_mempoolList;
+ pprev = l_mempoolList;
+ while (1) {
+ if (piter == NULL)
+ break;
+
+
+ if (piter == p) {
+ // unlink from list,
+ //
+ if (pprev == l_mempoolList) {
+ // this (p) is list begin. so set next as head.
+ l_mempoolList = p->next;
+ } else {
+ // replace prevs next wuth our next.
+ pprev->next = p->next;
+ }
+ break;
+ }
+
+ pprev = piter;
+ piter = piter->next;
+ }
+
+ p->next = NULL;
+ LeaveSpinLock(&l_mempoolListLock);
+
+
+ // Get both locks.
+ EnterSpinLock(&p->segmentLock);
+ EnterSpinLock(&p->nodeLock);
+
+
+ if (p->num_nodes_free != p->num_nodes_total)
+ ShowWarning("Mempool [%s] Destroy - %u nodes are not freed properly!\n", p->name, (p->num_nodes_total - p->num_nodes_free));
+
+ // Free All Segments (this will also free all nodes)
+ // The segment pointer is the base pointer to the whole segment.
+ seg = p->segments;
+ while (1) {
+ if (seg == NULL)
+ break;
+
+ segnext = seg->next;
+
+ // ..
+ if (p->ondealloc != NULL) {
+ // walk over the segment, and call dealloc callback!
+ ptr = (char *)seg;
+ ptr += ALIGN_TO_16(sizeof(struct pool_segment));
+ for (i = 0; i < seg->num_nodes_total; i++) {
+ niter = (struct node *)ptr;
+ ptr += sizeof(struct node);
+ ptr += p->elem_size;
#ifdef MEMPOOLASSERT
- if(niter->magic != NODE_MAGIC){
- ShowError("Mempool [%s] Destroy - walk over segment - node %p invalid magic!\n", p->name, niter);
- continue;
- }
+ if (niter->magic != NODE_MAGIC) {
+ ShowError("Mempool [%s] Destroy - walk over segment - node %p invalid magic!\n", p->name, niter);
+ continue;
+ }
#endif
-
- p->ondealloc( NODE_TO_DATA(niter) );
-
-
- }
- }//endif: ondealloc callback?
-
- // simple ..
- aFree(seg);
-
- seg = segnext;
- }
-
- // Clear node ptr
- p->free_list = NULL;
- InterlockedExchange64(&p->num_nodes_free, 0);
- InterlockedExchange64(&p->num_nodes_total, 0);
- InterlockedExchange64(&p->num_segments, 0);
- InterlockedExchange64(&p->num_bytes_total, 0);
-
- LeaveSpinLock(&p->nodeLock);
- LeaveSpinLock(&p->segmentLock);
-
- // Free pool itself :D
- aFree(p->name);
- aFree(p);
+
+ p->ondealloc(NODE_TO_DATA(niter));
+
+
+ }
+ }//endif: ondealloc callback?
+
+ // simple ..
+ aFree(seg);
+
+ seg = segnext;
+ }
+
+ // Clear node ptr
+ p->free_list = NULL;
+ InterlockedExchange64(&p->num_nodes_free, 0);
+ InterlockedExchange64(&p->num_nodes_total, 0);
+ InterlockedExchange64(&p->num_segments, 0);
+ InterlockedExchange64(&p->num_bytes_total, 0);
+
+ LeaveSpinLock(&p->nodeLock);
+ LeaveSpinLock(&p->segmentLock);
+
+ // Free pool itself :D
+ aFree(p->name);
+ aFree(p);
}//end: mempool_destroy()
-void *mempool_node_get(mempool p){
- struct node *node;
- int64 num_used;
-
- if(p->num_nodes_free < p->elem_realloc_thresh)
- racond_signal(l_async_cond);
-
- while(1){
-
- EnterSpinLock(&p->nodeLock);
-
- node = p->free_list;
- if(node != NULL)
- p->free_list = node->next;
-
- LeaveSpinLock(&p->nodeLock);
-
- if(node != NULL)
- break;
-
- rathread_yield();
- }
-
- InterlockedDecrement64(&p->num_nodes_free);
-
- // Update peak value
- num_used = (p->num_nodes_total - p->num_nodes_free);
- if(num_used > p->peak_nodes_used){
- InterlockedExchange64(&p->peak_nodes_used, num_used);
- }
-
+void *mempool_node_get(mempool p)
+{
+ struct node *node;
+ int64 num_used;
+
+ if (p->num_nodes_free < p->elem_realloc_thresh)
+ racond_signal(l_async_cond);
+
+ while (1) {
+
+ EnterSpinLock(&p->nodeLock);
+
+ node = p->free_list;
+ if (node != NULL)
+ p->free_list = node->next;
+
+ LeaveSpinLock(&p->nodeLock);
+
+ if (node != NULL)
+ break;
+
+ rathread_yield();
+ }
+
+ InterlockedDecrement64(&p->num_nodes_free);
+
+ // Update peak value
+ num_used = (p->num_nodes_total - p->num_nodes_free);
+ if (num_used > p->peak_nodes_used) {
+ InterlockedExchange64(&p->peak_nodes_used, num_used);
+ }
+
#ifdef MEMPOOLASSERT
- node->used = true;
+ node->used = true;
#endif
- return NODE_TO_DATA(node);
+ return NODE_TO_DATA(node);
}//end: mempool_node_get()
-void mempool_node_put(mempool p, void *data){
- struct node *node;
-
- node = DATA_TO_NODE(data);
+void mempool_node_put(mempool p, void *data)
+{
+ struct node *node;
+
+ node = DATA_TO_NODE(data);
#ifdef MEMPOOLASSERT
- if(node->magic != NODE_MAGIC){
- ShowError("Mempool [%s] node_put failed, given address (%p) has invalid magic.\n", p->name, data);
- return; // lost,
- }
-
- {
- struct pool_segment *node_seg = node->segment;
- if(node_seg->pool != p){
- ShowError("Mempool [%s] node_put faild, given node (data address %p) doesnt belongs to this pool. ( Node Origin is [%s] )\n", p->name, data, node_seg->pool);
- return;
- }
- }
-
- // reset used flag.
- node->used = false;
+ if (node->magic != NODE_MAGIC) {
+ ShowError("Mempool [%s] node_put failed, given address (%p) has invalid magic.\n", p->name, data);
+ return; // lost,
+ }
+
+ {
+ struct pool_segment *node_seg = node->segment;
+ if (node_seg->pool != p) {
+ ShowError("Mempool [%s] node_put faild, given node (data address %p) doesnt belongs to this pool. ( Node Origin is [%s] )\n", p->name, data, node_seg->pool);
+ return;
+ }
+ }
+
+ // reset used flag.
+ node->used = false;
#endif
- //
- EnterSpinLock(&p->nodeLock);
- node->next = p->free_list;
- p->free_list = node;
- LeaveSpinLock(&p->nodeLock);
-
- InterlockedIncrement64(&p->num_nodes_free);
+ //
+ EnterSpinLock(&p->nodeLock);
+ node->next = p->free_list;
+ p->free_list = node;
+ LeaveSpinLock(&p->nodeLock);
+
+ InterlockedIncrement64(&p->num_nodes_free);
}//end: mempool_node_put()
-mempool_stats mempool_get_stats(mempool pool){
- mempool_stats stats;
-
- // initialize all with zeros
- memset(&stats, 0x00, sizeof(mempool_stats));
-
- stats.num_nodes_total = pool->num_nodes_total;
- stats.num_nodes_free = pool->num_nodes_free;
- stats.num_nodes_used = (stats.num_nodes_total - stats.num_nodes_free);
- stats.num_segments = pool->num_segments;
- stats.num_realloc_events= pool->num_realloc_events;
- stats.peak_nodes_used = pool->peak_nodes_used;
- stats.num_bytes_total = pool->num_bytes_total;
-
- // Pushing such a large block over the stack as return value isnt nice
- // but lazy :) and should be okay in this case (Stats / Debug..)
- // if you dont like it - feel free and refactor it.
- return stats;
+mempool_stats mempool_get_stats(mempool pool)
+{
+ mempool_stats stats;
+
+ // initialize all with zeros
+ memset(&stats, 0x00, sizeof(mempool_stats));
+
+ stats.num_nodes_total = pool->num_nodes_total;
+ stats.num_nodes_free = pool->num_nodes_free;
+ stats.num_nodes_used = (stats.num_nodes_total - stats.num_nodes_free);
+ stats.num_segments = pool->num_segments;
+ stats.num_realloc_events= pool->num_realloc_events;
+ stats.peak_nodes_used = pool->peak_nodes_used;
+ stats.num_bytes_total = pool->num_bytes_total;
+
+ // Pushing such a large block over the stack as return value isnt nice
+ // but lazy :) and should be okay in this case (Stats / Debug..)
+ // if you dont like it - feel free and refactor it.
+ return stats;
}//end: mempool_get_stats()
diff --git a/src/common/mempool.h b/src/common/mempool.h
index aeaebe7fe..9c4f1563e 100644
--- a/src/common/mempool.h
+++ b/src/common/mempool.h
@@ -8,67 +8,67 @@ typedef struct mempool *mempool;
typedef void (*memPoolOnNodeAllocationProc)(void *ptr);
typedef void (*memPoolOnNodeDeallocationProc)(void *ptr);
-typedef struct mempool_stats{
- int64 num_nodes_total;
- int64 num_nodes_free;
- int64 num_nodes_used;
-
- int64 num_segments;
- int64 num_realloc_events;
-
- int64 peak_nodes_used;
-
- int64 num_bytes_total;
+typedef struct mempool_stats {
+ int64 num_nodes_total;
+ int64 num_nodes_free;
+ int64 num_nodes_used;
+
+ int64 num_segments;
+ int64 num_realloc_events;
+
+ int64 peak_nodes_used;
+
+ int64 num_bytes_total;
} mempool_stats;
-//
+//
void mempool_init();
void mempool_final();
-/**
+/**
* Creates a new Mempool
*
* @param name - Name of the pool (used for debug / error messages)
* @param elem_size - size of each element
- * @param initial_count - preallocation count
+ * @param initial_count - preallocation count
* @param realloc_count - #no of nodes being allocated when pool is running empty.
* @param onNodeAlloc - Node Allocation callback (see @note!)
* @param onNodeDealloc - Node Deallocation callback (see @note!)
*
* @note:
- * The onNode(De)alloc callbacks are only called once during segment allocation
- * (pool initialization / rallocation )
+ * The onNode(De)alloc callbacks are only called once during segment allocation
+ * (pool initialization / rallocation )
* you can use this callbacks for example to initlaize a mutex or somethingelse
- * you definitly need during runtime
+ * you definitly need during runtime
*
* @return not NULL
*/
mempool mempool_create(const char *name,
- uint64 elem_size,
- uint64 initial_count,
- uint64 realloc_count,
-
- memPoolOnNodeAllocationProc onNodeAlloc,
- memPoolOnNodeDeallocationProc onNodeDealloc);
-
-
+ uint64 elem_size,
+ uint64 initial_count,
+ uint64 realloc_count,
+
+ memPoolOnNodeAllocationProc onNodeAlloc,
+ memPoolOnNodeDeallocationProc onNodeDealloc);
+
+
/**
* Destroys a Mempool
- *
+ *
* @param pool - the mempool to destroy
*
* @note:
- * Everything gets deallocated, regardless if everything was freed properly!
- * So you have to ensure that all references are cleared properly!
+ * Everything gets deallocated, regardless if everything was freed properly!
+ * So you have to ensure that all references are cleared properly!
*/
void mempool_destroy(mempool pool);
/**
* Gets a new / empty node from the given mempool.
- *
+ *
* @param pool - the pool to get an empty node from.
*
* @return Address of empty Node
@@ -80,12 +80,12 @@ void *mempool_node_get(mempool pool);
* Returns the given node to the given mempool
*
* @param pool - the pool to put the node, to
- * @param node - the node to return
+ * @param node - the node to return
*/
void mempool_node_put(mempool pool, void *node);
-/**
+/**
* Returns Statistics for the given mempool
*
* @param pool - the pool to get thats for
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 5f6108b33..4236eb4c6 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -1,8 +1,8 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _MMO_H_
-#define _MMO_H_
+#ifndef _MMO_H_
+#define _MMO_H_
#include "cbasetypes.h"
#include <time.h>
@@ -46,25 +46,25 @@
// 20120307 - 2012-03-07aRagexeRE+ - 0x970
#ifndef PACKETVER
- #define PACKETVER 20120410
- //#define PACKETVER 20111116
+#define PACKETVER 20120410
+//#define PACKETVER 20111116
#endif
//Remove/Comment this line to disable sc_data saving. [Skotlex]
-#define ENABLE_SC_SAVING
+#define ENABLE_SC_SAVING
//Remove/Comment this line to disable server-side hot-key saving support [Skotlex]
//Note that newer clients no longer save hotkeys in the registry!
#define HOTKEY_SAVING
#if PACKETVER < 20090603
- // (27 = 9 skills x 3 bars) (0x02b9,191)
- #define MAX_HOTKEYS 27
+// (27 = 9 skills x 3 bars) (0x02b9,191)
+#define MAX_HOTKEYS 27
#elif PACKETVER < 20090617
- // (36 = 9 skills x 4 bars) (0x07d9,254)
- #define MAX_HOTKEYS 36
+// (36 = 9 skills x 4 bars) (0x07d9,254)
+#define MAX_HOTKEYS 36
#else
- // (38 = 9 skills x 4 bars & 2 Quickslots)(0x07d9,268)
- #define MAX_HOTKEYS 38
+// (38 = 9 skills x 4 bars & 2 Quickslots)(0x07d9,268)
+#define MAX_HOTKEYS 38
#endif
#define MAX_MAP_PER_SERVER 1500 // Increased to allow creation of Instance Maps
@@ -91,13 +91,13 @@
#define MAX_STORAGE 600
#define MAX_GUILD_STORAGE 600
#define MAX_PARTY 12
-#define MAX_GUILD 16+10*6 // increased max guild members +6 per 1 extension levels [Lupus]
-#define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
+#define MAX_GUILD 16+10*6 // increased max guild members +6 per 1 extension levels [Lupus]
+#define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
#define MAX_GUILDEXPULSION 32
#define MAX_GUILDALLIANCE 16
-#define MAX_GUILDSKILL 15 // increased max guild skills because of new skills [Sara-chan]
+#define MAX_GUILDSKILL 15 // increased max guild skills because of new skills [Sara-chan]
#define MAX_GUILDLEVEL 50
-#define MAX_GUARDIANS 8 //Local max per castle. [Skotlex]
+#define MAX_GUARDIANS 8 //Local max per castle. [Skotlex]
#define MAX_QUEST_DB 2000 //Max quests that the server will load
#define MAX_QUEST_OBJECTIVES 3 //Max quest objectives for a quest
@@ -140,7 +140,7 @@
//Base Homun skill.
#define HM_SKILLBASE 8001
#define MAX_HOMUNSKILL 43
-#define MAX_HOMUNCULUS_CLASS 52 //[orn], Increased to 60 from 16 to allow new Homun-S.
+#define MAX_HOMUNCULUS_CLASS 52 //[orn], Increased to 60 from 16 to allow new Homun-S.
#define HM_CLASS_BASE 6001
#define HM_CLASS_MAX (HM_CLASS_BASE+MAX_HOMUNCULUS_CLASS-1)
@@ -163,20 +163,20 @@
#define EL_CLASS_MAX (EL_CLASS_BASE+MAX_ELEMENTAL_CLASS-1)
enum item_types {
- IT_HEALING = 0,
- IT_UNKNOWN, //1
- IT_USABLE, //2
- IT_ETC, //3
- IT_WEAPON, //4
- IT_ARMOR, //5
- IT_CARD, //6
- IT_PETEGG, //7
- IT_PETARMOR,//8
- IT_UNKNOWN2,//9
- IT_AMMO, //10
- IT_DELAYCONSUME,//11
- IT_CASH = 18,
- IT_MAX
+ IT_HEALING = 0,
+ IT_UNKNOWN, //1
+ IT_USABLE, //2
+ IT_ETC, //3
+ IT_WEAPON, //4
+ IT_ARMOR, //5
+ IT_CARD, //6
+ IT_PETEGG, //7
+ IT_PETARMOR,//8
+ IT_UNKNOWN2,//9
+ IT_AMMO, //10
+ IT_DELAYCONSUME,//11
+ IT_CASH = 18,
+ IT_MAX
};
@@ -184,556 +184,555 @@ enum item_types {
typedef enum quest_state { Q_INACTIVE, Q_ACTIVE, Q_COMPLETE } quest_state;
struct quest {
- int quest_id;
- unsigned int time;
- int count[MAX_QUEST_OBJECTIVES];
- quest_state state;
+ int quest_id;
+ unsigned int time;
+ int count[MAX_QUEST_OBJECTIVES];
+ quest_state state;
};
struct item {
- int id;
- short nameid;
- short amount;
- unsigned short equip; // location(s) where item is equipped (using enum equip_pos for bitmasking)
- char identify;
- char refine;
- char attribute;
- short card[MAX_SLOTS];
- unsigned int expire_time;
- char favorite;
+ int id;
+ short nameid;
+ short amount;
+ unsigned short equip; // location(s) where item is equipped (using enum equip_pos for bitmasking)
+ char identify;
+ char refine;
+ char attribute;
+ short card[MAX_SLOTS];
+ unsigned int expire_time;
+ char favorite;
};
struct point {
- unsigned short map;
- short x,y;
+ unsigned short map;
+ 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'
- //...
+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;
- unsigned char lv;
- unsigned char flag; // see enum e_skill_flag
+ unsigned short id;
+ unsigned char lv;
+ unsigned char flag; // see enum e_skill_flag
};
struct global_reg {
- char str[32];
- char value[256];
+ char str[32];
+ char value[256];
};
//Holds array of global registries, used by the char server and converter.
struct accreg {
- int account_id, char_id;
- int reg_num;
- struct global_reg reg[MAX_REG_NUM];
+ int account_id, char_id;
+ int reg_num;
+ struct global_reg reg[MAX_REG_NUM];
};
//For saving status changes across sessions. [Skotlex]
struct status_change_data {
- unsigned short type; //SC_type
- long val1, val2, val3, val4, tick; //Remaining duration.
+ unsigned short type; //SC_type
+ long val1, val2, val3, val4, tick; //Remaining duration.
};
struct storage_data {
- int storage_amount;
- struct item items[MAX_STORAGE];
+ int storage_amount;
+ struct item items[MAX_STORAGE];
};
struct guild_storage {
- int dirty;
- int guild_id;
- short storage_status;
- short storage_amount;
- struct item items[MAX_GUILD_STORAGE];
+ int dirty;
+ int guild_id;
+ short storage_status;
+ short storage_amount;
+ struct item items[MAX_GUILD_STORAGE];
};
struct s_pet {
- int account_id;
- int char_id;
- int pet_id;
- short class_;
- short level;
- short egg_id;//pet egg id
- short equip;//pet equip name_id
- short intimate;//pet friendly
- short hungry;//pet hungry
- char name[NAME_LENGTH];
- char rename_flag;
- char incuvate;
-};
-
-struct s_homunculus { //[orn]
- char name[NAME_LENGTH];
- int hom_id;
- int char_id;
- short class_;
- short prev_class;
- int hp,max_hp,sp,max_sp;
- unsigned int intimacy; //[orn]
- short hunger;
- struct s_skill hskill[MAX_HOMUNSKILL]; //albator
- short skillpts;
- short level;
- unsigned int exp;
- short rename_flag;
- short vaporize; //albator
- int str ;
- int agi ;
- int vit ;
- int int_ ;
- int dex ;
- int luk ;
+ int account_id;
+ int char_id;
+ int pet_id;
+ short class_;
+ short level;
+ short egg_id;//pet egg id
+ short equip;//pet equip name_id
+ short intimate;//pet friendly
+ short hungry;//pet hungry
+ char name[NAME_LENGTH];
+ char rename_flag;
+ char incuvate;
+};
+
+struct s_homunculus { //[orn]
+ char name[NAME_LENGTH];
+ int hom_id;
+ int char_id;
+ short class_;
+ short prev_class;
+ int hp,max_hp,sp,max_sp;
+ unsigned int intimacy; //[orn]
+ short hunger;
+ struct s_skill hskill[MAX_HOMUNSKILL]; //albator
+ short skillpts;
+ short level;
+ unsigned int exp;
+ short rename_flag;
+ short vaporize; //albator
+ int str ;
+ int agi ;
+ int vit ;
+ int int_ ;
+ int dex ;
+ int luk ;
};
struct s_mercenary {
- int mercenary_id;
- int char_id;
- short class_;
- int hp, sp;
- unsigned int kill_count;
- unsigned int life_time;
+ int mercenary_id;
+ int char_id;
+ short class_;
+ int hp, sp;
+ unsigned int kill_count;
+ unsigned int life_time;
};
struct s_elemental {
- int elemental_id;
- int char_id;
- short class_;
- int mode;
- int hp, sp, max_hp, max_sp, str, agi, vit, int_, dex, luk;
- int life_time;
+ int elemental_id;
+ int char_id;
+ short class_;
+ int mode;
+ int hp, sp, max_hp, max_sp, str, agi, vit, int_, dex, luk;
+ int life_time;
};
struct s_friend {
- int account_id;
- int char_id;
- char name[NAME_LENGTH];
+ int account_id;
+ int char_id;
+ char name[NAME_LENGTH];
};
#ifdef HOTKEY_SAVING
struct hotkey {
- unsigned int id;
- unsigned short lv;
- unsigned char type; // 0: item, 1: skill
+ unsigned int id;
+ unsigned short lv;
+ unsigned char type; // 0: item, 1: skill
};
#endif
struct mmo_charstatus {
- int char_id;
- int account_id;
- int partner_id;
- int father;
- int mother;
- int child;
-
- unsigned int base_exp,job_exp;
- int zeny;
-
- short class_;
- unsigned int status_point,skill_point;
- int hp,max_hp,sp,max_sp;
- unsigned int option;
- short manner;
- unsigned char karma;
- short hair,hair_color,clothes_color;
- int party_id,guild_id,pet_id,hom_id,mer_id,ele_id;
- int fame;
-
- // Mercenary Guilds Rank
- int arch_faith, arch_calls;
- int spear_faith, spear_calls;
- int sword_faith, sword_calls;
-
- short weapon; // enum weapon_type
- short shield; // view-id
- short head_top,head_mid,head_bottom;
- short robe;
-
- char name[NAME_LENGTH];
- unsigned int base_level,job_level;
- short str,agi,vit,int_,dex,luk;
- unsigned char slot,sex;
-
- uint32 mapip;
- uint16 mapport;
-
- struct point last_point,save_point,memo_point[MAX_MEMOPOINTS];
- struct item inventory[MAX_INVENTORY],cart[MAX_CART];
- struct storage_data storage;
- struct s_skill skill[MAX_SKILL];
-
- struct s_friend friends[MAX_FRIENDS]; //New friend system [Skotlex]
+ int char_id;
+ int account_id;
+ int partner_id;
+ int father;
+ int mother;
+ int child;
+
+ unsigned int base_exp,job_exp;
+ int zeny;
+
+ short class_;
+ unsigned int status_point,skill_point;
+ int hp,max_hp,sp,max_sp;
+ unsigned int option;
+ short manner;
+ unsigned char karma;
+ short hair,hair_color,clothes_color;
+ int party_id,guild_id,pet_id,hom_id,mer_id,ele_id;
+ int fame;
+
+ // Mercenary Guilds Rank
+ int arch_faith, arch_calls;
+ int spear_faith, spear_calls;
+ int sword_faith, sword_calls;
+
+ short weapon; // enum weapon_type
+ short shield; // view-id
+ short head_top,head_mid,head_bottom;
+ short robe;
+
+ char name[NAME_LENGTH];
+ unsigned int base_level,job_level;
+ short str,agi,vit,int_,dex,luk;
+ unsigned char slot,sex;
+
+ uint32 mapip;
+ uint16 mapport;
+
+ struct point last_point,save_point,memo_point[MAX_MEMOPOINTS];
+ struct item inventory[MAX_INVENTORY],cart[MAX_CART];
+ struct storage_data storage;
+ struct s_skill skill[MAX_SKILL];
+
+ struct s_friend friends[MAX_FRIENDS]; //New friend system [Skotlex]
#ifdef HOTKEY_SAVING
- struct hotkey hotkeys[MAX_HOTKEYS];
+ struct hotkey hotkeys[MAX_HOTKEYS];
#endif
- bool show_equip;
- short rename;
+ bool show_equip;
+ short rename;
- time_t delete_date;
+ time_t delete_date;
};
typedef enum mail_status {
- MAIL_NEW,
- MAIL_UNREAD,
- MAIL_READ,
+ MAIL_NEW,
+ MAIL_UNREAD,
+ MAIL_READ,
} mail_status;
struct mail_message {
- int id;
- int send_id;
- char send_name[NAME_LENGTH];
- int dest_id;
- char dest_name[NAME_LENGTH];
- char title[MAIL_TITLE_LENGTH];
- char body[MAIL_BODY_LENGTH];
+ int id;
+ int send_id;
+ char send_name[NAME_LENGTH];
+ int dest_id;
+ char dest_name[NAME_LENGTH];
+ char title[MAIL_TITLE_LENGTH];
+ char body[MAIL_BODY_LENGTH];
- mail_status status;
- time_t timestamp; // marks when the message was sent
+ mail_status status;
+ time_t timestamp; // marks when the message was sent
- int zeny;
- struct item item;
+ int zeny;
+ struct item item;
};
struct mail_data {
- short amount;
- bool full;
- short unchecked, unread;
- struct mail_message msg[MAIL_MAX_INBOX];
+ short amount;
+ bool full;
+ short unchecked, unread;
+ struct mail_message msg[MAIL_MAX_INBOX];
};
struct auction_data {
- unsigned int auction_id;
- int seller_id;
- char seller_name[NAME_LENGTH];
- int buyer_id;
- char buyer_name[NAME_LENGTH];
-
- struct item item;
- // This data is required for searching, as itemdb is not read by char server
- char item_name[ITEM_NAME_LENGTH];
- short type;
-
- unsigned short hours;
- int price, buynow;
- time_t timestamp; // auction's end time
- int auction_end_timer;
+ unsigned int auction_id;
+ int seller_id;
+ char seller_name[NAME_LENGTH];
+ int buyer_id;
+ char buyer_name[NAME_LENGTH];
+
+ struct item item;
+ // This data is required for searching, as itemdb is not read by char server
+ char item_name[ITEM_NAME_LENGTH];
+ short type;
+
+ unsigned short hours;
+ int price, buynow;
+ time_t timestamp; // auction's end time
+ int auction_end_timer;
};
struct registry {
- int global_num;
- struct global_reg global[GLOBAL_REG_NUM];
- int account_num;
- struct global_reg account[ACCOUNT_REG_NUM];
- int account2_num;
- struct global_reg account2[ACCOUNT_REG2_NUM];
+ int global_num;
+ struct global_reg global[GLOBAL_REG_NUM];
+ int account_num;
+ struct global_reg account[ACCOUNT_REG_NUM];
+ int account2_num;
+ struct global_reg account2[ACCOUNT_REG2_NUM];
};
struct party_member {
- int account_id;
- int char_id;
- char name[NAME_LENGTH];
- unsigned short class_;
- unsigned short map;
- unsigned short lv;
- unsigned leader : 1,
- online : 1;
+ int account_id;
+ int char_id;
+ char name[NAME_LENGTH];
+ unsigned short class_;
+ unsigned short map;
+ unsigned short lv;
+ unsigned leader : 1,
+ online : 1;
};
struct party {
- int party_id;
- char name[NAME_LENGTH];
- unsigned char count; //Count of online characters.
- unsigned exp : 1,
- item : 2; //&1: Party-Share (round-robin), &2: pickup style: shared.
- struct party_member member[MAX_PARTY];
+ int party_id;
+ char name[NAME_LENGTH];
+ unsigned char count; //Count of online characters.
+ unsigned exp : 1,
+ item : 2; //&1: Party-Share (round-robin), &2: pickup style: shared.
+ struct party_member member[MAX_PARTY];
};
struct map_session_data;
struct guild_member {
- int account_id, char_id;
- short hair,hair_color,gender,class_,lv;
- uint64 exp;
- int exp_payper;
- short online,position;
- char name[NAME_LENGTH];
- struct map_session_data *sd;
- unsigned char modified;
+ int account_id, char_id;
+ short hair,hair_color,gender,class_,lv;
+ uint64 exp;
+ int exp_payper;
+ short online,position;
+ char name[NAME_LENGTH];
+ struct map_session_data *sd;
+ unsigned char modified;
};
struct guild_position {
- char name[NAME_LENGTH];
- int mode;
- int exp_mode;
- unsigned char modified;
+ char name[NAME_LENGTH];
+ int mode;
+ int exp_mode;
+ unsigned char modified;
};
struct guild_alliance {
- int opposition;
- int guild_id;
- char name[NAME_LENGTH];
+ int opposition;
+ int guild_id;
+ char name[NAME_LENGTH];
};
struct guild_expulsion {
- char name[NAME_LENGTH];
- char mes[40];
- int account_id;
+ char name[NAME_LENGTH];
+ char mes[40];
+ int account_id;
};
struct guild_skill {
- int id,lv;
+ int id,lv;
};
struct guild {
- int guild_id;
- short guild_lv, connect_member, max_member, average_lv;
- uint64 exp;
- unsigned int next_exp;
- int skill_point;
- char name[NAME_LENGTH],master[NAME_LENGTH];
- struct guild_member member[MAX_GUILD];
- struct guild_position position[MAX_GUILDPOSITION];
- char mes1[MAX_GUILDMES1],mes2[MAX_GUILDMES2];
- int emblem_len,emblem_id;
- char emblem_data[2048];
- struct guild_alliance alliance[MAX_GUILDALLIANCE];
- struct guild_expulsion expulsion[MAX_GUILDEXPULSION];
- struct guild_skill skill[MAX_GUILDSKILL];
-
- unsigned short save_flag; // for TXT saving
+ int guild_id;
+ short guild_lv, connect_member, max_member, average_lv;
+ uint64 exp;
+ unsigned int next_exp;
+ int skill_point;
+ char name[NAME_LENGTH],master[NAME_LENGTH];
+ struct guild_member member[MAX_GUILD];
+ struct guild_position position[MAX_GUILDPOSITION];
+ char mes1[MAX_GUILDMES1],mes2[MAX_GUILDMES2];
+ int emblem_len,emblem_id;
+ char emblem_data[2048];
+ struct guild_alliance alliance[MAX_GUILDALLIANCE];
+ struct guild_expulsion expulsion[MAX_GUILDEXPULSION];
+ struct guild_skill skill[MAX_GUILDSKILL];
+
+ unsigned short save_flag; // for TXT saving
};
struct guild_castle {
- int castle_id;
- int mapindex;
- char castle_name[NAME_LENGTH];
- char castle_event[NAME_LENGTH];
- int guild_id;
- int economy;
- int defense;
- int triggerE;
- int triggerD;
- int nextTime;
- int payTime;
- int createTime;
- int visibleC;
- struct {
- unsigned visible : 1;
- int id; // object id
- } guardian[MAX_GUARDIANS];
- int* temp_guardians; // ids of temporary guardians (mobs)
- int temp_guardians_max;
+ int castle_id;
+ int mapindex;
+ char castle_name[NAME_LENGTH];
+ char castle_event[NAME_LENGTH];
+ int guild_id;
+ int economy;
+ int defense;
+ int triggerE;
+ int triggerD;
+ int nextTime;
+ int payTime;
+ int createTime;
+ int visibleC;
+ struct {
+ unsigned visible : 1;
+ int id; // object id
+ } guardian[MAX_GUARDIANS];
+ int *temp_guardians; // ids of temporary guardians (mobs)
+ int temp_guardians_max;
};
struct fame_list {
- int id;
- int fame;
- char name[NAME_LENGTH];
+ int id;
+ int fame;
+ char name[NAME_LENGTH];
};
-enum { //Change Guild Infos
- GBI_EXP =1, // Guild Experience (EXP)
- GBI_GUILDLV, // Guild level
- GBI_SKILLPOINT, // Guild skillpoints
- GBI_SKILLLV, // Guild skilllv ?? seem unused
+enum { //Change Guild Infos
+ GBI_EXP =1, // Guild Experience (EXP)
+ GBI_GUILDLV, // Guild level
+ GBI_SKILLPOINT, // Guild skillpoints
+ GBI_SKILLLV, // Guild skilllv ?? seem unused
};
enum { //Change Member Infos
- GMI_POSITION =0,
- GMI_EXP,
- GMI_HAIR,
- GMI_HAIR_COLOR,
- GMI_GENDER,
- GMI_CLASS,
- GMI_LEVEL,
+ GMI_POSITION =0,
+ GMI_EXP,
+ GMI_HAIR,
+ GMI_HAIR_COLOR,
+ GMI_GENDER,
+ GMI_CLASS,
+ GMI_LEVEL,
};
enum {
- GD_SKILLBASE=10000,
- GD_APPROVAL=10000,
- GD_KAFRACONTRACT=10001,
- GD_GUARDRESEARCH=10002,
- GD_GUARDUP=10003,
- GD_EXTENSION=10004,
- GD_GLORYGUILD=10005,
- GD_LEADERSHIP=10006,
- GD_GLORYWOUNDS=10007,
- GD_SOULCOLD=10008,
- GD_HAWKEYES=10009,
- GD_BATTLEORDER=10010,
- GD_REGENERATION=10011,
- GD_RESTORE=10012,
- GD_EMERGENCYCALL=10013,
- GD_DEVELOPMENT=10014,
- GD_MAX,
+ GD_SKILLBASE=10000,
+ GD_APPROVAL=10000,
+ GD_KAFRACONTRACT=10001,
+ GD_GUARDRESEARCH=10002,
+ GD_GUARDUP=10003,
+ GD_EXTENSION=10004,
+ GD_GLORYGUILD=10005,
+ GD_LEADERSHIP=10006,
+ GD_GLORYWOUNDS=10007,
+ GD_SOULCOLD=10008,
+ GD_HAWKEYES=10009,
+ GD_BATTLEORDER=10010,
+ GD_REGENERATION=10011,
+ GD_RESTORE=10012,
+ GD_EMERGENCYCALL=10013,
+ GD_DEVELOPMENT=10014,
+ GD_MAX,
};
//These mark the ID of the jobs, as expected by the client. [Skotlex]
enum {
- JOB_NOVICE,
- JOB_SWORDMAN,
- JOB_MAGE,
- JOB_ARCHER,
- JOB_ACOLYTE,
- JOB_MERCHANT,
- JOB_THIEF,
- JOB_KNIGHT,
- JOB_PRIEST,
- JOB_WIZARD,
- JOB_BLACKSMITH,
- JOB_HUNTER,
- JOB_ASSASSIN,
- JOB_KNIGHT2,
- JOB_CRUSADER,
- JOB_MONK,
- JOB_SAGE,
- JOB_ROGUE,
- JOB_ALCHEMIST,
- JOB_BARD,
- JOB_DANCER,
- JOB_CRUSADER2,
- JOB_WEDDING,
- JOB_SUPER_NOVICE,
- JOB_GUNSLINGER,
- JOB_NINJA,
- JOB_XMAS,
- JOB_SUMMER,
- JOB_MAX_BASIC,
-
- JOB_NOVICE_HIGH = 4001,
- JOB_SWORDMAN_HIGH,
- JOB_MAGE_HIGH,
- JOB_ARCHER_HIGH,
- JOB_ACOLYTE_HIGH,
- JOB_MERCHANT_HIGH,
- JOB_THIEF_HIGH,
- JOB_LORD_KNIGHT,
- JOB_HIGH_PRIEST,
- JOB_HIGH_WIZARD,
- JOB_WHITESMITH,
- JOB_SNIPER,
- JOB_ASSASSIN_CROSS,
- JOB_LORD_KNIGHT2,
- JOB_PALADIN,
- JOB_CHAMPION,
- JOB_PROFESSOR,
- JOB_STALKER,
- JOB_CREATOR,
- JOB_CLOWN,
- JOB_GYPSY,
- JOB_PALADIN2,
-
- JOB_BABY,
- JOB_BABY_SWORDMAN,
- JOB_BABY_MAGE,
- JOB_BABY_ARCHER,
- JOB_BABY_ACOLYTE,
- JOB_BABY_MERCHANT,
- JOB_BABY_THIEF,
- JOB_BABY_KNIGHT,
- JOB_BABY_PRIEST,
- JOB_BABY_WIZARD,
- JOB_BABY_BLACKSMITH,
- JOB_BABY_HUNTER,
- JOB_BABY_ASSASSIN,
- JOB_BABY_KNIGHT2,
- JOB_BABY_CRUSADER,
- JOB_BABY_MONK,
- JOB_BABY_SAGE,
- JOB_BABY_ROGUE,
- JOB_BABY_ALCHEMIST,
- JOB_BABY_BARD,
- JOB_BABY_DANCER,
- JOB_BABY_CRUSADER2,
- JOB_SUPER_BABY,
-
- JOB_TAEKWON,
- JOB_STAR_GLADIATOR,
- JOB_STAR_GLADIATOR2,
- JOB_SOUL_LINKER,
-
- JOB_GANGSI,
- JOB_DEATH_KNIGHT,
- JOB_DARK_COLLECTOR,
-
- JOB_RUNE_KNIGHT = 4054,
- JOB_WARLOCK,
- JOB_RANGER,
- JOB_ARCH_BISHOP,
- JOB_MECHANIC,
- JOB_GUILLOTINE_CROSS,
-
- JOB_RUNE_KNIGHT_T,
- JOB_WARLOCK_T,
- JOB_RANGER_T,
- JOB_ARCH_BISHOP_T,
- JOB_MECHANIC_T,
- JOB_GUILLOTINE_CROSS_T,
-
- JOB_ROYAL_GUARD,
- JOB_SORCERER,
- JOB_MINSTREL,
- JOB_WANDERER,
- JOB_SURA,
- JOB_GENETIC,
- JOB_SHADOW_CHASER,
-
- JOB_ROYAL_GUARD_T,
- JOB_SORCERER_T,
- JOB_MINSTREL_T,
- JOB_WANDERER_T,
- JOB_SURA_T,
- JOB_GENETIC_T,
- JOB_SHADOW_CHASER_T,
-
- JOB_RUNE_KNIGHT2,
- JOB_RUNE_KNIGHT_T2,
- JOB_ROYAL_GUARD2,
- JOB_ROYAL_GUARD_T2,
- JOB_RANGER2,
- JOB_RANGER_T2,
- JOB_MECHANIC2,
- JOB_MECHANIC_T2,
-
- JOB_BABY_RUNE = 4096,
- JOB_BABY_WARLOCK,
- JOB_BABY_RANGER,
- JOB_BABY_BISHOP,
- JOB_BABY_MECHANIC,
- JOB_BABY_CROSS,
-
- JOB_BABY_GUARD,
- JOB_BABY_SORCERER,
- JOB_BABY_MINSTREL,
- JOB_BABY_WANDERER,
- JOB_BABY_SURA,
- JOB_BABY_GENETIC,
- JOB_BABY_CHASER,
-
- JOB_BABY_RUNE2,
- JOB_BABY_GUARD2,
- JOB_BABY_RANGER2,
- JOB_BABY_MECHANIC2,
-
- JOB_SUPER_NOVICE_E = 4190,
- JOB_SUPER_BABY_E,
-
- JOB_KAGEROU = 4211,
- JOB_OBORO,
-
- JOB_MAX,
+ JOB_NOVICE,
+ JOB_SWORDMAN,
+ JOB_MAGE,
+ JOB_ARCHER,
+ JOB_ACOLYTE,
+ JOB_MERCHANT,
+ JOB_THIEF,
+ JOB_KNIGHT,
+ JOB_PRIEST,
+ JOB_WIZARD,
+ JOB_BLACKSMITH,
+ JOB_HUNTER,
+ JOB_ASSASSIN,
+ JOB_KNIGHT2,
+ JOB_CRUSADER,
+ JOB_MONK,
+ JOB_SAGE,
+ JOB_ROGUE,
+ JOB_ALCHEMIST,
+ JOB_BARD,
+ JOB_DANCER,
+ JOB_CRUSADER2,
+ JOB_WEDDING,
+ JOB_SUPER_NOVICE,
+ JOB_GUNSLINGER,
+ JOB_NINJA,
+ JOB_XMAS,
+ JOB_SUMMER,
+ JOB_MAX_BASIC,
+
+ JOB_NOVICE_HIGH = 4001,
+ JOB_SWORDMAN_HIGH,
+ JOB_MAGE_HIGH,
+ JOB_ARCHER_HIGH,
+ JOB_ACOLYTE_HIGH,
+ JOB_MERCHANT_HIGH,
+ JOB_THIEF_HIGH,
+ JOB_LORD_KNIGHT,
+ JOB_HIGH_PRIEST,
+ JOB_HIGH_WIZARD,
+ JOB_WHITESMITH,
+ JOB_SNIPER,
+ JOB_ASSASSIN_CROSS,
+ JOB_LORD_KNIGHT2,
+ JOB_PALADIN,
+ JOB_CHAMPION,
+ JOB_PROFESSOR,
+ JOB_STALKER,
+ JOB_CREATOR,
+ JOB_CLOWN,
+ JOB_GYPSY,
+ JOB_PALADIN2,
+
+ JOB_BABY,
+ JOB_BABY_SWORDMAN,
+ JOB_BABY_MAGE,
+ JOB_BABY_ARCHER,
+ JOB_BABY_ACOLYTE,
+ JOB_BABY_MERCHANT,
+ JOB_BABY_THIEF,
+ JOB_BABY_KNIGHT,
+ JOB_BABY_PRIEST,
+ JOB_BABY_WIZARD,
+ JOB_BABY_BLACKSMITH,
+ JOB_BABY_HUNTER,
+ JOB_BABY_ASSASSIN,
+ JOB_BABY_KNIGHT2,
+ JOB_BABY_CRUSADER,
+ JOB_BABY_MONK,
+ JOB_BABY_SAGE,
+ JOB_BABY_ROGUE,
+ JOB_BABY_ALCHEMIST,
+ JOB_BABY_BARD,
+ JOB_BABY_DANCER,
+ JOB_BABY_CRUSADER2,
+ JOB_SUPER_BABY,
+
+ JOB_TAEKWON,
+ JOB_STAR_GLADIATOR,
+ JOB_STAR_GLADIATOR2,
+ JOB_SOUL_LINKER,
+
+ JOB_GANGSI,
+ JOB_DEATH_KNIGHT,
+ JOB_DARK_COLLECTOR,
+
+ JOB_RUNE_KNIGHT = 4054,
+ JOB_WARLOCK,
+ JOB_RANGER,
+ JOB_ARCH_BISHOP,
+ JOB_MECHANIC,
+ JOB_GUILLOTINE_CROSS,
+
+ JOB_RUNE_KNIGHT_T,
+ JOB_WARLOCK_T,
+ JOB_RANGER_T,
+ JOB_ARCH_BISHOP_T,
+ JOB_MECHANIC_T,
+ JOB_GUILLOTINE_CROSS_T,
+
+ JOB_ROYAL_GUARD,
+ JOB_SORCERER,
+ JOB_MINSTREL,
+ JOB_WANDERER,
+ JOB_SURA,
+ JOB_GENETIC,
+ JOB_SHADOW_CHASER,
+
+ JOB_ROYAL_GUARD_T,
+ JOB_SORCERER_T,
+ JOB_MINSTREL_T,
+ JOB_WANDERER_T,
+ JOB_SURA_T,
+ JOB_GENETIC_T,
+ JOB_SHADOW_CHASER_T,
+
+ JOB_RUNE_KNIGHT2,
+ JOB_RUNE_KNIGHT_T2,
+ JOB_ROYAL_GUARD2,
+ JOB_ROYAL_GUARD_T2,
+ JOB_RANGER2,
+ JOB_RANGER_T2,
+ JOB_MECHANIC2,
+ JOB_MECHANIC_T2,
+
+ JOB_BABY_RUNE = 4096,
+ JOB_BABY_WARLOCK,
+ JOB_BABY_RANGER,
+ JOB_BABY_BISHOP,
+ JOB_BABY_MECHANIC,
+ JOB_BABY_CROSS,
+
+ JOB_BABY_GUARD,
+ JOB_BABY_SORCERER,
+ JOB_BABY_MINSTREL,
+ JOB_BABY_WANDERER,
+ JOB_BABY_SURA,
+ JOB_BABY_GENETIC,
+ JOB_BABY_CHASER,
+
+ JOB_BABY_RUNE2,
+ JOB_BABY_GUARD2,
+ JOB_BABY_RANGER2,
+ JOB_BABY_MECHANIC2,
+
+ JOB_SUPER_NOVICE_E = 4190,
+ JOB_SUPER_BABY_E,
+
+ JOB_KAGEROU = 4211,
+ JOB_OBORO,
+
+ JOB_MAX,
};
enum {
- SEX_FEMALE = 0,
- SEX_MALE,
- SEX_SERVER
+ SEX_FEMALE = 0,
+ SEX_MALE,
+ SEX_SERVER
};
// sanity checks...
diff --git a/src/common/mutex.c b/src/common/mutex.c
index 6b4f55119..813bef31b 100644
--- a/src/common/mutex.c
+++ b/src/common/mutex.c
@@ -15,26 +15,26 @@
#include "../common/timer.h"
#include "../common/mutex.h"
-struct ramutex{
+struct ramutex {
#ifdef WIN32
- CRITICAL_SECTION hMutex;
+ CRITICAL_SECTION hMutex;
#else
- pthread_mutex_t hMutex;
+ pthread_mutex_t hMutex;
#endif
};
-struct racond{
+struct racond {
#ifdef WIN32
- HANDLE events[2];
- ra_align(8) volatile LONG nWaiters;
- CRITICAL_SECTION waiters_lock;
+ HANDLE events[2];
+ ra_align(8) volatile LONG nWaiters;
+ CRITICAL_SECTION waiters_lock;
#define EVENT_COND_SIGNAL 0
#define EVENT_COND_BROADCAST 1
#else
- pthread_cond_t hCond;
+ pthread_cond_t hCond;
#endif
};
@@ -46,68 +46,73 @@ struct racond{
//
-ramutex ramutex_create(){
- struct ramutex *m;
-
- m = (struct ramutex*)aMalloc( sizeof(struct ramutex) );
- if(m == NULL){
- ShowFatalError("ramutex_create: OOM while allocating %u bytes.\n", sizeof(struct ramutex));
- return NULL;
- }
-
+ramutex ramutex_create()
+{
+ struct ramutex *m;
+
+ m = (struct ramutex *)aMalloc(sizeof(struct ramutex));
+ if (m == NULL) {
+ ShowFatalError("ramutex_create: OOM while allocating %u bytes.\n", sizeof(struct ramutex));
+ return NULL;
+ }
+
#ifdef WIN32
- InitializeCriticalSection(&m->hMutex);
+ InitializeCriticalSection(&m->hMutex);
#else
- pthread_mutex_init(&m->hMutex, NULL);
+ pthread_mutex_init(&m->hMutex, NULL);
#endif
-
- return m;
+
+ return m;
}//end: ramutex_create()
-void ramutex_destroy( ramutex m ){
+void ramutex_destroy(ramutex m)
+{
#ifdef WIN32
- DeleteCriticalSection(&m->hMutex);
+ DeleteCriticalSection(&m->hMutex);
#else
- pthread_mutex_destroy(&m->hMutex);
+ pthread_mutex_destroy(&m->hMutex);
#endif
- aFree(m);
+ aFree(m);
}//end: ramutex_destroy()
-void ramutex_lock( ramutex m ){
+void ramutex_lock(ramutex m)
+{
#ifdef WIN32
- EnterCriticalSection(&m->hMutex);
+ EnterCriticalSection(&m->hMutex);
#else
- pthread_mutex_lock(&m->hMutex);
+ pthread_mutex_lock(&m->hMutex);
#endif
}//end: ramutex_lock
-bool ramutex_trylock( ramutex m ){
+bool ramutex_trylock(ramutex m)
+{
#ifdef WIN32
- if(TryEnterCriticalSection(&m->hMutex) == TRUE)
- return true;
+ if (TryEnterCriticalSection(&m->hMutex) == TRUE)
+ return true;
- return false;
+ return false;
#else
- if(pthread_mutex_trylock(&m->hMutex) == 0)
- return true;
-
- return false;
+ if (pthread_mutex_trylock(&m->hMutex) == 0)
+ return true;
+
+ return false;
#endif
}//end: ramutex_trylock()
-void ramutex_unlock( ramutex m ){
+void ramutex_unlock(ramutex m)
+{
#ifdef WIN32
- LeaveCriticalSection(&m->hMutex);
+ LeaveCriticalSection(&m->hMutex);
#else
- pthread_mutex_unlock(&m->hMutex);
+ pthread_mutex_unlock(&m->hMutex);
#endif
}//end: ramutex_unlock()
@@ -116,131 +121,136 @@ void ramutex_unlock( ramutex m ){
///////////////
// Condition Variables
-//
+//
// Implementation:
//
-racond racond_create(){
- struct racond *c;
-
- c = (struct racond*)aMalloc( sizeof(struct racond) );
- if(c == NULL){
- ShowFatalError("racond_create: OOM while allocating %u bytes\n", sizeof(struct racond));
- return NULL;
- }
+racond racond_create()
+{
+ struct racond *c;
+
+ c = (struct racond *)aMalloc(sizeof(struct racond));
+ if (c == NULL) {
+ ShowFatalError("racond_create: OOM while allocating %u bytes\n", sizeof(struct racond));
+ return NULL;
+ }
#ifdef WIN32
- c->nWaiters = 0;
- c->events[ EVENT_COND_SIGNAL ] = CreateEvent( NULL, FALSE, FALSE, NULL );
- c->events[ EVENT_COND_BROADCAST ] = CreateEvent( NULL, TRUE, FALSE, NULL );
- InitializeCriticalSection( &c->waiters_lock );
+ c->nWaiters = 0;
+ c->events[ EVENT_COND_SIGNAL ] = CreateEvent(NULL, FALSE, FALSE, NULL);
+ c->events[ EVENT_COND_BROADCAST ] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ InitializeCriticalSection(&c->waiters_lock);
#else
- pthread_cond_init(&c->hCond, NULL);
+ pthread_cond_init(&c->hCond, NULL);
#endif
-
- return c;
+
+ return c;
}//end: racond_create()
-void racond_destroy( racond c ){
+void racond_destroy(racond c)
+{
#ifdef WIN32
- CloseHandle( c->events[ EVENT_COND_SIGNAL ] );
- CloseHandle( c->events[ EVENT_COND_BROADCAST ] );
- DeleteCriticalSection( &c->waiters_lock );
+ CloseHandle(c->events[ EVENT_COND_SIGNAL ]);
+ CloseHandle(c->events[ EVENT_COND_BROADCAST ]);
+ DeleteCriticalSection(&c->waiters_lock);
#else
- pthread_cond_destroy(&c->hCond);
+ pthread_cond_destroy(&c->hCond);
#endif
- aFree(c);
+ aFree(c);
}//end: racond_destroy()
-void racond_wait( racond c, ramutex m, sysint timeout_ticks){
+void racond_wait(racond c, ramutex m, sysint timeout_ticks)
+{
#ifdef WIN32
- register DWORD ms;
- int result;
- bool is_last = false;
+ register DWORD ms;
+ int result;
+ bool is_last = false;
- EnterCriticalSection(&c->waiters_lock);
- c->nWaiters++;
- LeaveCriticalSection(&c->waiters_lock);
+ EnterCriticalSection(&c->waiters_lock);
+ c->nWaiters++;
+ LeaveCriticalSection(&c->waiters_lock);
- if(timeout_ticks < 0)
- ms = INFINITE;
- else
- ms = (timeout_ticks > MAXDWORD) ? (MAXDWORD - 1) : (DWORD)timeout_ticks;
-
-
- // we can release the mutex (m) here, cause win's
- // manual reset events maintain state when used with
- // SetEvent()
- ramutex_unlock(m);
+ if (timeout_ticks < 0)
+ ms = INFINITE;
+ else
+ ms = (timeout_ticks > MAXDWORD) ? (MAXDWORD - 1) : (DWORD)timeout_ticks;
- result = WaitForMultipleObjects(2, c->events, FALSE, ms);
-
-
- EnterCriticalSection(&c->waiters_lock);
- c->nWaiters--;
- if( (result == WAIT_OBJECT_0 + EVENT_COND_BROADCAST) && (c->nWaiters == 0) )
- is_last = true; // Broadcast called!
- LeaveCriticalSection(&c->waiters_lock);
-
+ // we can release the mutex (m) here, cause win's
+ // manual reset events maintain state when used with
+ // SetEvent()
+ ramutex_unlock(m);
- // we are the last waiter that has to be notified, or to stop waiting
- // so we have to do a manual reset
- if(is_last == true)
- ResetEvent( c->events[EVENT_COND_BROADCAST] );
+ result = WaitForMultipleObjects(2, c->events, FALSE, ms);
- ramutex_lock(m);
+ EnterCriticalSection(&c->waiters_lock);
+ c->nWaiters--;
+ if ((result == WAIT_OBJECT_0 + EVENT_COND_BROADCAST) && (c->nWaiters == 0))
+ is_last = true; // Broadcast called!
+ LeaveCriticalSection(&c->waiters_lock);
+
+
+
+ // we are the last waiter that has to be notified, or to stop waiting
+ // so we have to do a manual reset
+ if (is_last == true)
+ ResetEvent(c->events[EVENT_COND_BROADCAST]);
+
+
+ ramutex_lock(m);
#else
- if(timeout_ticks < 0){
- pthread_cond_wait( &c->hCond, &m->hMutex );
- }else{
- struct timespec wtime;
- int64 exact_timeout = gettick() + timeout_ticks;
-
- wtime.tv_sec = exact_timeout/1000;
- wtime.tv_nsec = (exact_timeout%1000)*1000000;
-
- pthread_cond_timedwait( &c->hCond, &m->hMutex, &wtime);
- }
+ if (timeout_ticks < 0) {
+ pthread_cond_wait(&c->hCond, &m->hMutex);
+ } else {
+ struct timespec wtime;
+ int64 exact_timeout = gettick() + timeout_ticks;
+
+ wtime.tv_sec = exact_timeout/1000;
+ wtime.tv_nsec = (exact_timeout%1000)*1000000;
+
+ pthread_cond_timedwait(&c->hCond, &m->hMutex, &wtime);
+ }
#endif
}//end: racond_wait()
-void racond_signal( racond c ){
+void racond_signal(racond c)
+{
#ifdef WIN32
-// bool has_waiters = false;
-// EnterCriticalSection(&c->waiters_lock);
-// if(c->nWaiters > 0)
-// has_waiters = true;
-// LeaveCriticalSection(&c->waiters_lock);
-
-// if(has_waiters == true)
- SetEvent( c->events[ EVENT_COND_SIGNAL ] );
+ // bool has_waiters = false;
+ // EnterCriticalSection(&c->waiters_lock);
+ // if(c->nWaiters > 0)
+ // has_waiters = true;
+ // LeaveCriticalSection(&c->waiters_lock);
+
+ // if(has_waiters == true)
+ SetEvent(c->events[ EVENT_COND_SIGNAL ]);
#else
- pthread_cond_signal(&c->hCond);
+ pthread_cond_signal(&c->hCond);
#endif
}//end: racond_signal()
-void racond_broadcast( racond c ){
+void racond_broadcast(racond c)
+{
#ifdef WIN32
-// bool has_waiters = false;
-// EnterCriticalSection(&c->waiters_lock);
-// if(c->nWaiters > 0)
-// has_waiters = true;
-// LeaveCriticalSection(&c->waiters_lock);
-
-// if(has_waiters == true)
- SetEvent( c->events[ EVENT_COND_BROADCAST ] );
+ // bool has_waiters = false;
+ // EnterCriticalSection(&c->waiters_lock);
+ // if(c->nWaiters > 0)
+ // has_waiters = true;
+ // LeaveCriticalSection(&c->waiters_lock);
+
+ // if(has_waiters == true)
+ SetEvent(c->events[ EVENT_COND_BROADCAST ]);
#else
- pthread_cond_broadcast(&c->hCond);
+ pthread_cond_broadcast(&c->hCond);
#endif
}//end: racond_broadcast()
diff --git a/src/common/mutex.h b/src/common/mutex.h
index 1999627cd..abef731f4 100644
--- a/src/common/mutex.h
+++ b/src/common/mutex.h
@@ -1,5 +1,5 @@
// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// For more information, see LICENCE in the main folder
#ifndef _rA_MUTEX_H_
#define _rA_MUTEX_H_
@@ -9,67 +9,67 @@ typedef struct ramutex *ramutex; // Mutex
typedef struct racond *racond; // Condition Var
/**
- * Creates a Mutex
+ * Creates a Mutex
*
* @return not NULL
*/
ramutex ramutex_create();
-/**
+/**
* Destroys a Mutex
- *
+ *
* @param m - the mutex to destroy
*/
-void ramutex_destroy( ramutex m );
+void ramutex_destroy(ramutex m);
-/**
+/**
* Gets a lock
*
* @param m - the mutex to lock
*/
-void ramutex_lock( ramutex m);
+void ramutex_lock(ramutex m);
-/**
+/**
* Trys to get the Lock
- *
+ *
* @param m - the mutex try to lock
- *
+ *
* @return boolean (true = got the lock)
*/
-bool ramutex_trylock( ramutex m );
+bool ramutex_trylock(ramutex m);
-/**
+/**
* Unlocks a mutex
*
* @param m - the mutex to unlock
*/
-void ramutex_unlock( ramutex m);
+void ramutex_unlock(ramutex m);
-/**
+/**
* Creates a Condition variable
*
* @return not NULL
*/
racond racond_create();
-/**
+/**
* Destroy a Condition variable
*
* @param c - the condition varaible to destroy
*/
-void racond_destroy( racond c );
+void racond_destroy(racond c);
/**
* Waits Until state is signalled
- *
- * @param c - the condition var to wait for signalled state
+ *
+ * @param c - the condition var to wait for signalled state
* @param m - the mutex used for syncronization
* @param timeout_ticks - timeout in ticks ( -1 = INFINITE )
*/
-void racond_wait( racond c, ramutex m, sysint timeout_ticks);
+void racond_wait(racond c, ramutex m, sysint timeout_ticks);
-/**
+/**
* Sets the given condition var to signalled state
*
* @param c - condition var to set in signalled state.
@@ -77,16 +77,16 @@ void racond_wait( racond c, ramutex m, sysint timeout_ticks);
* @note:
* Only one waiter gets notified.
*/
-void racond_signal( racond c );
+void racond_signal(racond c);
-/**
+/**
* Sets notifys all waiting threads thats signalled.
* @param c - condition var to set in signalled state
- *
+ *
* @note:
* All Waiters getting notified.
- */
-void racond_broadcast( racond c );
+ */
+void racond_broadcast(racond c);
#endif
diff --git a/src/common/netbuffer.c b/src/common/netbuffer.c
index 57742d612..9ce13ffc3 100644
--- a/src/common/netbuffer.c
+++ b/src/common/netbuffer.c
@@ -26,10 +26,10 @@
#include "../common/netbuffer.h"
-//
+//
// Buffers are available in the following sizes:
-// 48, 192, 2048, 8192
-// 65536 (inter server connects may use it for charstatus struct..)
+// 48, 192, 2048, 8192
+// 65536 (inter server connects may use it for charstatus struct..)
//
@@ -42,180 +42,197 @@ static sysint *l_poolElemSize = NULL;
static mempool *l_pool = NULL;
-void netbuffer_init(){
- char localsection[32];
- raconf conf;
- sysint i;
-
- // Initialize Statistic counters:
- l_nEmergencyAllocations = 0;
-
- // Set localsection name according to running serverype.
- switch(SERVER_TYPE){
- case ATHENA_SERVER_LOGIN: strcpy(localsection, "login-netbuffer"); break;
- case ATHENA_SERVER_CHAR: strcpy(localsection, "char-netbuffer"); break;
- case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break;
- case ATHENA_SERVER_MAP: strcpy(localsection, "map-netbuffer"); break;
- default: strcpy(localsection, "unsupported_type"); break;
- }
-
-
- conf = raconf_parse("conf/network.conf");
- if(conf == NULL){
- ShowFatalError("Failed to Parse required Configuration (conf/network.conf)");
- exit(EXIT_FAILURE);
- }
-
- // Get Values from config file
- l_nPools = (sysint)raconf_getintEx(conf, localsection, "netbuffer", "num", 0);
- if(l_nPools == 0){
- ShowFatalError("Netbuffer (network.conf) failure - requires at least 1 Pool.\n");
- exit(EXIT_FAILURE);
- }
-
- // Allocate arrays.
- l_poolElemSize = (sysint*)aCalloc( l_nPools, sizeof(sysint) );
- l_pool = (mempool*)aCalloc( l_nPools, sizeof(mempool) );
-
-
- for(i = 0; i < l_nPools; i++){
- int64 num_prealloc, num_realloc;
- char key[32];
-
- sprintf(key, "pool_%u_size", (uint32)i+1);
- l_poolElemSize[i] = (sysint)raconf_getintEx(conf, localsection, "netbuffer", key, 4096);
- if(l_poolElemSize[i] < 32){
- ShowWarning("Netbuffer (network.conf) failure - minimum allowed buffer size is 32 byte) - fixed.\n");
- l_poolElemSize[i] = 32;
- }
-
- sprintf(key, "pool_%u_prealloc", (uint32)i+1);
- num_prealloc = raconf_getintEx(conf, localsection, "netbuffer", key, 150);
-
- sprintf(key, "pool_%u_realloc_step", (uint32)i+1);
- num_realloc = raconf_getintEx(conf, localsection, "netbuffer", key, 100);
-
- // Create Pool!
- sprintf(key, "Netbuffer %u", (uint32)l_poolElemSize[i]); // name.
-
- // Info
- ShowInfo("NetBuffer: Creating Pool %u (Prealloc: %u, Realloc Step: %u) - %0.2f MiB\n", l_poolElemSize[i], num_prealloc, num_realloc, (float)((sizeof(struct netbuf) + l_poolElemSize[i] - 32)* num_prealloc)/1024.0f/1024.0f);
-
- //
- // Size Calculation:
- // struct netbuf + requested buffer size - 32 (because the struct already contains 32 byte buffer space at the end of struct)
- l_pool[i] = mempool_create(key, (sizeof(struct netbuf) + l_poolElemSize[i] - 32), num_prealloc, num_realloc, NULL, NULL);
- if(l_pool[i] == NULL){
- ShowFatalError("Netbuffer: cannot create Pool for %u byte buffers.\n", l_poolElemSize[i]);
- // @leak: clean everything :D
- exit(EXIT_FAILURE);
- }
-
- }//
-
-
- raconf_destroy(conf);
+void netbuffer_init()
+{
+ char localsection[32];
+ raconf conf;
+ sysint i;
+
+ // Initialize Statistic counters:
+ l_nEmergencyAllocations = 0;
+
+ // Set localsection name according to running serverype.
+ switch (SERVER_TYPE) {
+ case ATHENA_SERVER_LOGIN:
+ strcpy(localsection, "login-netbuffer");
+ break;
+ case ATHENA_SERVER_CHAR:
+ strcpy(localsection, "char-netbuffer");
+ break;
+ case ATHENA_SERVER_INTER:
+ strcpy(localsection, "inter-netbuffer");
+ break;
+ case ATHENA_SERVER_MAP:
+ strcpy(localsection, "map-netbuffer");
+ break;
+ default:
+ strcpy(localsection, "unsupported_type");
+ break;
+ }
+
+
+ conf = raconf_parse("conf/network.conf");
+ if (conf == NULL) {
+ ShowFatalError("Failed to Parse required Configuration (conf/network.conf)");
+ exit(EXIT_FAILURE);
+ }
+
+ // Get Values from config file
+ l_nPools = (sysint)raconf_getintEx(conf, localsection, "netbuffer", "num", 0);
+ if (l_nPools == 0) {
+ ShowFatalError("Netbuffer (network.conf) failure - requires at least 1 Pool.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Allocate arrays.
+ l_poolElemSize = (sysint *)aCalloc(l_nPools, sizeof(sysint));
+ l_pool = (mempool *)aCalloc(l_nPools, sizeof(mempool));
+
+
+ for (i = 0; i < l_nPools; i++) {
+ int64 num_prealloc, num_realloc;
+ char key[32];
+
+ sprintf(key, "pool_%u_size", (uint32)i+1);
+ l_poolElemSize[i] = (sysint)raconf_getintEx(conf, localsection, "netbuffer", key, 4096);
+ if (l_poolElemSize[i] < 32) {
+ ShowWarning("Netbuffer (network.conf) failure - minimum allowed buffer size is 32 byte) - fixed.\n");
+ l_poolElemSize[i] = 32;
+ }
+
+ sprintf(key, "pool_%u_prealloc", (uint32)i+1);
+ num_prealloc = raconf_getintEx(conf, localsection, "netbuffer", key, 150);
+
+ sprintf(key, "pool_%u_realloc_step", (uint32)i+1);
+ num_realloc = raconf_getintEx(conf, localsection, "netbuffer", key, 100);
+
+ // Create Pool!
+ sprintf(key, "Netbuffer %u", (uint32)l_poolElemSize[i]); // name.
+
+ // Info
+ ShowInfo("NetBuffer: Creating Pool %u (Prealloc: %u, Realloc Step: %u) - %0.2f MiB\n", l_poolElemSize[i], num_prealloc, num_realloc, (float)((sizeof(struct netbuf) + l_poolElemSize[i] - 32)* num_prealloc)/1024.0f/1024.0f);
+
+ //
+ // Size Calculation:
+ // struct netbuf + requested buffer size - 32 (because the struct already contains 32 byte buffer space at the end of struct)
+ l_pool[i] = mempool_create(key, (sizeof(struct netbuf) + l_poolElemSize[i] - 32), num_prealloc, num_realloc, NULL, NULL);
+ if (l_pool[i] == NULL) {
+ ShowFatalError("Netbuffer: cannot create Pool for %u byte buffers.\n", l_poolElemSize[i]);
+ // @leak: clean everything :D
+ exit(EXIT_FAILURE);
+ }
+
+ }//
+
+
+ raconf_destroy(conf);
}//end: netbuffer_init()
-void netbuffer_final(){
- sysint i;
-
- if(l_nPools > 0){
- /// .. finalize mempools
- for(i = 0; i < l_nPools; i++){
- mempool_stats stats = mempool_get_stats(l_pool[i]);
-
- ShowInfo("Netbuffer: Freeing Pool %u (Peak Usage: %u, Realloc Events: %u)\n", l_poolElemSize[i], stats.peak_nodes_used, stats.num_realloc_events);
-
- mempool_destroy(l_pool[i]);
- }
-
- if(l_nEmergencyAllocations > 0){
- ShowWarning("Netbuffer: did %u Emergency Allocations, please tune your network.conf!\n", l_nEmergencyAllocations);
- l_nEmergencyAllocations = 0;
- }
-
- aFree(l_poolElemSize); l_poolElemSize = NULL;
- aFree(l_pool); l_pool = NULL;
- l_nPools = 0;
- }
-
-
+void netbuffer_final()
+{
+ sysint i;
+
+ if (l_nPools > 0) {
+ /// .. finalize mempools
+ for (i = 0; i < l_nPools; i++) {
+ mempool_stats stats = mempool_get_stats(l_pool[i]);
+
+ ShowInfo("Netbuffer: Freeing Pool %u (Peak Usage: %u, Realloc Events: %u)\n", l_poolElemSize[i], stats.peak_nodes_used, stats.num_realloc_events);
+
+ mempool_destroy(l_pool[i]);
+ }
+
+ if (l_nEmergencyAllocations > 0) {
+ ShowWarning("Netbuffer: did %u Emergency Allocations, please tune your network.conf!\n", l_nEmergencyAllocations);
+ l_nEmergencyAllocations = 0;
+ }
+
+ aFree(l_poolElemSize);
+ l_poolElemSize = NULL;
+ aFree(l_pool);
+ l_pool = NULL;
+ l_nPools = 0;
+ }
+
+
}//end: netbuffer_final()
-netbuf netbuffer_get( sysint sz ){
- sysint i;
- netbuf nb = NULL;
-
- // Search an appropriate pool
- for(i = 0; i < l_nPools; i++){
- if(sz <= l_poolElemSize[i]){
- // match
-
- nb = (netbuf)mempool_node_get(l_pool[i]);
- nb->pool = i;
-
- break;
- }
- }
-
- // No Bufferpool found that mets there quirements?.. (thats bad..)
- if(nb == NULL){
- ShowWarning("Netbuffer: get(%u): => no appropriate pool found - emergency allocation required.\n", sz);
- ShowWarning("Please reconfigure your network.conf!");
-
- InterlockedIncrement(&l_nEmergencyAllocations);
-
- // .. better to check (netbuf struct provides 32 byte bufferspace itself.
- if(sz < 32) sz = 32;
-
- // allocate memory using malloc ..
- while(1){
- nb = (netbuf) aMalloc( (sizeof(struct netbuf) + sz - 32) );
- if(nb != NULL){
- memset(nb, 0x00, (sizeof(struct netbuf) + sz - 32) ); // zero memory! (to enforce commit @ os.)
- nb->pool = -1; // emergency alloc.
- break;
- }
-
- rathread_yield();
- }// spin allocation.
-
- }
-
-
- nb->refcnt = 1; // Initial refcount is 1
-
- return nb;
+netbuf netbuffer_get(sysint sz)
+{
+ sysint i;
+ netbuf nb = NULL;
+
+ // Search an appropriate pool
+ for (i = 0; i < l_nPools; i++) {
+ if (sz <= l_poolElemSize[i]) {
+ // match
+
+ nb = (netbuf)mempool_node_get(l_pool[i]);
+ nb->pool = i;
+
+ break;
+ }
+ }
+
+ // No Bufferpool found that mets there quirements?.. (thats bad..)
+ if (nb == NULL) {
+ ShowWarning("Netbuffer: get(%u): => no appropriate pool found - emergency allocation required.\n", sz);
+ ShowWarning("Please reconfigure your network.conf!");
+
+ InterlockedIncrement(&l_nEmergencyAllocations);
+
+ // .. better to check (netbuf struct provides 32 byte bufferspace itself.
+ if (sz < 32) sz = 32;
+
+ // allocate memory using malloc ..
+ while (1) {
+ nb = (netbuf) aMalloc((sizeof(struct netbuf) + sz - 32));
+ if (nb != NULL) {
+ memset(nb, 0x00, (sizeof(struct netbuf) + sz - 32)); // zero memory! (to enforce commit @ os.)
+ nb->pool = -1; // emergency alloc.
+ break;
+ }
+
+ rathread_yield();
+ }// spin allocation.
+
+ }
+
+
+ nb->refcnt = 1; // Initial refcount is 1
+
+ return nb;
}//end: netbuffer_get()
-void netbuffer_put( netbuf nb ){
-
- // Decrement reference counter, if > 0 do nothing :)
- if( InterlockedDecrement(&nb->refcnt) > 0 )
- return;
-
- // Is this buffer an emergency allocated buffer?
- if(nb->pool == -1){
- aFree(nb);
- return;
- }
-
-
- // Otherwise its a normal mempool based buffer
- // return it to the according mempool:
- mempool_node_put( l_pool[nb->pool], nb);
-
-
+void netbuffer_put(netbuf nb)
+{
+
+ // Decrement reference counter, if > 0 do nothing :)
+ if (InterlockedDecrement(&nb->refcnt) > 0)
+ return;
+
+ // Is this buffer an emergency allocated buffer?
+ if (nb->pool == -1) {
+ aFree(nb);
+ return;
+ }
+
+
+ // Otherwise its a normal mempool based buffer
+ // return it to the according mempool:
+ mempool_node_put(l_pool[nb->pool], nb);
+
+
}//end: netbuffer_put()
-void netbuffer_incref( netbuf nb ){
-
- InterlockedIncrement(&nb->refcnt);
-
+void netbuffer_incref(netbuf nb)
+{
+
+ InterlockedIncrement(&nb->refcnt);
+
}//end: netbuf_incref()
diff --git a/src/common/netbuffer.h b/src/common/netbuffer.h
index 844241226..a4feb7287 100644
--- a/src/common/netbuffer.h
+++ b/src/common/netbuffer.h
@@ -6,37 +6,37 @@
#include "../common/cbasetypes.h"
-typedef struct netbuf{
- sysint pool; // The pool ID this buffer belongs to,
- // is set to -1 if its an emergency allocated buffer
-
- struct netbuf *next; // Used by Network system.
-
- volatile int32 refcnt; // Internal Refcount, it gets lowered every call to netbuffer_put,
- // if its getting zero, the buffer will returned back to the pool
- // and can be reused.
-
- int32 dataPos; // Current Offset
- // Used only for Reading (recv job)
- // write cases are using the sessions local datapos member due to
- // shared write buffer support.
-
- int32 dataLen; // read buffer case:
- // The length expected to read to.
- // when this->dataPos == dateLen, read job has been completed.
- // write buffer case:
- // The lngth of data in te buffer
- // when s->dataPos == dataLen, write job has been completed
- //
- // Note:
- // leftBytes = (dateLen - dataPos)
- //
- // Due to shared buffer support
- // dataPos gets not used in write case (each connection has its local offset)
- //
-
- // The Bufferspace itself.
- char buf[32];
+typedef struct netbuf {
+ sysint pool; // The pool ID this buffer belongs to,
+ // is set to -1 if its an emergency allocated buffer
+
+ struct netbuf *next; // Used by Network system.
+
+ volatile int32 refcnt; // Internal Refcount, it gets lowered every call to netbuffer_put,
+ // if its getting zero, the buffer will returned back to the pool
+ // and can be reused.
+
+ int32 dataPos; // Current Offset
+ // Used only for Reading (recv job)
+ // write cases are using the sessions local datapos member due to
+ // shared write buffer support.
+
+ int32 dataLen; // read buffer case:
+ // The length expected to read to.
+ // when this->dataPos == dateLen, read job has been completed.
+ // write buffer case:
+ // The lngth of data in te buffer
+ // when s->dataPos == dataLen, write job has been completed
+ //
+ // Note:
+ // leftBytes = (dateLen - dataPos)
+ //
+ // Due to shared buffer support
+ // dataPos gets not used in write case (each connection has its local offset)
+ //
+
+ // The Bufferspace itself.
+ char buf[32];
} *netbuf;
@@ -47,29 +47,29 @@ void netbuffer_final();
* Gets a netbuffer that has atleast (sz) byes space.
*
* @note: The netbuffer system guarantees that youll always recevie a buffer.
- * no check for null is required!
+ * no check for null is required!
*
* @param sz - minimum size needed.
*
* @return pointer to netbuf struct
*/
-netbuf netbuffer_get( sysint sz );
+netbuf netbuffer_get(sysint sz);
-/**
+/**
* Returns the given netbuffer (decreases refcount, if its 0 - the buffer will get returned to the pool)
*
- * @param buf - the buffer to return
+ * @param buf - the buffer to return
*/
-void netbuffer_put( netbuf buf );
+void netbuffer_put(netbuf buf);
-/**
- * Increases the Refcount on the given buffer
+/**
+ * Increases the Refcount on the given buffer
* (used for areasends .. etc)
*
*/
-void netbuffer_incref( netbuf buf );
+void netbuffer_incref(netbuf buf);
// Some Useful macros
diff --git a/src/common/network.c b/src/common/network.c
index 1f1621363..1c968200d 100644
--- a/src/common/network.c
+++ b/src/common/network.c
@@ -51,1011 +51,1020 @@ static bool onSend(int32 fd);
#define _network_free_netbuf_async( buf ) add_timer( 0, _network_async_free_netbuf_proc, 0, (intptr_t) buf)
-static int _network_async_free_netbuf_proc(int tid, unsigned int tick, int id, intptr_t data){
- // netbuf is in data
- netbuffer_put( (netbuf)data );
+static int _network_async_free_netbuf_proc(int tid, unsigned int tick, int id, intptr_t data)
+{
+ // netbuf is in data
+ netbuffer_put((netbuf)data);
- return 0;
+ return 0;
}//end: _network_async_free_netbuf_proc()
-void network_init(){
- SESSION *s;
- int32 i;
-
- memset(g_Session, 0x00, (sizeof(SESSION) * MAXCONN) );
-
- for(i = 0; i < MAXCONN; i++){
- s = &g_Session[i];
-
- s->type = NST_FREE;
- s->disconnect_in_progress = false;
-
- }
-
- // Initialize the correspondig event dispatcher
- evdp_init();
-
- //
- add_timer_func_list(_network_async_free_netbuf_proc, "_network_async_free_netbuf_proc");
-
+void network_init()
+{
+ SESSION *s;
+ int32 i;
+
+ memset(g_Session, 0x00, (sizeof(SESSION) * MAXCONN));
+
+ for (i = 0; i < MAXCONN; i++) {
+ s = &g_Session[i];
+
+ s->type = NST_FREE;
+ s->disconnect_in_progress = false;
+
+ }
+
+ // Initialize the correspondig event dispatcher
+ evdp_init();
+
+ //
+ add_timer_func_list(_network_async_free_netbuf_proc, "_network_async_free_netbuf_proc");
+
}//end: network_init()
-void network_final(){
+void network_final()
+{
+
+ // @TODO:
+ // .. disconnect and cleanup everything!
- // @TODO:
- // .. disconnect and cleanup everything!
-
- evdp_final();
+ evdp_final();
}//end: network_final()
-void network_do(){
- struct EVDP_EVENT l_events[EVENTS_PER_CYCLE];
- register struct EVDP_EVENT *ev;
- register int n, nfds;
- register SESSION *s;
-
- nfds = evdp_wait( l_events, EVENTS_PER_CYCLE, 1000); // @TODO: timer_getnext()
-
- for(n = 0; n < nfds; n++){
- ev = &l_events[n];
- s = &g_Session[ ev->fd ];
-
- if(ev->events & EVDP_EVENT_HUP){
- network_disconnect( ev->fd );
- continue; // no further event processing.
- }// endif vent is HUP (disconnect)
-
-
- if(ev->events & EVDP_EVENT_IN){
-
- if(s->onRecv != NULL){
- if( false == s->onRecv(ev->fd) ){
- network_disconnect(ev->fd);
- continue; // ..
- }
- }else{
- ShowError("network_do: fd #%u has no onRecv proc set. - disconnecting\n", ev->fd);
- network_disconnect(ev->fd);
- continue;
- }
-
- }// endif event is IN (recv)
-
-
- if(ev->events & EVDP_EVENT_OUT){
- if(s->onSend != NULL){
- if( false == s->onSend(ev->fd) ){
- network_disconnect(ev->fd);
- continue;
- }
- }else{
- ShowError("network_do: fd #%u has no onSend proc set. - disconnecting\n", ev->fd);
- network_disconnect(ev->fd);
- continue;
- }
- }// endif event is OUT (send)
-
- }//endfor
-
+void network_do()
+{
+ struct EVDP_EVENT l_events[EVENTS_PER_CYCLE];
+ register struct EVDP_EVENT *ev;
+ register int n, nfds;
+ register SESSION *s;
+
+ nfds = evdp_wait(l_events, EVENTS_PER_CYCLE, 1000); // @TODO: timer_getnext()
+
+ for (n = 0; n < nfds; n++) {
+ ev = &l_events[n];
+ s = &g_Session[ ev->fd ];
+
+ if (ev->events & EVDP_EVENT_HUP) {
+ network_disconnect(ev->fd);
+ continue; // no further event processing.
+ }// endif vent is HUP (disconnect)
+
+
+ if (ev->events & EVDP_EVENT_IN) {
+
+ if (s->onRecv != NULL) {
+ if (false == s->onRecv(ev->fd)) {
+ network_disconnect(ev->fd);
+ continue; // ..
+ }
+ } else {
+ ShowError("network_do: fd #%u has no onRecv proc set. - disconnecting\n", ev->fd);
+ network_disconnect(ev->fd);
+ continue;
+ }
+
+ }// endif event is IN (recv)
+
+
+ if (ev->events & EVDP_EVENT_OUT) {
+ if (s->onSend != NULL) {
+ if (false == s->onSend(ev->fd)) {
+ network_disconnect(ev->fd);
+ continue;
+ }
+ } else {
+ ShowError("network_do: fd #%u has no onSend proc set. - disconnecting\n", ev->fd);
+ network_disconnect(ev->fd);
+ continue;
+ }
+ }// endif event is OUT (send)
+
+ }//endfor
+
}//end: network_do()
-static bool _setnonblock(int32 fd){
- int flags = fcntl(fd, F_GETFL, 0);
- if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0)
- return false;
+static bool _setnonblock(int32 fd)
+{
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0)
+ return false;
- return true;
+ return true;
}//end: _setnonblock()
-static bool _network_accept(int32 fd){
- SESSION *listener = &g_Session[fd];
- SESSION *s;
- union{
- struct sockaddr_in v4;
+static bool _network_accept(int32 fd)
+{
+ SESSION *listener = &g_Session[fd];
+ SESSION *s;
+ union {
+ struct sockaddr_in v4;
#ifdef ENABLE_IPV6
- struct sockaddr_in6 v6;
+ struct sockaddr_in6 v6;
#endif
- } _addr;
- int newfd;
- socklen_t addrlen;
- struct sockaddr *addr;
-
- // Accept until OS returns - nothing to accept anymore
- // - this is required due to our EVDP abstraction. (which handles on listening sockets similar to epoll's EPOLLET flag.)
- while(1){
+ } _addr;
+ int newfd;
+ socklen_t addrlen;
+ struct sockaddr *addr;
+
+ // Accept until OS returns - nothing to accept anymore
+ // - this is required due to our EVDP abstraction. (which handles on listening sockets similar to epoll's EPOLLET flag.)
+ while (1) {
#ifdef ENABLE_IPV6
- if(listener->v6 == true){
- addrlen = sizeof(_addr.v6);
- addr = (struct sockaddr*)&_addr.v6;
- }else{
+ if (listener->v6 == true) {
+ addrlen = sizeof(_addr.v6);
+ addr = (struct sockaddr *)&_addr.v6;
+ } else {
#endif
- addrlen = sizeof(_addr.v4);
- addr = (struct sockaddr*)&_addr.v4;
+ addrlen = sizeof(_addr.v4);
+ addr = (struct sockaddr *)&_addr.v4;
#ifdef ENABLE_IPV6
- }
+ }
#endif
#ifdef HAVE_ACCEPT4
- newfd = accept4(fd, addr, &addrlen, SOCK_NONBLOCK);
+ newfd = accept4(fd, addr, &addrlen, SOCK_NONBLOCK);
#else
- newfd = accept(fd, addr, &addrlen);
+ newfd = accept(fd, addr, &addrlen);
#endif
- if(newfd == -1){
- if(errno == EAGAIN || errno == EWOULDBLOCK)
- break; // this is fully valid & whished., se explaination on top of while(1)
-
- // Otherwis .. we have serious problems :( seems tahat our listner has gone away..
- // @TODO handle this ..
- ShowError("_network_accept: accept() returned error. closing listener. (errno: %u / %s)\n", errno, strerror(errno));
+ if (newfd == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ break; // this is fully valid & whished., se explaination on top of while(1)
+
+ // Otherwis .. we have serious problems :( seems tahat our listner has gone away..
+ // @TODO handle this ..
+ ShowError("_network_accept: accept() returned error. closing listener. (errno: %u / %s)\n", errno, strerror(errno));
- return false; // will call disconnect after return.
- //break;
- }
+ return false; // will call disconnect after return.
+ //break;
+ }
#ifndef HAVE_ACCEPT4 // no accept4 means, we have to set nonblock by ourself. ..
- if(_setnonblock(newfd) == false){
- ShowError("_network_accept: failed to set newly accepted connection nonblocking (errno: %u / %s). - disconnecting.\n", errno, strerror(errno));
- close(newfd);
- continue;
- }
+ if (_setnonblock(newfd) == false) {
+ ShowError("_network_accept: failed to set newly accepted connection nonblocking (errno: %u / %s). - disconnecting.\n", errno, strerror(errno));
+ close(newfd);
+ continue;
+ }
#endif
- // Check connection limits.
- if(newfd >= MAXCONN){
- ShowError("_network_accept: failed to accept connection - MAXCONN (%u) exceeded.\n", MAXCONN);
- close(newfd);
- continue; // we have to loop over the events (and disconnect them too ..) but otherwise we would leak event notifications.
- }
-
-
- // Create new Session.
- s = &g_Session[newfd];
- s->type = NST_CLIENT;
-
- // The new connection inherits listenr's handlers.
- s->onDisconnect = listener->onDisconnect;
- s->onConnect = listener->onConnect; // maybe useless but .. fear the future .. :~
-
- // Register the new connection @ EVDP
- if( evdp_addclient(newfd, &s->evdp_data) == false){
- ShowError("_network_accept: failed to accept connection - event subsystem returned an error.\n");
- close(newfd);
- s->type = NST_FREE;
- }
-
- // Call the onConnect handler on the listener.
- if( listener->onConnect(newfd) == false ){
- // Resfused by onConnect handler..
- evdp_remove(newfd, &s->evdp_data);
-
- close(newfd);
- s->type = NST_FREE;
-
- s->data = NULL; // be on the safe side ~ !
- continue;
- }
-
-
- }
-
- return true;
+ // Check connection limits.
+ if (newfd >= MAXCONN) {
+ ShowError("_network_accept: failed to accept connection - MAXCONN (%u) exceeded.\n", MAXCONN);
+ close(newfd);
+ continue; // we have to loop over the events (and disconnect them too ..) but otherwise we would leak event notifications.
+ }
+
+
+ // Create new Session.
+ s = &g_Session[newfd];
+ s->type = NST_CLIENT;
+
+ // The new connection inherits listenr's handlers.
+ s->onDisconnect = listener->onDisconnect;
+ s->onConnect = listener->onConnect; // maybe useless but .. fear the future .. :~
+
+ // Register the new connection @ EVDP
+ if (evdp_addclient(newfd, &s->evdp_data) == false) {
+ ShowError("_network_accept: failed to accept connection - event subsystem returned an error.\n");
+ close(newfd);
+ s->type = NST_FREE;
+ }
+
+ // Call the onConnect handler on the listener.
+ if (listener->onConnect(newfd) == false) {
+ // Resfused by onConnect handler..
+ evdp_remove(newfd, &s->evdp_data);
+
+ close(newfd);
+ s->type = NST_FREE;
+
+ s->data = NULL; // be on the safe side ~ !
+ continue;
+ }
+
+
+ }
+
+ return true;
}//end: _network_accept()
-void network_disconnect(int32 fd){
- SESSION *s = &g_Session[fd];
- netbuf b, bn;
-
- // Prevent recursive calls
- // by wrong implemented on disconnect handlers.. and such..
- if(s->disconnect_in_progress == true)
- return;
-
- s->disconnect_in_progress = true;
-
-
- // Disconnect Todo:
- // - Call onDisconnect Handler
- // - Release all Assigned buffers.
- // - remove from event system (notifications)
- // - cleanup session structure
- // - close connection.
- //
-
- if(s->onDisconnect != NULL &&
- s->type != NST_LISTENER){
-
- s->onDisconnect( fd );
- }
-
- // Read Buffer
- if(s->read.buf != NULL){
- netbuffer_put(s->read.buf);
- s->read.buf = NULL;
- }
-
- // Write Buffer(s)
- b = s->write.buf;
- while(1){
- if(b == NULL) break;
-
- bn = b->next;
-
- netbuffer_put(b);
-
- b = bn;
- }
- s->write.buf = NULL;
- s->write.buf_last = NULL;
-
- s->write.n_outstanding = 0;
- s->write.max_outstanding = 0;
-
-
- // Remove from event system.
- evdp_remove(fd, &s->evdp_data);
-
- // Cleanup Session Structure.
- s->type = NST_FREE;
- s->data = NULL; // no application level data assigned
- s->disconnect_in_progress = false;
-
-
- // Close connection
- close(fd);
-
+void network_disconnect(int32 fd)
+{
+ SESSION *s = &g_Session[fd];
+ netbuf b, bn;
+
+ // Prevent recursive calls
+ // by wrong implemented on disconnect handlers.. and such..
+ if (s->disconnect_in_progress == true)
+ return;
+
+ s->disconnect_in_progress = true;
+
+
+ // Disconnect Todo:
+ // - Call onDisconnect Handler
+ // - Release all Assigned buffers.
+ // - remove from event system (notifications)
+ // - cleanup session structure
+ // - close connection.
+ //
+
+ if (s->onDisconnect != NULL &&
+ s->type != NST_LISTENER) {
+
+ s->onDisconnect(fd);
+ }
+
+ // Read Buffer
+ if (s->read.buf != NULL) {
+ netbuffer_put(s->read.buf);
+ s->read.buf = NULL;
+ }
+
+ // Write Buffer(s)
+ b = s->write.buf;
+ while (1) {
+ if (b == NULL) break;
+
+ bn = b->next;
+
+ netbuffer_put(b);
+
+ b = bn;
+ }
+ s->write.buf = NULL;
+ s->write.buf_last = NULL;
+
+ s->write.n_outstanding = 0;
+ s->write.max_outstanding = 0;
+
+
+ // Remove from event system.
+ evdp_remove(fd, &s->evdp_data);
+
+ // Cleanup Session Structure.
+ s->type = NST_FREE;
+ s->data = NULL; // no application level data assigned
+ s->disconnect_in_progress = false;
+
+
+ // Close connection
+ close(fd);
+
}//end: network_disconnect()
-int32 network_addlistener(bool v6, const char *addr, uint16 port){
- SESSION *s;
- int optval, fd;
+int32 network_addlistener(bool v6, const char *addr, uint16 port)
+{
+ SESSION *s;
+ int optval, fd;
#if !defined(ENABLE_IPV6)
- if(v6 == true){
- ShowError("network_addlistener(%c, '%s', %u): this release has no IPV6 support.\n", (v6==true?'t':'f'), addr, port);
- return -1;
- }
+ if (v6 == true) {
+ ShowError("network_addlistener(%c, '%s', %u): this release has no IPV6 support.\n", (v6==true?'t':'f'), addr, port);
+ return -1;
+ }
#endif
#ifdef ENABLE_IPV6
- if(v6 == true)
- fd = socket(AF_INET6, SOCK_STREAM, 0);
- else
+ if (v6 == true)
+ fd = socket(AF_INET6, SOCK_STREAM, 0);
+ else
#endif
- fd = socket(AF_INET, SOCK_STREAM, 0);
-
- // Error?
- if(fd == -1){
- ShowError("network_addlistener(%c, '%s', %u): socket() failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- return -1;
- }
-
- // Too many connections?
- if(fd >= MAXCONN){
- ShowError("network_addlistener(%c, '%s', %u): cannot create listener, exceeds more than supported connections (%u).\n", (v6==true?'t':'f'), addr, port, MAXCONN);
- close(fd);
- return -1;
- }
-
-
- s = &g_Session[fd];
- if(s->type != NST_FREE){ // additional checks.. :)
- ShowError("network_addlistener(%c, '%s', %u): failed, got fd #%u which is already in use in local session table?!\n", (v6==true?'t':'f'), addr, port, fd);
- close(fd);
- return -1;
- }
-
-
- // Fill ip addr structs
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+
+ // Error?
+ if (fd == -1) {
+ ShowError("network_addlistener(%c, '%s', %u): socket() failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ return -1;
+ }
+
+ // Too many connections?
+ if (fd >= MAXCONN) {
+ ShowError("network_addlistener(%c, '%s', %u): cannot create listener, exceeds more than supported connections (%u).\n", (v6==true?'t':'f'), addr, port, MAXCONN);
+ close(fd);
+ return -1;
+ }
+
+
+ s = &g_Session[fd];
+ if (s->type != NST_FREE) { // additional checks.. :)
+ ShowError("network_addlistener(%c, '%s', %u): failed, got fd #%u which is already in use in local session table?!\n", (v6==true?'t':'f'), addr, port, fd);
+ close(fd);
+ return -1;
+ }
+
+
+ // Fill ip addr structs
#ifdef ENABLE_IPV6
- if(v6 == true){
- memset(&s->addr.v6, 0x00, sizeof(s->addr.v6));
- s->addr.v6.sin6_family = AF_INET6;
- s->addr.v6.sin6_port = htons(port);
- if(inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1){
- ShowError("network_addlistener(%c, '%s', %u): failed to parse the given IPV6 address.\n", (v6==true?'t':'f'), addr, port);
- close(fd);
- return -1;
- }
-
- }else{
+ if (v6 == true) {
+ memset(&s->addr.v6, 0x00, sizeof(s->addr.v6));
+ s->addr.v6.sin6_family = AF_INET6;
+ s->addr.v6.sin6_port = htons(port);
+ if (inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1) {
+ ShowError("network_addlistener(%c, '%s', %u): failed to parse the given IPV6 address.\n", (v6==true?'t':'f'), addr, port);
+ close(fd);
+ return -1;
+ }
+
+ } else {
#endif
- memset(&s->addr.v4, 0x00, sizeof(s->addr.v4));
- s->addr.v4.sin_family = AF_INET;
- s->addr.v4.sin_port = htons(port);
- s->addr.v4.sin_addr.s_addr = inet_addr(addr);
+ memset(&s->addr.v4, 0x00, sizeof(s->addr.v4));
+ s->addr.v4.sin_family = AF_INET;
+ s->addr.v4.sin_port = htons(port);
+ s->addr.v4.sin_addr.s_addr = inet_addr(addr);
#ifdef ENABLE_IPV6
- }
+ }
#endif
-
- // if OS has support for SO_REUSEADDR, apply the flag
- // so the address could be used when there're still time_wait sockets outstanding from previous application run.
+
+ // if OS has support for SO_REUSEADDR, apply the flag
+ // so the address could be used when there're still time_wait sockets outstanding from previous application run.
#ifdef SO_REUSEADDR
- optval=1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ optval=1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
#endif
- // Bind
+ // Bind
#ifdef ENABLE_IPV6
- if(v6 == true){
- if( bind(fd, (struct sockaddr*)&s->addr.v6, sizeof(s->addr.v6)) == -1) {
- ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
- }else{
+ if (v6 == true) {
+ if (bind(fd, (struct sockaddr *)&s->addr.v6, sizeof(s->addr.v6)) == -1) {
+ ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ } else {
#endif
- if( bind(fd, (struct sockaddr*)&s->addr.v4, sizeof(s->addr.v4)) == -1) {
- ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
+ if (bind(fd, (struct sockaddr *)&s->addr.v4, sizeof(s->addr.v4)) == -1) {
+ ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
#ifdef ENABLE_IPV6
- }
+ }
#endif
- if( listen(fd, l_ListenBacklog) == -1){
- ShowError("network_addlistener(%c, '%s', %u): listen failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
-
-
- // Set to nonblock!
- if(_setnonblock(fd) == false){
- ShowError("network_addlistener(%c, '%s', %u): cannot set to nonblock (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
-
-
- // Rgister @ evdp.
- if( evdp_addlistener(fd, &s->evdp_data) != true){
- ShowError("network_addlistener(%c, '%s', %u): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port);
- close(fd);
- return -1;
- }
-
-
- // Apply flags on Session array for this conneciton.
- if(v6 == true) s->v6 = true;
- else s->v6 = false;
-
- s->type = NST_LISTENER;
- s->onRecv = _network_accept;
-
- ShowStatus("Added Listener on '%s':%u\n", addr, port, (v6==true ? "(ipv6)":"(ipv4)") );
-
- return fd;
+ if (listen(fd, l_ListenBacklog) == -1) {
+ ShowError("network_addlistener(%c, '%s', %u): listen failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+
+ // Set to nonblock!
+ if (_setnonblock(fd) == false) {
+ ShowError("network_addlistener(%c, '%s', %u): cannot set to nonblock (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+
+ // Rgister @ evdp.
+ if (evdp_addlistener(fd, &s->evdp_data) != true) {
+ ShowError("network_addlistener(%c, '%s', %u): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port);
+ close(fd);
+ return -1;
+ }
+
+
+ // Apply flags on Session array for this conneciton.
+ if (v6 == true) s->v6 = true;
+ else s->v6 = false;
+
+ s->type = NST_LISTENER;
+ s->onRecv = _network_accept;
+
+ ShowStatus("Added Listener on '%s':%u\n", addr, port, (v6==true ? "(ipv6)":"(ipv4)"));
+
+ return fd;
}//end: network_addlistener()
-static bool _network_connect_establishedHandler(int32 fd){
- register SESSION *s = &g_Session[fd];
- int val;
- socklen_t val_len;
-
- if(s->type == NST_FREE)
- return true; // due to multiple non coalesced event notifications
- // this can happen .. when a previous handled event has already disconnected the connection
- // within the same cycle..
-
- val = -1;
- val_len = sizeof(val);
- getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &val_len);
-
- if(val != 0){
- // :( .. cleanup session..
- s->type = NST_FREE;
- s->onSend = NULL;
- s->onConnect = NULL;
- s->onDisconnect = NULL;
-
- evdp_remove(fd, &s->evdp_data);
- close(fd);
-
- return true; // we CANT return false,
- // becuase the normal disconnect procedure would execute the ondisconnect handler, which we dont want .. in this case.
- }else{
- // ok
- if(s->onConnect(fd) == false) {
- // onConnect handler has refused the connection ..
- // cleanup .. and ok
- s->type = NST_FREE;
- s->onSend = NULL;
- s->onConnect = NULL;
- s->onDisconnect = NULL;
-
- evdp_remove(fd, &s->evdp_data);
- close(fd);
-
- return true; // we dnot want the ondisconnect handler to be executed, so its okay to handle this by ourself.
- }
-
- // connection established !
- //
- if( evdp_outgoingconnection_established(fd, &s->evdp_data) == false ){
- return false; // we want the normal disconnect procedure.. with call to ondisconnect handler.
- }
-
- s->onSend = NULL;
-
- ShowStatus("#%u connection successfull!\n", fd);
- }
-
- return true;
+static bool _network_connect_establishedHandler(int32 fd)
+{
+ register SESSION *s = &g_Session[fd];
+ int val;
+ socklen_t val_len;
+
+ if (s->type == NST_FREE)
+ return true; // due to multiple non coalesced event notifications
+ // this can happen .. when a previous handled event has already disconnected the connection
+ // within the same cycle..
+
+ val = -1;
+ val_len = sizeof(val);
+ getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &val_len);
+
+ if (val != 0) {
+ // :( .. cleanup session..
+ s->type = NST_FREE;
+ s->onSend = NULL;
+ s->onConnect = NULL;
+ s->onDisconnect = NULL;
+
+ evdp_remove(fd, &s->evdp_data);
+ close(fd);
+
+ return true; // we CANT return false,
+ // becuase the normal disconnect procedure would execute the ondisconnect handler, which we dont want .. in this case.
+ } else {
+ // ok
+ if (s->onConnect(fd) == false) {
+ // onConnect handler has refused the connection ..
+ // cleanup .. and ok
+ s->type = NST_FREE;
+ s->onSend = NULL;
+ s->onConnect = NULL;
+ s->onDisconnect = NULL;
+
+ evdp_remove(fd, &s->evdp_data);
+ close(fd);
+
+ return true; // we dnot want the ondisconnect handler to be executed, so its okay to handle this by ourself.
+ }
+
+ // connection established !
+ //
+ if (evdp_outgoingconnection_established(fd, &s->evdp_data) == false) {
+ return false; // we want the normal disconnect procedure.. with call to ondisconnect handler.
+ }
+
+ s->onSend = NULL;
+
+ ShowStatus("#%u connection successfull!\n", fd);
+ }
+
+ return true;
}//end: _network_connect_establishedHandler()
int32 network_connect(bool v6,
- const char *addr,
- uint16 port,
- const char *from_addr,
- uint16 from_port,
- bool (*onConnectionEstablishedHandler)(int32 fd),
- void (*onConnectionLooseHandler)(int32 fd)
-){
- register SESSION *s;
- int32 fd, optval, ret;
- struct sockaddr_in ip4;
+ const char *addr,
+ uint16 port,
+ const char *from_addr,
+ uint16 from_port,
+ bool (*onConnectionEstablishedHandler)(int32 fd),
+ void (*onConnectionLooseHandler)(int32 fd)
+ )
+{
+ register SESSION *s;
+ int32 fd, optval, ret;
+ struct sockaddr_in ip4;
#ifdef ENABLE_IPV6
- struct sockaddr_in6 ip6;
+ struct sockaddr_in6 ip6;
#endif
#ifdef ENABLE_IPV6
- if(v6 == true)
- fd = socket(AF_INET6, SOCK_STREAM, 0);
- else
+ if (v6 == true)
+ fd = socket(AF_INET6, SOCK_STREAM, 0);
+ else
#endif
- fd = socket(AF_INET, SOCK_STREAM, 0);
+ fd = socket(AF_INET, SOCK_STREAM, 0);
#ifndef ENABLE_IPV6
- // check..
- if(v6 == true){
- ShowError("network_connect(%c, '%s', %u...): tried to create an ipv6 connection, IPV6 is not supported in this release.\n", (v6==true?'t':'f'), addr, port);
- return -1;
- }
+ // check..
+ if (v6 == true) {
+ ShowError("network_connect(%c, '%s', %u...): tried to create an ipv6 connection, IPV6 is not supported in this release.\n", (v6==true?'t':'f'), addr, port);
+ return -1;
+ }
#endif
- // check connection limits.
- if(fd >= MAXCONN){
- ShowError("network_connect(%c, '%s', %u...): cannot create new connection, exceeeds more than supported connections (%u)\n", (v6==true?'t':'f'), addr, port );
- close(fd);
- return -1;
- }
-
-
- // Originating IP/Port pair given ?
- if(from_addr != NULL && *from_addr != 0){
- //..
- #ifdef SO_REUSEADDR
- optval=1;
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
- #endif
-
- #ifdef ENABLE_IPV6
- if(v6 == true){
- memset(&ip6, 0x00, sizeof(ip6));
- ip6.sin6_family = AF_INET6;
- ip6.sin6_port = htons(from_port);
-
- if(inet_pton(AF_INET6, from_addr, &ip6.sin6_addr) != 1){
- ShowError("network_connect(%c, '%s', %u...): cannot parse originating (from) IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
-
- ret = bind(fd, (struct sockaddr*)&ip6, sizeof(ip6));
- }else{
- #endif
- memset(&ip4, 0x00, sizeof(ip4));
-
- ip4.sin_family = AF_INET;
- ip4.sin_port = htons(from_port);
- ip4.sin_addr.s_addr = inet_addr(from_addr);
- ret = bind(fd, (struct sockaddr*)&ip4, sizeof(ip4));
- #ifdef ENABLE_IPV6
- }
- #endif
-
- }
-
-
- // Set non block
- if(_setnonblock(fd) == false){
- ShowError("network_connect(%c, '%s', %u...): cannot set socket to nonblocking (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
-
-
- // Create ip addr block to connect to ..
+ // check connection limits.
+ if (fd >= MAXCONN) {
+ ShowError("network_connect(%c, '%s', %u...): cannot create new connection, exceeeds more than supported connections (%u)\n", (v6==true?'t':'f'), addr, port);
+ close(fd);
+ return -1;
+ }
+
+
+ // Originating IP/Port pair given ?
+ if (from_addr != NULL && *from_addr != 0) {
+ //..
+#ifdef SO_REUSEADDR
+ optval=1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+#endif
+
+#ifdef ENABLE_IPV6
+ if (v6 == true) {
+ memset(&ip6, 0x00, sizeof(ip6));
+ ip6.sin6_family = AF_INET6;
+ ip6.sin6_port = htons(from_port);
+
+ if (inet_pton(AF_INET6, from_addr, &ip6.sin6_addr) != 1) {
+ ShowError("network_connect(%c, '%s', %u...): cannot parse originating (from) IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ ret = bind(fd, (struct sockaddr *)&ip6, sizeof(ip6));
+ } else {
+#endif
+ memset(&ip4, 0x00, sizeof(ip4));
+
+ ip4.sin_family = AF_INET;
+ ip4.sin_port = htons(from_port);
+ ip4.sin_addr.s_addr = inet_addr(from_addr);
+ ret = bind(fd, (struct sockaddr *)&ip4, sizeof(ip4));
#ifdef ENABLE_IPV6
- if(v6 == true){
- memset(&ip6, 0x00, sizeof(ip6));
- ip6.sin6_family = AF_INET6;
- ip6.sin6_port = htons(port);
-
- if(inet_pton(AF_INET6, addr, &ip6.sin6_addr) != 1){
- ShowError("network_connect(%c, '%s', %u...): cannot parse destination IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
- close(fd);
- return -1;
- }
-
- }else{
+ }
#endif
- memset(&ip4, 0x00, sizeof(ip4));
-
- ip4.sin_family = AF_INET;
- ip4.sin_port = htons(port);
- ip4.sin_addr.s_addr = inet_addr(addr);
+
+ }
+
+
+ // Set non block
+ if (_setnonblock(fd) == false) {
+ ShowError("network_connect(%c, '%s', %u...): cannot set socket to nonblocking (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+
+ // Create ip addr block to connect to ..
+#ifdef ENABLE_IPV6
+ if (v6 == true) {
+ memset(&ip6, 0x00, sizeof(ip6));
+ ip6.sin6_family = AF_INET6;
+ ip6.sin6_port = htons(port);
+
+ if (inet_pton(AF_INET6, addr, &ip6.sin6_addr) != 1) {
+ ShowError("network_connect(%c, '%s', %u...): cannot parse destination IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ } else {
+#endif
+ memset(&ip4, 0x00, sizeof(ip4));
+
+ ip4.sin_family = AF_INET;
+ ip4.sin_port = htons(port);
+ ip4.sin_addr.s_addr = inet_addr(addr);
#ifdef ENABLE_IPV6
- }
+ }
#endif
- // Assign Session..
- s = &g_Session[fd];
- s->type = NST_OUTGOING;
- s->v6 = v6;
- s->onConnect = onConnectionEstablishedHandler;
- s->onDisconnect = onConnectionLooseHandler;
- s->onRecv = NULL;
- s->onSend = _network_connect_establishedHandler;
+ // Assign Session..
+ s = &g_Session[fd];
+ s->type = NST_OUTGOING;
+ s->v6 = v6;
+ s->onConnect = onConnectionEstablishedHandler;
+ s->onDisconnect = onConnectionLooseHandler;
+ s->onRecv = NULL;
+ s->onSend = _network_connect_establishedHandler;
#ifdef ENABLE_IPV6
- if(v6 == true)
- memcpy(&s->addr.v6, &ip6, sizeof(ip6));
- else
+ if (v6 == true)
+ memcpy(&s->addr.v6, &ip6, sizeof(ip6));
+ else
#endif
- memcpy(&s->addr.v4, &ip4, sizeof(ip4));
-
- // Register @ EVDP. as outgoing (see doc of the function)
- if(evdp_addconnecting(fd, &s->evdp_data) == false){
- ShowError("network_connect(%c, '%s', %u...): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port);
-
- // cleanup session x.x..
- s->type = NST_FREE;
- s->onConnect = NULL;
- s->onDisconnect = NULL;
- s->onSend = NULL;
-
- // close, return error code.
- close(fd);
- return -1;
- }
+ memcpy(&s->addr.v4, &ip4, sizeof(ip4));
+
+ // Register @ EVDP. as outgoing (see doc of the function)
+ if (evdp_addconnecting(fd, &s->evdp_data) == false) {
+ ShowError("network_connect(%c, '%s', %u...): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port);
+
+ // cleanup session x.x..
+ s->type = NST_FREE;
+ s->onConnect = NULL;
+ s->onDisconnect = NULL;
+ s->onSend = NULL;
+
+ // close, return error code.
+ close(fd);
+ return -1;
+ }
#ifdef ENABLE_IPV6
- if(v6 == true)
- ret = connect(fd, (struct sockaddr*)&ip6, sizeof(ip6));
- else
+ if (v6 == true)
+ ret = connect(fd, (struct sockaddr *)&ip6, sizeof(ip6));
+ else
#endif
- ret = connect(fd, (struct sockaddr*)&ip4, sizeof(ip4));
-
-
- //
- if(ret != 0 && errno != EINPROGRESS){
- ShowWarning("network_connect(%c, '%s', %u...): connection failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
-
- // Cleanup session ..
- s->type = NST_FREE;
- s->onConnect = NULL;
- s->onDisconnect = NULL;
- s->onSend = NULL;
-
- // .. remove from evdp and close fd.
- evdp_remove(fd, &s->evdp_data);
- close(fd);
- return -1;
- }
-
-
- // ! The Info Message :~D
- ShowStatus("network_connect fd#%u (%s:%u) in progress.. \n", fd, addr, port);
-
-return fd;
+ ret = connect(fd, (struct sockaddr *)&ip4, sizeof(ip4));
+
+
+ //
+ if (ret != 0 && errno != EINPROGRESS) {
+ ShowWarning("network_connect(%c, '%s', %u...): connection failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
+
+ // Cleanup session ..
+ s->type = NST_FREE;
+ s->onConnect = NULL;
+ s->onDisconnect = NULL;
+ s->onSend = NULL;
+
+ // .. remove from evdp and close fd.
+ evdp_remove(fd, &s->evdp_data);
+ close(fd);
+ return -1;
+ }
+
+
+ // ! The Info Message :~D
+ ShowStatus("network_connect fd#%u (%s:%u) in progress.. \n", fd, addr, port);
+
+ return fd;
}//end: network_connect()
-static bool _onSend(int32 fd){
- register SESSION *s = &g_Session[fd];
- register netbuf buf, buf_next;
- register uint32 szNeeded;
- register int wLen;
-
- if(s->type == NST_FREE)
- return true; // Possible due to multipl non coalsced event notifications
- // so onSend gets called after disconnect caused by an previous vent.
- // we can ignore the call to onSend, then.
-
- buf = s->write.buf;
- while(1){
- if(buf == NULL)
- break;
-
- buf_next = buf->next;
-
-
- szNeeded = (buf->dataLen - s->write.dataPos); // using th session-local .dataPos member, due to shared write buffer support.
-
- // try to write.
- wLen = write(fd, &buf->buf[s->write.dataPos], szNeeded);
- if(wLen == 0){
- return false; // eof.
- }else if(wLen == -1){
- if(errno == EAGAIN || errno == EWOULDBLOCK)
- return true; // dont disconnect / try again later.
-
- // all other errors. .
- return false;
- }
-
- // Wrote data.. =>
- szNeeded -= wLen;
- if(szNeeded > 0){
- // still data left ..
- //
- s->write.dataPos += wLen; // fix offset.
- return true;
- }else{
- // this buffer has been written successfully
- // could be returned to pool.
- netbuffer_put(buf);
- s->write.n_outstanding--; // When threadsafe -> Interlocked here.
- s->write.dataPos = 0;
- }
-
-
- buf = buf_next;
- }
-
- // okay,
- // reaching this part means:
- // while interrupted by break -
- // which means all buffers are written, nothing left
- //
-
- s->write.buf_last = NULL;
- s->write.buf = NULL;
- s->write.n_outstanding = 0;
- s->write.dataPos = 0;
-
- // Remove from event dispatcher (write notification)
- //
- evdp_writable_remove(fd, &s->evdp_data);
-
- return true;
+static bool _onSend(int32 fd)
+{
+ register SESSION *s = &g_Session[fd];
+ register netbuf buf, buf_next;
+ register uint32 szNeeded;
+ register int wLen;
+
+ if (s->type == NST_FREE)
+ return true; // Possible due to multipl non coalsced event notifications
+ // so onSend gets called after disconnect caused by an previous vent.
+ // we can ignore the call to onSend, then.
+
+ buf = s->write.buf;
+ while (1) {
+ if (buf == NULL)
+ break;
+
+ buf_next = buf->next;
+
+
+ szNeeded = (buf->dataLen - s->write.dataPos); // using th session-local .dataPos member, due to shared write buffer support.
+
+ // try to write.
+ wLen = write(fd, &buf->buf[s->write.dataPos], szNeeded);
+ if (wLen == 0) {
+ return false; // eof.
+ } else if (wLen == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return true; // dont disconnect / try again later.
+
+ // all other errors. .
+ return false;
+ }
+
+ // Wrote data.. =>
+ szNeeded -= wLen;
+ if (szNeeded > 0) {
+ // still data left ..
+ //
+ s->write.dataPos += wLen; // fix offset.
+ return true;
+ } else {
+ // this buffer has been written successfully
+ // could be returned to pool.
+ netbuffer_put(buf);
+ s->write.n_outstanding--; // When threadsafe -> Interlocked here.
+ s->write.dataPos = 0;
+ }
+
+
+ buf = buf_next;
+ }
+
+ // okay,
+ // reaching this part means:
+ // while interrupted by break -
+ // which means all buffers are written, nothing left
+ //
+
+ s->write.buf_last = NULL;
+ s->write.buf = NULL;
+ s->write.n_outstanding = 0;
+ s->write.dataPos = 0;
+
+ // Remove from event dispatcher (write notification)
+ //
+ evdp_writable_remove(fd, &s->evdp_data);
+
+ return true;
}//end: _onSend()
-static bool _onRORecv(int32 fd){
- register SESSION *s = &g_Session[fd];
- register uint32 szNeeded;
- register char *p;
- register int rLen;
-
- if(s->type == NST_FREE)
- return true; // Possible due to multiple non coalesced events by evdp.
- // simply ignore this call returning positive result.
-
- // Initialize p and szNeeded depending on change
- //
- switch(s->read.state){
- case NRS_WAITOP:
- szNeeded = s->read.head_left;
- p = ((char*)&s->read.head[0]) + (2-szNeeded);
- break;
-
- case NRS_WAITLEN:
- szNeeded = s->read.head_left;
- p = ((char*)&s->read.head[1]) + (2-szNeeded);
- break;
-
- case NRS_WAITDATA:{
- register netbuf buf = s->read.buf;
-
- szNeeded = (buf->dataLen - buf->dataPos);
- p = (char*)&buf->buf[ buf->dataPos ];
- }
- break;
-
- default:
- // .. the impossible gets possible ..
- ShowError("_onRORecv: fd #%u has unknown read.state (%d) - disconnecting\n", fd, s->read.state);
- return false;
- break;
- }
-
-
- //
-
- rLen = read(fd, p, szNeeded);
- if(rLen == 0){
- // eof..
- return false;
- }else if(rLen == -1){
-
- if(errno == EAGAIN || errno == EWOULDBLOCK){
- // try again later .. (this case shouldnt happen, because we're event trigered.. but .. sometimes it happens :)
- return true;
- }
-
- // an additional interesting case would be
- // EINTR, this 'could' be handled .. but:
- // posix says that its possible that data gets currupted during irq
- // or data gor read and not reported.., so we'd have a data loss..
- // (which shouldnt happen with stream based protocols such as tcp)
- // its better to disonnect the client in that case.
-
- return false;
- }
-
- //
- // Got Data:
- // next action also depends on current state ..
- //
- szNeeded -= rLen;
- switch(s->read.state){
- case NRS_WAITOP:
-
- if(szNeeded > 0){
- // still data missing ..
- s->read.head_left = szNeeded;
- return true; // wait for completion.
- }else{
- // complete ..
- // next state depends on packet type.
-
- s->read.head[1] = ((uint16*)s->netparser_data)[ s->read.head[0] ]; // store lenght of packet by opcode head[0] to head[1]
-
- if(s->read.head[1] == ROPACKET_UNKNOWN){
- // unknown packet - disconnect
- ShowWarning("_onRORecv: fd #%u got unlnown packet 0x%04x - disconnecting.\n", fd, s->read.head[0]);
- return false;
- }
- else if(s->read.head[1] == ROPACKET_DYNLEN){
- // dynamic length
- // next state: requrie len.
- s->read.state = NRS_WAITLEN;
- s->read.head_left = 2;
- return true; //
- }
- else if(s->read.head[1] == 2){
- // packet has no data (only opcode)
- register netbuf buf = netbuffer_get(2); // :D whoohoo its giant!
-
- NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin.
- buf->dataPos = 2;
- buf->dataLen = 2;
- buf->next = NULL;
-
- // Back to initial state -> Need opcode.
- s->read.state = NRS_WAITOP;
- s->read.head_left = 2;
- s->read.buf = NULL;
-
- // Call completion routine here.
- s->onPacketComplete(fd, s->read.head[0], 2, buf);
-
- return true; // done :)
- }
- else{
- // paket needs .. data ..
- register netbuf buf = netbuffer_get( s->read.head[1] );
-
- NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin.
- buf->dataPos = 2;
- buf->dataLen = s->read.head[1];
- buf->next = NULL;
-
- // attach buffer.
- s->read.buf = buf;
-
- // set state:
- s->read.state = NRS_WAITDATA;
-
- return true;
- }
-
- }//endif: szNeeded > 0 (opcode read completed?)
-
- break;
-
-
- case NRS_WAITLEN:
-
- if(szNeeded > 0){
- // incomplete ..
- s->read.head_left = szNeeded;
- return true;
- }else{
-
- if(s->read.head[1] == 4){
- // packet has no data (only opcode + length)
- register netbuf buf = netbuffer_get( 4 );
-
- NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
- buf->dataPos = 4;
- buf->dataLen = 4;
- buf->next = NULL;
-
- // set initial state (need opcode)
- s->read.state = NRS_WAITOP;
- s->read.head_left = 2;
- s->read.buf = NULL;
-
- // call completion routine.
- s->onPacketComplete(fd, s->read.head[0], 4, buf);
-
- return true;
- }
- else if(s->read.head[1] < 4){
- // invalid header.
- ShowWarning("_onRORecv: fd #%u invalid header - got packet 0x%04x, reported length < 4 - INVALID - disconnecting\n", fd, s->read.head[0]);
- return false;
- }
- else{
- // Data needed
- // next state -> waitdata!
- register netbuf buf = netbuffer_get( s->read.head[1] );
-
- NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
- buf->dataPos = 4;
- buf->dataLen = s->read.head[1];
- buf->next = NULL;
-
- // attach to session:
- s->read.buf = buf;
- s->read.state = NRS_WAITDATA;
-
- return true;
- }
-
- }//endif: szNeeded > 0 (length read complete?)
-
- break;
-
-
- case NRS_WAITDATA:
-
- if(szNeeded == 0){
- // Packet finished!
- // compltion.
- register netbuf buf = s->read.buf;
-
- // set initial state.
- s->read.state = NRS_WAITOP;
- s->read.head_left = 2;
- s->read.buf = NULL;
-
- // Call completion routine.
- s->onPacketComplete(fd, NBUFW(buf, 0), buf->dataLen, buf);
-
- return true;
- }else{
- // still data needed
- s->read.buf->dataPos += rLen;
-
- return true;
- }
- break;
-
-
- //
- default:
- ShowError("_onRORecv: fd #%u has unknown read.state (%d) [2] - disconnecting\n", fd, s->read.state);
- return false;
- break;
- }
-
-
- return false;
+static bool _onRORecv(int32 fd)
+{
+ register SESSION *s = &g_Session[fd];
+ register uint32 szNeeded;
+ register char *p;
+ register int rLen;
+
+ if (s->type == NST_FREE)
+ return true; // Possible due to multiple non coalesced events by evdp.
+ // simply ignore this call returning positive result.
+
+ // Initialize p and szNeeded depending on change
+ //
+ switch (s->read.state) {
+ case NRS_WAITOP:
+ szNeeded = s->read.head_left;
+ p = ((char *)&s->read.head[0]) + (2-szNeeded);
+ break;
+
+ case NRS_WAITLEN:
+ szNeeded = s->read.head_left;
+ p = ((char *)&s->read.head[1]) + (2-szNeeded);
+ break;
+
+ case NRS_WAITDATA: {
+ register netbuf buf = s->read.buf;
+
+ szNeeded = (buf->dataLen - buf->dataPos);
+ p = (char *)&buf->buf[ buf->dataPos ];
+ }
+ break;
+
+ default:
+ // .. the impossible gets possible ..
+ ShowError("_onRORecv: fd #%u has unknown read.state (%d) - disconnecting\n", fd, s->read.state);
+ return false;
+ break;
+ }
+
+
+ //
+
+ rLen = read(fd, p, szNeeded);
+ if (rLen == 0) {
+ // eof..
+ return false;
+ } else if (rLen == -1) {
+
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ // try again later .. (this case shouldnt happen, because we're event trigered.. but .. sometimes it happens :)
+ return true;
+ }
+
+ // an additional interesting case would be
+ // EINTR, this 'could' be handled .. but:
+ // posix says that its possible that data gets currupted during irq
+ // or data gor read and not reported.., so we'd have a data loss..
+ // (which shouldnt happen with stream based protocols such as tcp)
+ // its better to disonnect the client in that case.
+
+ return false;
+ }
+
+ //
+ // Got Data:
+ // next action also depends on current state ..
+ //
+ szNeeded -= rLen;
+ switch (s->read.state) {
+ case NRS_WAITOP:
+
+ if (szNeeded > 0) {
+ // still data missing ..
+ s->read.head_left = szNeeded;
+ return true; // wait for completion.
+ } else {
+ // complete ..
+ // next state depends on packet type.
+
+ s->read.head[1] = ((uint16 *)s->netparser_data)[ s->read.head[0] ]; // store lenght of packet by opcode head[0] to head[1]
+
+ if (s->read.head[1] == ROPACKET_UNKNOWN) {
+ // unknown packet - disconnect
+ ShowWarning("_onRORecv: fd #%u got unlnown packet 0x%04x - disconnecting.\n", fd, s->read.head[0]);
+ return false;
+ } else if (s->read.head[1] == ROPACKET_DYNLEN) {
+ // dynamic length
+ // next state: requrie len.
+ s->read.state = NRS_WAITLEN;
+ s->read.head_left = 2;
+ return true; //
+ } else if (s->read.head[1] == 2) {
+ // packet has no data (only opcode)
+ register netbuf buf = netbuffer_get(2); // :D whoohoo its giant!
+
+ NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin.
+ buf->dataPos = 2;
+ buf->dataLen = 2;
+ buf->next = NULL;
+
+ // Back to initial state -> Need opcode.
+ s->read.state = NRS_WAITOP;
+ s->read.head_left = 2;
+ s->read.buf = NULL;
+
+ // Call completion routine here.
+ s->onPacketComplete(fd, s->read.head[0], 2, buf);
+
+ return true; // done :)
+ } else {
+ // paket needs .. data ..
+ register netbuf buf = netbuffer_get(s->read.head[1]);
+
+ NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin.
+ buf->dataPos = 2;
+ buf->dataLen = s->read.head[1];
+ buf->next = NULL;
+
+ // attach buffer.
+ s->read.buf = buf;
+
+ // set state:
+ s->read.state = NRS_WAITDATA;
+
+ return true;
+ }
+
+ }//endif: szNeeded > 0 (opcode read completed?)
+
+ break;
+
+
+ case NRS_WAITLEN:
+
+ if (szNeeded > 0) {
+ // incomplete ..
+ s->read.head_left = szNeeded;
+ return true;
+ } else {
+
+ if (s->read.head[1] == 4) {
+ // packet has no data (only opcode + length)
+ register netbuf buf = netbuffer_get(4);
+
+ NBUFL(buf, 0) = *((uint32 *)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
+ buf->dataPos = 4;
+ buf->dataLen = 4;
+ buf->next = NULL;
+
+ // set initial state (need opcode)
+ s->read.state = NRS_WAITOP;
+ s->read.head_left = 2;
+ s->read.buf = NULL;
+
+ // call completion routine.
+ s->onPacketComplete(fd, s->read.head[0], 4, buf);
+
+ return true;
+ } else if (s->read.head[1] < 4) {
+ // invalid header.
+ ShowWarning("_onRORecv: fd #%u invalid header - got packet 0x%04x, reported length < 4 - INVALID - disconnecting\n", fd, s->read.head[0]);
+ return false;
+ } else {
+ // Data needed
+ // next state -> waitdata!
+ register netbuf buf = netbuffer_get(s->read.head[1]);
+
+ NBUFL(buf, 0) = *((uint32 *)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
+ buf->dataPos = 4;
+ buf->dataLen = s->read.head[1];
+ buf->next = NULL;
+
+ // attach to session:
+ s->read.buf = buf;
+ s->read.state = NRS_WAITDATA;
+
+ return true;
+ }
+
+ }//endif: szNeeded > 0 (length read complete?)
+
+ break;
+
+
+ case NRS_WAITDATA:
+
+ if (szNeeded == 0) {
+ // Packet finished!
+ // compltion.
+ register netbuf buf = s->read.buf;
+
+ // set initial state.
+ s->read.state = NRS_WAITOP;
+ s->read.head_left = 2;
+ s->read.buf = NULL;
+
+ // Call completion routine.
+ s->onPacketComplete(fd, NBUFW(buf, 0), buf->dataLen, buf);
+
+ return true;
+ } else {
+ // still data needed
+ s->read.buf->dataPos += rLen;
+
+ return true;
+ }
+ break;
+
+
+ //
+ default:
+ ShowError("_onRORecv: fd #%u has unknown read.state (%d) [2] - disconnecting\n", fd, s->read.state);
+ return false;
+ break;
+ }
+
+
+ return false;
}//end: _onRORecv()
-void network_send(int32 fd, netbuf buf){
- register SESSION *s = &g_Session[fd];
-
+void network_send(int32 fd, netbuf buf)
+{
+ register SESSION *s = &g_Session[fd];
+
#ifdef PARANOID_CHECKS
- if(fd >= MAXCONN){
- ShowError("network_send: tried to attach buffer to connection idientifer #%u which is out of bounds.\n", fd);
- _network_free_netbuf_async(buf);
- return;
- }
+ if (fd >= MAXCONN) {
+ ShowError("network_send: tried to attach buffer to connection idientifer #%u which is out of bounds.\n", fd);
+ _network_free_netbuf_async(buf);
+ return;
+ }
#endif
- if(s->type == NST_FREE)
- return;
-
- // Check Max Outstanding buffers limit.
- if( (s->write.max_outstanding > 0) &&
- (s->write.n_outstanding >= s->write.max_outstanding) ){
-
- ShowWarning("network_send: fd #%u max Outstanding buffers exceeded. - disconnecting.\n", fd);
- network_disconnect(fd);
- //
- _network_free_netbuf_async(buf);
- return;
- }
-
-
- // Attach to the end:
- buf->next = NULL;
- if(s->write.buf_last != NULL){
- s->write.buf_last->next = buf;
- s->write.buf_last = buf;
-
- }else{
- // currently no buffer attached.
- s->write.buf = s->write.buf_last = buf;
-
- // register @ evdp for writable notification.
- evdp_writable_add(fd, &s->evdp_data); //
- }
-
-
- //
- s->write.n_outstanding++;
-
+ if (s->type == NST_FREE)
+ return;
+
+ // Check Max Outstanding buffers limit.
+ if ((s->write.max_outstanding > 0) &&
+ (s->write.n_outstanding >= s->write.max_outstanding)) {
+
+ ShowWarning("network_send: fd #%u max Outstanding buffers exceeded. - disconnecting.\n", fd);
+ network_disconnect(fd);
+ //
+ _network_free_netbuf_async(buf);
+ return;
+ }
+
+
+ // Attach to the end:
+ buf->next = NULL;
+ if (s->write.buf_last != NULL) {
+ s->write.buf_last->next = buf;
+ s->write.buf_last = buf;
+
+ } else {
+ // currently no buffer attached.
+ s->write.buf = s->write.buf_last = buf;
+
+ // register @ evdp for writable notification.
+ evdp_writable_add(fd, &s->evdp_data); //
+ }
+
+
+ //
+ s->write.n_outstanding++;
+
}//end: network_send()
void network_parser_set_ro(int32 fd,
- int16 *packetlentable,
- void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
- ){
- register SESSION *s = &g_Session[fd];
- register netbuf b, nb; // used for potential free attached buffers.
-
- if(s->type == NST_FREE)
- return;
-
- s->onPacketComplete = onPacketCompleteProc;
-
- s->onRecv = _onRORecv; // ..
- s->onSend = _onSend; // Using the normal generic netbuf based send function.
-
- s->netparser_data = packetlentable;
-
- // Initial State -> Need Packet OPCode.
- s->read.state = NRS_WAITOP;
- s->read.head_left = 2;
-
-
- // Detach (if..) all buffers.
- if(s->read.buf != NULL){
- _network_free_netbuf_async(s->read.buf); //
- s->read.buf = NULL;
- }
-
- if(s->write.buf != NULL){
- b = s->write.buf;
- while(1){
- nb = b->next;
-
- _network_free_netbuf_async(b);
-
- b = nb;
- }
-
- s->write.buf = NULL;
- s->write.buf_last = NULL;
- s->write.n_outstanding = 0;
- }
-
- // not changing any limits on outstanding ..
- //
-
+ int16 *packetlentable,
+ void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
+ )
+{
+ register SESSION *s = &g_Session[fd];
+ register netbuf b, nb; // used for potential free attached buffers.
+
+ if (s->type == NST_FREE)
+ return;
+
+ s->onPacketComplete = onPacketCompleteProc;
+
+ s->onRecv = _onRORecv; // ..
+ s->onSend = _onSend; // Using the normal generic netbuf based send function.
+
+ s->netparser_data = packetlentable;
+
+ // Initial State -> Need Packet OPCode.
+ s->read.state = NRS_WAITOP;
+ s->read.head_left = 2;
+
+
+ // Detach (if..) all buffers.
+ if (s->read.buf != NULL) {
+ _network_free_netbuf_async(s->read.buf); //
+ s->read.buf = NULL;
+ }
+
+ if (s->write.buf != NULL) {
+ b = s->write.buf;
+ while (1) {
+ nb = b->next;
+
+ _network_free_netbuf_async(b);
+
+ b = nb;
+ }
+
+ s->write.buf = NULL;
+ s->write.buf_last = NULL;
+ s->write.n_outstanding = 0;
+ }
+
+ // not changing any limits on outstanding ..
+ //
+
}//end: network_parser_set_ro()
diff --git a/src/common/network.h b/src/common/network.h
index d7b463a2f..b883b41e6 100644
--- a/src/common/network.h
+++ b/src/common/network.h
@@ -3,7 +3,7 @@
#include <netinet/in.h>
#include "../common/cbasetypes.h"
-#include "../common/netbuffer.h"
+#include "../common/netbuffer.h"
#include "../common/evdp.h"
#ifndef MAXCONN
@@ -11,79 +11,79 @@
#endif
-typedef struct SESSION{
- EVDP_DATA evdp_data; // Must be always the frist member! (some evdp's may rely on this fact)
-
- // Connection Type
- enum{ NST_FREE=0, NST_LISTENER = 1, NST_CLIENT=2, NST_OUTGOING=3} type;
-
- // Flags / Settings.
- bool v6; // is v6?
- bool disconnect_in_progress; // To prevent stack overflows / recursive calls.
-
-
- union{ // union to save memory.
- struct sockaddr_in v4;
- struct sockaddr_in6 v6;
- }addr;
-
-
- // "lowlevel" Handlers
- // (Implemented by the protocol specific parser)
- //
- bool (*onRecv)(int32 fd); // return false = disconnect
- bool (*onSend)(int32 fd); // return false = disconnect
-
- // Event Handlers for LISTENER type sockets
- //
- // onConnect gets Called when a connection has been
- // successfully accepted.
- // Session entry is available in this Handler!
- // A returncode of false will reejct the connection (disconnect)
- // Note: When rejecting a connection in onConnect by returning false
- // The onDisconnect handler wont get called!
- // Note: the onConnect Handler is also responsible for setting
- // the appropriate netparser (which implements onRecv/onSend..) [protocol specific]
- //
- // onDisconnect gets called when a connection gets disconnected
- // (by peer as well as by core)
- //
- bool (*onConnect)(int32 fd); // return false = disconnect (wont accept)
- void (*onDisconnect)(int32 fd);
-
-
- //
- // Parser specific data
- //
- void *netparser_data; // incase of RO Packet Parser, pointer to packet len table (uint16array)
- void (*onPacketComplete)(int32 fd, uint16 op, uint16 len, netbuf buf);
-
-
- //
- // Buffers
- //
- struct{
- enum NETREADSTATE { NRS_WAITOP = 0, NRS_WAITLEN = 1, NRS_WAITDATA = 2} state;
-
- uint32 head_left;
- uint16 head[2];
-
- netbuf buf;
- } read;
-
- struct{
- uint32 max_outstanding;
- uint32 n_outstanding;
-
- uint32 dataPos;
-
- netbuf buf, buf_last;
- } write;
-
- // Application Level data Pointer
- // (required for backward compatibility with previous athena socket system.)
- void *data;
-
+typedef struct SESSION {
+ EVDP_DATA evdp_data; // Must be always the frist member! (some evdp's may rely on this fact)
+
+ // Connection Type
+ enum { NST_FREE=0, NST_LISTENER = 1, NST_CLIENT=2, NST_OUTGOING=3} type;
+
+ // Flags / Settings.
+ bool v6; // is v6?
+ bool disconnect_in_progress; // To prevent stack overflows / recursive calls.
+
+
+ union { // union to save memory.
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ } addr;
+
+
+ // "lowlevel" Handlers
+ // (Implemented by the protocol specific parser)
+ //
+ bool (*onRecv)(int32 fd); // return false = disconnect
+ bool (*onSend)(int32 fd); // return false = disconnect
+
+ // Event Handlers for LISTENER type sockets
+ //
+ // onConnect gets Called when a connection has been
+ // successfully accepted.
+ // Session entry is available in this Handler!
+ // A returncode of false will reejct the connection (disconnect)
+ // Note: When rejecting a connection in onConnect by returning false
+ // The onDisconnect handler wont get called!
+ // Note: the onConnect Handler is also responsible for setting
+ // the appropriate netparser (which implements onRecv/onSend..) [protocol specific]
+ //
+ // onDisconnect gets called when a connection gets disconnected
+ // (by peer as well as by core)
+ //
+ bool (*onConnect)(int32 fd); // return false = disconnect (wont accept)
+ void (*onDisconnect)(int32 fd);
+
+
+ //
+ // Parser specific data
+ //
+ void *netparser_data; // incase of RO Packet Parser, pointer to packet len table (uint16array)
+ void (*onPacketComplete)(int32 fd, uint16 op, uint16 len, netbuf buf);
+
+
+ //
+ // Buffers
+ //
+ struct {
+ enum NETREADSTATE { NRS_WAITOP = 0, NRS_WAITLEN = 1, NRS_WAITDATA = 2} state;
+
+ uint32 head_left;
+ uint16 head[2];
+
+ netbuf buf;
+ } read;
+
+ struct {
+ uint32 max_outstanding;
+ uint32 n_outstanding;
+
+ uint32 dataPos;
+
+ netbuf buf, buf_last;
+ } write;
+
+ // Application Level data Pointer
+ // (required for backward compatibility with previous athena socket system.)
+ void *data;
+
} SESSION;
@@ -101,12 +101,12 @@ void network_final();
void network_do();
-/**
+/**
* Adds a new listner.
*
- * @param v6 v6 listner?
- * @param *addr the address to listen on.
- * @param port port to listen on
+ * @param v6 v6 listner?
+ * @param *addr the address to listen on.
+ * @param port port to listen on
*
* @return -1 on error otherwise the identifier of the new listener.
*/
@@ -116,26 +116,26 @@ int32 network_addlistener(bool v6, const char *addr, uint16 port);
/**
* Tries to establish an outgoing connection.
*
- * @param v6 operate with IPv6 addresses?
- * @param addr the address to connect to
- * @param port the port to connect to
- * @param from_addr the address to connect from (local source / optional if auto -> NULL)
+ * @param v6 operate with IPv6 addresses?
+ * @param addr the address to connect to
+ * @param port the port to connect to
+ * @param from_addr the address to connect from (local source / optional if auto -> NULL)
* @param from_port the port to connect from (local source / optional if auto -> 0)
- * @param onConnectionEstablishedHandler callback that gets called when the connection is established.
- * @param onConnectionLooseHandler callback that gets called when the connection gets disconnected (or the connection couldnt be established)
+ * @param onConnectionEstablishedHandler callback that gets called when the connection is established.
+ * @param onConnectionLooseHandler callback that gets called when the connection gets disconnected (or the connection couldnt be established)
*
* @return -1 on error otherwise the identifier of the new connection
*/
int32 network_connect(bool v6,
- const char *addr,
- uint16 port,
- const char *from_addr,
- uint16 from_port,
- bool (*onConnectionEstablishedHandler)(int32 fd),
- void (*onConnectionLooseHandler)(int32 fd)
-);
+ const char *addr,
+ uint16 port,
+ const char *from_addr,
+ uint16 from_port,
+ bool (*onConnectionEstablishedHandler)(int32 fd),
+ void (*onConnectionLooseHandler)(int32 fd)
+ );
+
-
/**
* Disconnects the given connection
@@ -143,43 +143,43 @@ int32 network_connect(bool v6,
* @param fd connection identifier.
*
* @Note:
- * - onDisconnect callback gets called!
- * - cleares (returns) all assigned buffers
+ * - onDisconnect callback gets called!
+ * - cleares (returns) all assigned buffers
*
*/
void network_disconnect(int32 fd);
-/**
+/**
* Attach's a netbuffer at the end of sending queue to the given connection
*
- * @param fd connection identifier
- * @param buf netbuffer to attach.
+ * @param fd connection identifier
+ * @param buf netbuffer to attach.
*/
void network_send(int32 fd, netbuf buf);
/**
* Sets the parser to RO Protocol like Packet Parser.
- *
- * @param fd connection identifier
- * @param *packetlentable pointer to array of uint16 in size of UINT16_MAX,
- * @param onComplteProc callback for packet completion.
+ *
+ * @param fd connection identifier
+ * @param *packetlentable pointer to array of uint16 in size of UINT16_MAX,
+ * @param onComplteProc callback for packet completion.
*
* @note:
- * PacketLen Table Fromat:
- * each element's offsets represents th ro opcode.
- * value is length.
- * a length of 0 means the packet is dynamic.
- * a length of UINT16_MAX means the packet is unknown.
+ * PacketLen Table Fromat:
+ * each element's offsets represents th ro opcode.
+ * value is length.
+ * a length of 0 means the packet is dynamic.
+ * a length of UINT16_MAX means the packet is unknown.
*
- * Static Packets must contain their hader in len so (0x64 == 55 ..)
+ * Static Packets must contain their hader in len so (0x64 == 55 ..)
*
*/
void network_parser_set_ro(int32 fd,
- int16 *packetlentable,
- void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
- );
+ int16 *packetlentable,
+ void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
+ );
#define ROPACKET_UNKNOWN UINT16_MAX
#define ROPACKET_DYNLEN 0
diff --git a/src/common/nullpo.c b/src/common/nullpo.c
index 4383109a7..ef2f3cd66 100644
--- a/src/common/nullpo.c
+++ b/src/common/nullpo.c
@@ -8,7 +8,7 @@
#include "../common/showmsg.h"
// #include "logs.h" // •z΂µ‚Ä‚Ý‚é
-static void nullpo_info_core(const char *file, int line, const char *func,
+static void nullpo_info_core(const char *file, int line, const char *func,
const char *fmt, va_list ap);
/*======================================
@@ -17,75 +17,73 @@ static void nullpo_info_core(const char *file, int line, const char *func,
int nullpo_chk_f(const char *file, int line, const char *func, const void *target,
const char *fmt, ...)
{
- va_list ap;
-
- if (target != NULL)
- return 0;
-
- va_start(ap, fmt);
- nullpo_info_core(file, line, func, fmt, ap);
- va_end(ap);
- return 1;
+ va_list ap;
+
+ if (target != NULL)
+ return 0;
+
+ va_start(ap, fmt);
+ nullpo_info_core(file, line, func, fmt, ap);
+ va_end(ap);
+ return 1;
}
int nullpo_chk(const char *file, int line, const char *func, const void *target)
{
- if (target != NULL)
- return 0;
-
- nullpo_info_core(file, line, func, NULL, NULL);
- return 1;
+ if (target != NULL)
+ return 0;
+
+ nullpo_info_core(file, line, func, NULL, NULL);
+ return 1;
}
/*======================================
* nullpoî•ño—Í(ŠO•”ŒÄo‚µŒü‚¯ƒ‰ƒbƒp)
*--------------------------------------*/
-void nullpo_info_f(const char *file, int line, const char *func,
- const char *fmt, ...)
+void nullpo_info_f(const char *file, int line, const char *func,
+ const char *fmt, ...)
{
- va_list ap;
-
- va_start(ap, fmt);
- nullpo_info_core(file, line, func, fmt, ap);
- va_end(ap);
+ va_list ap;
+
+ va_start(ap, fmt);
+ nullpo_info_core(file, line, func, fmt, ap);
+ va_end(ap);
}
void nullpo_info(const char *file, int line, const char *func)
{
- nullpo_info_core(file, line, func, NULL, NULL);
+ nullpo_info_core(file, line, func, NULL, NULL);
}
/*======================================
* nullpoî•ño—Í(Main)
*--------------------------------------*/
-static void nullpo_info_core(const char *file, int line, const char *func,
+static void nullpo_info_core(const char *file, int line, const char *func,
const char *fmt, va_list ap)
{
- if (file == NULL)
- file = "??";
-
- func =
- func == NULL ? "unknown":
- func[0] == '\0' ? "unknown":
- func;
-
- ShowMessage("--- nullpo info --------------------------------------------\n");
- ShowMessage("%s:%d: in func `%s'\n", file, line, func);
- if (fmt != NULL)
- {
- if (fmt[0] != '\0')
- {
- vprintf(fmt, ap);
-
- // ÅŒã‚ɉüs‚µ‚½‚©Šm”F
- if (fmt[strlen(fmt)-1] != '\n')
- ShowMessage("\n");
- }
- }
- ShowMessage("--- end nullpo info ----------------------------------------\n");
-
- // ‚±‚±‚ç‚ÅnullpoƒƒO‚ðƒtƒ@ƒCƒ‹‚É‘‚«o‚¹‚½‚ç
- // ‚Ü‚Æ‚ß‚Ä’ño‚Å‚«‚é‚È‚ÆŽv‚Á‚Ä‚¢‚½‚èB
+ if (file == NULL)
+ file = "??";
+
+ func =
+ func == NULL ? "unknown":
+ func[0] == '\0' ? "unknown":
+ func;
+
+ ShowMessage("--- nullpo info --------------------------------------------\n");
+ ShowMessage("%s:%d: in func `%s'\n", file, line, func);
+ if (fmt != NULL) {
+ if (fmt[0] != '\0') {
+ vprintf(fmt, ap);
+
+ // ÅŒã‚ɉüs‚µ‚½‚©Šm”F
+ if (fmt[strlen(fmt)-1] != '\n')
+ ShowMessage("\n");
+ }
+ }
+ ShowMessage("--- end nullpo info ----------------------------------------\n");
+
+ // ‚±‚±‚ç‚ÅnullpoƒƒO‚ðƒtƒ@ƒCƒ‹‚É‘‚«o‚¹‚½‚ç
+ // ‚Ü‚Æ‚ß‚Ä’ño‚Å‚«‚é‚È‚ÆŽv‚Á‚Ä‚¢‚½‚èB
}
diff --git a/src/common/nullpo.h b/src/common/nullpo.h
index 8ee86a782..67679432f 100644
--- a/src/common/nullpo.h
+++ b/src/common/nullpo.h
@@ -71,45 +71,45 @@
#if defined(NULLPO_CHECK)
#define nullpo_ret(t) \
- if (nullpo_chk(NLP_MARK, (void *)(t))) {return(0);}
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {return(0);}
#define nullpo_retv(t) \
- if (nullpo_chk(NLP_MARK, (void *)(t))) {return;}
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {return;}
#define nullpo_retr(ret, t) \
- if (nullpo_chk(NLP_MARK, (void *)(t))) {return(ret);}
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {return(ret);}
#define nullpo_retb(t) \
- if (nullpo_chk(NLP_MARK, (void *)(t))) {break;}
+ if (nullpo_chk(NLP_MARK, (void *)(t))) {break;}
// ‰Â•Ïˆø”ƒ}ƒNƒ‚ÉŠÖ‚·‚éðŒƒRƒ“ƒpƒCƒ‹
#if __STDC_VERSION__ >= 199901L
/* C99‚ɑΉž */
#define nullpo_ret_f(t, fmt, ...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(0);}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(0);}
#define nullpo_retv_f(t, fmt, ...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return;}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return;}
#define nullpo_retr_f(ret, t, fmt, ...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(ret);}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(ret);}
#define nullpo_retb_f(t, fmt, ...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {break;}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {break;}
#elif __GNUC__ >= 2
/* GCC—p */
#define nullpo_ret_f(t, fmt, args...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(0);}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(0);}
#define nullpo_retv_f(t, fmt, args...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return;}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return;}
#define nullpo_retr_f(ret, t, fmt, args...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(ret);}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(ret);}
#define nullpo_retb_f(t, fmt, args...) \
- if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {break;}
+ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {break;}
#else
@@ -189,7 +189,7 @@ int nullpo_chk(const char *file, int line, const char *func, const void *target)
*/
int nullpo_chk_f(const char *file, int line, const char *func, const void *target,
const char *fmt, ...)
- __attribute__((format(printf,5,6)));
+__attribute__((format(printf,5,6)));
/*======================================
@@ -217,9 +217,9 @@ void nullpo_info(const char *file, int line, const char *func);
* ”õl‚âŠÖŒW•Ï”‚Ì‘‚«o‚µ‚È‚Ç‚É
*--------------------------------------
*/
-void nullpo_info_f(const char *file, int line, const char *func,
+void nullpo_info_f(const char *file, int line, const char *func,
const char *fmt, ...)
- __attribute__((format(printf,4,5)));
+__attribute__((format(printf,4,5)));
#endif /* _NULLPO_H_ */
diff --git a/src/common/raconf.c b/src/common/raconf.c
index 2703560ff..e73154f50 100644
--- a/src/common/raconf.c
+++ b/src/common/raconf.c
@@ -1,7 +1,7 @@
-//
+//
// Athena style config parser
-// (would be better to have "one" implementation instead of .. 4 :)
-//
+// (would be better to have "one" implementation instead of .. 4 :)
+//
//
// Author: Florian Wilkemeyer <fw@f-ws.de>
//
@@ -25,560 +25,571 @@
#define VARNAME_LEN 64
struct raconf {
- DBMap *db;
+ DBMap *db;
};
-struct conf_value{
- int64 intval;
- bool bval;
- double floatval;
- size_t strval_len; // not includung \0
- char strval[16];
+struct conf_value {
+ int64 intval;
+ bool bval;
+ double floatval;
+ size_t strval_len; // not includung \0
+ char strval[16];
};
-static struct conf_value *makeValue(const char *key, char *val, size_t val_len){
- struct conf_value *v;
- char *p;
- size_t sz;
-
- sz = sizeof(struct conf_value);
- if(val_len >= sizeof(v->strval))
- sz += (val_len - sizeof(v->strval) + 1);
-
- v = (struct conf_value*)aCalloc(1, sizeof(struct conf_value));
- if(v == NULL){
- ShowFatalError("raconf: makeValue => Out of Memory while allocating new node.\n");
- return NULL;
- }
-
- memcpy(v->strval, val, val_len);
- v->strval[val_len+1] = '\0';
- v->strval_len = val_len;
-
-
- // Parse boolean value:
- if((val_len == 4) && (strncmpi("true", val, 4) == 0))
- v->bval = true;
- else if((val_len == 3) && (strncmpi("yes", val, 3) == 0))
- v->bval = true;
- else if((val_len == 3) && (strncmpi("oui", val, 3) == 0))
- v->bval = true;
- else if((val_len == 2) && (strncmpi("si", val, 2) == 0))
- v->bval = true;
- else if((val_len == 2) && (strncmpi("ja", val, 2) == 0))
- v->bval = true;
- else if((val_len == 1) && (*val == '1'))
- v->bval = true;
- else if((val_len == 5) && (strncmpi("false", val, 5) == 0))
- v->bval = false;
- else if((val_len == 2) && (strncmpi("no", val, 2) == 0))
- v->bval = false;
- else if((val_len == 3) && (strncmpi("non", val, 3) == 0))
- v->bval = false;
- else if((val_len == 2) && (strncmpi("no", val, 2) == 0))
- v->bval = false;
- else if((val_len == 4) && (strncmpi("nein", val, 4) == 0))
- v->bval = false;
- else if((val_len == 1) && (*val == '0'))
- v->bval = false;
- else
- v->bval = false; // assume false.
-
- // Parse number
- // Supported formats:
- // prefix: 0x hex .
- // postix: h for hex
- // b for bin (dual)
- if( (val_len >= 1 && (val[val_len] == 'h')) || (val_len >= 2 && (val[0] == '0' && val[1] == 'x')) ){//HEX!
- if(val[val_len] == 'h'){
- val[val_len]= '\0';
- v->intval = strtoull(val, NULL, 16);
- val[val_len] = 'h';
- }else
- v->intval = strtoull(&val[2], NULL, 16);
- }else if( val_len >= 1 && (val[val_len] == 'b') ){ //BIN
- val[val_len] = '\0';
- v->intval = strtoull(val, NULL, 2);
- val[val_len] = 'b';
- }else if( *val >='0' && *val <= '9'){ // begins with normal digit, so assume its dec.
- // is it float?
- bool is_float = false;
-
- for(p = val; *p != '\0'; p++){
- if(*p == '.'){
- v->floatval = strtod(val, NULL);
- v->intval = (int64) v->floatval;
- is_float = true;
- break;
- }
- }
-
- if(is_float == false){
- v->intval = strtoull(val, NULL, 10);
- v->floatval = (double) v->intval;
- }
- }else{
- // Everything else: lets use boolean for fallback
- if(v->bval == true)
- v->intval = 1;
- else
- v->intval = 0;
- }
-
- return v;
+static struct conf_value *makeValue(const char *key, char *val, size_t val_len) {
+ struct conf_value *v;
+ char *p;
+ size_t sz;
+
+ sz = sizeof(struct conf_value);
+ if (val_len >= sizeof(v->strval))
+ sz += (val_len - sizeof(v->strval) + 1);
+
+ v = (struct conf_value *)aCalloc(1, sizeof(struct conf_value));
+ if (v == NULL) {
+ ShowFatalError("raconf: makeValue => Out of Memory while allocating new node.\n");
+ return NULL;
+ }
+
+ memcpy(v->strval, val, val_len);
+ v->strval[val_len+1] = '\0';
+ v->strval_len = val_len;
+
+
+ // Parse boolean value:
+ if ((val_len == 4) && (strncmpi("true", val, 4) == 0))
+ v->bval = true;
+ else if ((val_len == 3) && (strncmpi("yes", val, 3) == 0))
+ v->bval = true;
+ else if ((val_len == 3) && (strncmpi("oui", val, 3) == 0))
+ v->bval = true;
+ else if ((val_len == 2) && (strncmpi("si", val, 2) == 0))
+ v->bval = true;
+ else if ((val_len == 2) && (strncmpi("ja", val, 2) == 0))
+ v->bval = true;
+ else if ((val_len == 1) && (*val == '1'))
+ v->bval = true;
+ else if ((val_len == 5) && (strncmpi("false", val, 5) == 0))
+ v->bval = false;
+ else if ((val_len == 2) && (strncmpi("no", val, 2) == 0))
+ v->bval = false;
+ else if ((val_len == 3) && (strncmpi("non", val, 3) == 0))
+ v->bval = false;
+ else if ((val_len == 2) && (strncmpi("no", val, 2) == 0))
+ v->bval = false;
+ else if ((val_len == 4) && (strncmpi("nein", val, 4) == 0))
+ v->bval = false;
+ else if ((val_len == 1) && (*val == '0'))
+ v->bval = false;
+ else
+ v->bval = false; // assume false.
+
+ // Parse number
+ // Supported formats:
+ // prefix: 0x hex .
+ // postix: h for hex
+ // b for bin (dual)
+ if ((val_len >= 1 && (val[val_len] == 'h')) || (val_len >= 2 && (val[0] == '0' && val[1] == 'x'))) {//HEX!
+ if (val[val_len] == 'h') {
+ val[val_len]= '\0';
+ v->intval = strtoull(val, NULL, 16);
+ val[val_len] = 'h';
+ } else
+ v->intval = strtoull(&val[2], NULL, 16);
+ } else if (val_len >= 1 && (val[val_len] == 'b')) { //BIN
+ val[val_len] = '\0';
+ v->intval = strtoull(val, NULL, 2);
+ val[val_len] = 'b';
+ } else if (*val >='0' && *val <= '9') { // begins with normal digit, so assume its dec.
+ // is it float?
+ bool is_float = false;
+
+ for (p = val; *p != '\0'; p++) {
+ if (*p == '.') {
+ v->floatval = strtod(val, NULL);
+ v->intval = (int64) v->floatval;
+ is_float = true;
+ break;
+ }
+ }
+
+ if (is_float == false) {
+ v->intval = strtoull(val, NULL, 10);
+ v->floatval = (double) v->intval;
+ }
+ } else {
+ // Everything else: lets use boolean for fallback
+ if (v->bval == true)
+ v->intval = 1;
+ else
+ v->intval = 0;
+ }
+
+ return v;
}//end: makeValue()
-static bool configParse(raconf inst, const char *fileName){
- FILE *fp;
- char line[4096];
- char currentSection[SECTION_LEN];
- char *p;
- char c;
- int linecnt;
- size_t linelen;
- size_t currentSection_len;
-
- fp = fopen(fileName, "r");
- if(fp == NULL){
- ShowError("configParse: cannot open '%s' for reading.\n", fileName);
- return false;
- }
-
-
- // Start with empty section:
- currentSection[0] = '\0';
- currentSection_len = 0;
-
- //
- linecnt = 0;
- while(1){
- linecnt++;
-
- if(fgets(line, sizeof(line), fp) != line)
- break;
-
- linelen = strlen(line);
- p = line;
-
- // Skip whitespaces from beginning (space and tab)
- _line_begin_skip_whities:
- c = *p;
- if(c == ' ' || c == '\t'){
- p++;
- linelen--;
- goto _line_begin_skip_whities;
- }
-
- // Remove linebreaks as (cr or lf) and whitespaces from line end!
- _line_end_skip_whities_and_breaks:
- c = p[linelen-1];
- if(c == '\r' || c == '\n' || c == ' ' || c == '\t'){
- p[--linelen] = '\0';
- goto _line_end_skip_whities_and_breaks;
- }
-
- // Empty line?
- // or line starts with comment (commented out)?
- if(linelen == 0 || (p[0] == '/' && p[1] == '/') || p[0] == ';')
- continue;
-
- // Variable names can contain:
- // A-Za-z-_.0-9
- //
- // Sections start with [ .. ] (INI Style)
- //
- c = *p;
-
- // check what we have.. :)
- if(c == '['){ // got section!
- // Got Section!
- // Search for ]
- char *start = (p+1);
-
- while(1){
- ++p;
- c = *p;
-
- if(c == '\0'){
- ShowError("Syntax Error: unterminated Section name in %s:%u (expected ']')\n", fileName, linecnt);
- fclose(fp);
- return false;
- }else if(c == ']'){ // closing backet (section name termination)
- if( (p - start + 1) > (sizeof(currentSection) ) ){
- ShowError("Syntax Error: Section name in %s:%u is too large (max Supported length: %u chars)\n", fileName, linecnt, sizeof(currentSection)-1);
- fclose(fp);
- return false;
- }
-
- // Set section!
- *p = '\0'; // add termination here.
- memcpy(currentSection, start, (p-start)+1 ); // we'll copy \0, too! (we replaced the ] backet with \0.)
- currentSection_len = (p-start);
-
- break;
-
- }else if( (c >= '0' && c <= '9') || (c == '-') || (c == ' ') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){
- // skip .. (allowed char / specifier)
- continue;
- }else{
- ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Section name.\n", c, fileName, linecnt, (p-line));
- fclose(fp);
- return false;
- }
-
- }//endwhile: parse section name
-
-
- }else if( (c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){
- // Got variable!
- // Search for '=' or ':' wich termiantes the name
- char *start = p;
- char *valuestart = NULL;
- size_t start_len;
-
- while(1){
- ++p;
- c = *p;
-
- if(c == '\0'){
- ShowError("Syntax Error: unterminated Variable name in %s:%u\n", fileName, linecnt);
- fclose(fp);
- return false;
- }else if( (c == '=') || (c == ':') ){
- // got name termination
-
- *p = '\0'; // Terminate it so (start) will hold the pointer to the name.
-
- break;
-
- }else if( (c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){
- // skip .. allowed char
- continue;
- }else{
- ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Variable name.\n", c, fileName, linecnt, (p-line));
- fclose(fp);
- return false;
- }
-
- }//endwhile: parse var name
-
- start_len = (p-start);
- if(start_len >= VARNAME_LEN){
- ShowError("%s:%u Variable length exceeds limit of %u Characters.\n", fileName, linecnt, VARNAME_LEN-1);
- fclose(fp);
- return false;
- }else if(start_len == 0){
- ShowError("%s:%u Empty Variable name is not allowed.\n", fileName, linecnt);
- fclose(fp);
- return false;
- }
-
-
- valuestart = (p+1);
-
-
- // Skip whitespace from begin of value (tab and space)
- _skip_value_begin_whities:
- c = *valuestart;
- if(c == ' ' || c == '\t'){
- valuestart++;
- goto _skip_value_begin_whities;
- }
-
- // Scan for value termination,
- // wich can be \0 or comment start (// or ; (INI) )
- //
- p = valuestart;
- while(1){
- c = *p;
- if(c == '\0'){
- // Terminated by line end.
- break;
- }else if(c == '/' && p[1] == '/'){
- // terminated by c++ style comment.
- *p = '\0';
- break;
- }else if(c == ';'){
- // terminated by ini style comment.
- *p = '\0';
- break;
- }
-
- p++;
- }//endwhile: search var value end.
-
-
- // Strip whitespaces from end of value.
- if(valuestart != p){ // not empty!
- p--;
- _strip_value_end_whities:
- c = *p;
- if(c == ' ' || c == '\t'){
- *p = '\0';
- p--;
- goto _strip_value_end_whities;
- }
- p++;
- }
-
-
- // Buildin Hook:
- if( stricmp(start, "import") == 0){
- if( configParse(inst, valuestart) != true){
- ShowError("%s:%u - Import of '%s' failed!\n", fileName, linecnt, valuestart);
- }
- }else{
- // put it to db.
- struct conf_value *v, *o;
- char key[ (SECTION_LEN+VARNAME_LEN+1+1) ]; //+1 for delimiter, +1 for termination.
- size_t section_len;
-
- if(*currentSection == '\0'){ // empty / none
- strncpy(key, "<unnamed>",9);
- section_len = 9;
- }else{
- strncpy(key, currentSection, currentSection_len);
- section_len = currentSection_len;
- }
-
- key[section_len] = '.'; // Delim
-
- strncpy(&key[section_len+1], start, start_len);
-
- key[section_len + start_len + 1] = '\0';
-
-
- v = makeValue(key, valuestart, (p-valuestart) );
-
- // Try to get the old one before
- o = strdb_get(inst->db, key);
- if(o != NULL){
- strdb_remove(inst->db, key);
- aFree(o); //
- }
-
- strdb_put( inst->db, key, v);
- }
-
-
- }else{
- ShowError("Syntax Error: unexpected Character '%c' in %s:%u (offset %u)\n", c, fileName, linecnt, (p-line) );
- fclose(fp);
- return false;
- }
-
-
-
- }
-
-
-
- fclose(fp);
- return true;
+static bool configParse(raconf inst, const char *fileName)
+{
+ FILE *fp;
+ char line[4096];
+ char currentSection[SECTION_LEN];
+ char *p;
+ char c;
+ int linecnt;
+ size_t linelen;
+ size_t currentSection_len;
+
+ fp = fopen(fileName, "r");
+ if (fp == NULL) {
+ ShowError("configParse: cannot open '%s' for reading.\n", fileName);
+ return false;
+ }
+
+
+ // Start with empty section:
+ currentSection[0] = '\0';
+ currentSection_len = 0;
+
+ //
+ linecnt = 0;
+ while (1) {
+ linecnt++;
+
+ if (fgets(line, sizeof(line), fp) != line)
+ break;
+
+ linelen = strlen(line);
+ p = line;
+
+ // Skip whitespaces from beginning (space and tab)
+ _line_begin_skip_whities:
+ c = *p;
+ if (c == ' ' || c == '\t') {
+ p++;
+ linelen--;
+ goto _line_begin_skip_whities;
+ }
+
+ // Remove linebreaks as (cr or lf) and whitespaces from line end!
+ _line_end_skip_whities_and_breaks:
+ c = p[linelen-1];
+ if (c == '\r' || c == '\n' || c == ' ' || c == '\t') {
+ p[--linelen] = '\0';
+ goto _line_end_skip_whities_and_breaks;
+ }
+
+ // Empty line?
+ // or line starts with comment (commented out)?
+ if (linelen == 0 || (p[0] == '/' && p[1] == '/') || p[0] == ';')
+ continue;
+
+ // Variable names can contain:
+ // A-Za-z-_.0-9
+ //
+ // Sections start with [ .. ] (INI Style)
+ //
+ c = *p;
+
+ // check what we have.. :)
+ if (c == '[') { // got section!
+ // Got Section!
+ // Search for ]
+ char *start = (p+1);
+
+ while (1) {
+ ++p;
+ c = *p;
+
+ if (c == '\0') {
+ ShowError("Syntax Error: unterminated Section name in %s:%u (expected ']')\n", fileName, linecnt);
+ fclose(fp);
+ return false;
+ } else if (c == ']') { // closing backet (section name termination)
+ if ((p - start + 1) > (sizeof(currentSection))) {
+ ShowError("Syntax Error: Section name in %s:%u is too large (max Supported length: %u chars)\n", fileName, linecnt, sizeof(currentSection)-1);
+ fclose(fp);
+ return false;
+ }
+
+ // Set section!
+ *p = '\0'; // add termination here.
+ memcpy(currentSection, start, (p-start)+1); // we'll copy \0, too! (we replaced the ] backet with \0.)
+ currentSection_len = (p-start);
+
+ break;
+
+ } else if ((c >= '0' && c <= '9') || (c == '-') || (c == ' ') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ // skip .. (allowed char / specifier)
+ continue;
+ } else {
+ ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Section name.\n", c, fileName, linecnt, (p-line));
+ fclose(fp);
+ return false;
+ }
+
+ }//endwhile: parse section name
+
+
+ } else if ((c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ // Got variable!
+ // Search for '=' or ':' wich termiantes the name
+ char *start = p;
+ char *valuestart = NULL;
+ size_t start_len;
+
+ while (1) {
+ ++p;
+ c = *p;
+
+ if (c == '\0') {
+ ShowError("Syntax Error: unterminated Variable name in %s:%u\n", fileName, linecnt);
+ fclose(fp);
+ return false;
+ } else if ((c == '=') || (c == ':')) {
+ // got name termination
+
+ *p = '\0'; // Terminate it so (start) will hold the pointer to the name.
+
+ break;
+
+ } else if ((c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ // skip .. allowed char
+ continue;
+ } else {
+ ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Variable name.\n", c, fileName, linecnt, (p-line));
+ fclose(fp);
+ return false;
+ }
+
+ }//endwhile: parse var name
+
+ start_len = (p-start);
+ if (start_len >= VARNAME_LEN) {
+ ShowError("%s:%u Variable length exceeds limit of %u Characters.\n", fileName, linecnt, VARNAME_LEN-1);
+ fclose(fp);
+ return false;
+ } else if (start_len == 0) {
+ ShowError("%s:%u Empty Variable name is not allowed.\n", fileName, linecnt);
+ fclose(fp);
+ return false;
+ }
+
+
+ valuestart = (p+1);
+
+
+ // Skip whitespace from begin of value (tab and space)
+ _skip_value_begin_whities:
+ c = *valuestart;
+ if (c == ' ' || c == '\t') {
+ valuestart++;
+ goto _skip_value_begin_whities;
+ }
+
+ // Scan for value termination,
+ // wich can be \0 or comment start (// or ; (INI) )
+ //
+ p = valuestart;
+ while (1) {
+ c = *p;
+ if (c == '\0') {
+ // Terminated by line end.
+ break;
+ } else if (c == '/' && p[1] == '/') {
+ // terminated by c++ style comment.
+ *p = '\0';
+ break;
+ } else if (c == ';') {
+ // terminated by ini style comment.
+ *p = '\0';
+ break;
+ }
+
+ p++;
+ }//endwhile: search var value end.
+
+
+ // Strip whitespaces from end of value.
+ if (valuestart != p) { // not empty!
+ p--;
+ _strip_value_end_whities:
+ c = *p;
+ if (c == ' ' || c == '\t') {
+ *p = '\0';
+ p--;
+ goto _strip_value_end_whities;
+ }
+ p++;
+ }
+
+
+ // Buildin Hook:
+ if (stricmp(start, "import") == 0) {
+ if (configParse(inst, valuestart) != true) {
+ ShowError("%s:%u - Import of '%s' failed!\n", fileName, linecnt, valuestart);
+ }
+ } else {
+ // put it to db.
+ struct conf_value *v, *o;
+ char key[(SECTION_LEN+VARNAME_LEN+1+1) ]; //+1 for delimiter, +1 for termination.
+ size_t section_len;
+
+ if (*currentSection == '\0') { // empty / none
+ strncpy(key, "<unnamed>",9);
+ section_len = 9;
+ } else {
+ strncpy(key, currentSection, currentSection_len);
+ section_len = currentSection_len;
+ }
+
+ key[section_len] = '.'; // Delim
+
+ strncpy(&key[section_len+1], start, start_len);
+
+ key[section_len + start_len + 1] = '\0';
+
+
+ v = makeValue(key, valuestart, (p-valuestart));
+
+ // Try to get the old one before
+ o = strdb_get(inst->db, key);
+ if (o != NULL) {
+ strdb_remove(inst->db, key);
+ aFree(o); //
+ }
+
+ strdb_put(inst->db, key, v);
+ }
+
+
+ } else {
+ ShowError("Syntax Error: unexpected Character '%c' in %s:%u (offset %u)\n", c, fileName, linecnt, (p-line));
+ fclose(fp);
+ return false;
+ }
+
+
+
+ }
+
+
+
+ fclose(fp);
+ return true;
}//end: configParse()
#define MAKEKEY(dest, section, key) { size_t section_len, key_len; \
- if(section == NULL || *section == '\0'){ \
- strncpy(dest, "<unnamed>", 9); \
- section_len = 9; \
- }else{ \
- section_len = strlen(section); \
- strncpy(dest, section, section_len); \
- } \
- \
- dest[section_len] = '.'; \
- \
- key_len = strlen(key); \
- strncpy(&dest[section_len+1], key, key_len); \
- dest[section_len + key_len + 1] = '\0'; \
- }
-
-
-raconf raconf_parse(const char *file_name){
- struct raconf *rc;
-
- rc = aCalloc(1, sizeof(struct raconf) );
- if(rc == NULL){
- ShowFatalError("raconf_parse: failed to allocate memory for new handle\n");
- return NULL;
- }
-
- rc->db = strdb_alloc(DB_OPT_BASE | DB_OPT_DUP_KEY, 98);
- //
-
- if(configParse(rc, file_name) != true){
- ShowError("Failed to Parse Configuration file '%s'\n", file_name);
- }
-
- return rc;
+ if(section == NULL || *section == '\0'){ \
+ strncpy(dest, "<unnamed>", 9); \
+ section_len = 9; \
+ }else{ \
+ section_len = strlen(section); \
+ strncpy(dest, section, section_len); \
+ } \
+ \
+ dest[section_len] = '.'; \
+ \
+ key_len = strlen(key); \
+ strncpy(&dest[section_len+1], key, key_len); \
+ dest[section_len + key_len + 1] = '\0'; \
+ }
+
+
+raconf raconf_parse(const char *file_name)
+{
+ struct raconf *rc;
+
+ rc = aCalloc(1, sizeof(struct raconf));
+ if (rc == NULL) {
+ ShowFatalError("raconf_parse: failed to allocate memory for new handle\n");
+ return NULL;
+ }
+
+ rc->db = strdb_alloc(DB_OPT_BASE | DB_OPT_DUP_KEY, 98);
+ //
+
+ if (configParse(rc, file_name) != true) {
+ ShowError("Failed to Parse Configuration file '%s'\n", file_name);
+ }
+
+ return rc;
}//end: raconf_parse()
-void raconf_destroy(raconf rc){
- DBIterator *iter;
- struct conf_value *v;
-
- // Clear all entrys in db.
- iter = db_iterator(rc->db);
- for( v = (struct conf_value*)dbi_first(iter); dbi_exists(iter); v = (struct conf_value*)dbi_next(iter) ){
- aFree(v);
- }
- dbi_destroy(iter);
-
- db_destroy(rc->db);
-
- aFree(rc);
-
+void raconf_destroy(raconf rc)
+{
+ DBIterator *iter;
+ struct conf_value *v;
+
+ // Clear all entrys in db.
+ iter = db_iterator(rc->db);
+ for (v = (struct conf_value *)dbi_first(iter); dbi_exists(iter); v = (struct conf_value *)dbi_next(iter)) {
+ aFree(v);
+ }
+ dbi_destroy(iter);
+
+ db_destroy(rc->db);
+
+ aFree(rc);
+
}//end: raconf_destroy()
-bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
-
- v = strdb_get(rc->db, keystr);
- if(v == NULL)
- return _default;
- else
- return v->bval;
+bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
+
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL)
+ return _default;
+ else
+ return v->bval;
}//end: raconf_getbool()
-float raconf_getfloat(raconf rc,const char *section, const char *key, float _default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
+float raconf_getfloat(raconf rc,const char *section, const char *key, float _default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL)
- return _default;
- else
- return (float)v->floatval;
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL)
+ return _default;
+ else
+ return (float)v->floatval;
}//end: raconf_getfloat()
-int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
-
- v = strdb_get(rc->db, keystr);
- if(v == NULL)
- return _default;
- else
- return v->intval;
+int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
+
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL)
+ return _default;
+ else
+ return v->intval;
}//end: raconf_getint()
-const char* raconf_getstr(raconf rc, const char *section, const char *key, const char *_default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
+const char *raconf_getstr(raconf rc, const char *section, const char *key, const char *_default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
- MAKEKEY(keystr, section, key);
+ MAKEKEY(keystr, section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL)
- return _default;
- else
- return v->strval;
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL)
+ return _default;
+ else
+ return v->strval;
}//end: raconf_getstr()
-bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_section, const char *key, bool _default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
-
- MAKEKEY(keystr, fallback_section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
- return _default;
- }else{
- return v->bval;
- }
-
- }else{
- return v->bval;
- }
+bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_section, const char *key, bool _default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+
+ MAKEKEY(keystr, fallback_section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+ return _default;
+ } else {
+ return v->bval;
+ }
+
+ } else {
+ return v->bval;
+ }
}//end: raconf_getboolEx()
-float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_section, const char *key, float _default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
-
- MAKEKEY(keystr, fallback_section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
- return _default;
- }else{
- return (float)v->floatval;
- }
-
- }else{
- return (float)v->floatval;
- }
-
+float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_section, const char *key, float _default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+
+ MAKEKEY(keystr, fallback_section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+ return _default;
+ } else {
+ return (float)v->floatval;
+ }
+
+ } else {
+ return (float)v->floatval;
+ }
+
}//end: raconf_getfloatEx()
-int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_section, const char *key, int64 _default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
-
- MAKEKEY(keystr, fallback_section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
- return _default;
- }else{
- return v->intval;
- }
-
- }else{
- return v->intval;
- }
+int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_section, const char *key, int64 _default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+
+ MAKEKEY(keystr, fallback_section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+ return _default;
+ } else {
+ return v->intval;
+ }
+
+ } else {
+ return v->intval;
+ }
}//end: raconf_getintEx()
-const char* raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default){
- char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
- struct conf_value *v;
-
- MAKEKEY(keystr, section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
-
- MAKEKEY(keystr, fallback_section, key);
- v = strdb_get(rc->db, keystr);
- if(v == NULL){
- return _default;
- }else{
- return v->strval;
- }
-
- }else{
- return v->strval;
- }
+const char *raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default)
+{
+ char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
+ struct conf_value *v;
+
+ MAKEKEY(keystr, section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+
+ MAKEKEY(keystr, fallback_section, key);
+ v = strdb_get(rc->db, keystr);
+ if (v == NULL) {
+ return _default;
+ } else {
+ return v->strval;
+ }
+
+ } else {
+ return v->strval;
+ }
}//end: raconf_getstrEx()
diff --git a/src/common/raconf.h b/src/common/raconf.h
index 68a2b51b2..242c585bb 100644
--- a/src/common/raconf.h
+++ b/src/common/raconf.h
@@ -7,52 +7,52 @@
#include "../common/cbasetypes.h"
// rAthena generic configuration file parser
-//
-// Config file Syntax is athena style
-// extended with ini style support (including sections)
//
-// Comments are started with // or ; (ini style)
+// Config file Syntax is athena style
+// extended with ini style support (including sections)
+//
+// Comments are started with // or ; (ini style)
//
typedef struct raconf *raconf;
-/**
+/**
* Parses a rAthna Configuration file
- *
+ *
* @param file_name path to the file to parse
*
* @returns not NULL incase of success
*/
-raconf raconf_parse(const char *file_name);
+raconf raconf_parse(const char *file_name);
-/**
+/**
* Frees a Handle received from raconf_parse
*
* @param rc - the handle to free
*/
-void raconf_destroy(raconf rc);
+void raconf_destroy(raconf rc);
-/**
- * Gets the value for Section / Key pair, if key not exists returns _default!
+/**
+ * Gets the value for Section / Key pair, if key not exists returns _default!
*
*/
-bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default);
-float raconf_getfloat(raconf rc,const char *section, const char *key, float _default);
-int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default);
-const char* raconf_getstr(raconf rc, const char *section, const char *key, const char *_default);
+bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default);
+float raconf_getfloat(raconf rc,const char *section, const char *key, float _default);
+int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default);
+const char *raconf_getstr(raconf rc, const char *section, const char *key, const char *_default);
/**
- * Gets the value for Section / Key pair, but has fallback section option if not found in section,
+ * Gets the value for Section / Key pair, but has fallback section option if not found in section,
* if not found in both - default gets returned.
*
*/
bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_section, const char *key, bool _default);
float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_section, const char *key, float _default);
int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_section, const char *key, int64 _default);
-const char* raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default);
+const char *raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default);
diff --git a/src/common/random.c b/src/common/random.c
index 5c048c7eb..ab9b0052f 100644
--- a/src/common/random.c
+++ b/src/common/random.c
@@ -5,10 +5,10 @@
#include "../common/timer.h" // gettick
#include "random.h"
#if defined(WIN32)
- #include "../common/winapi.h"
+#include "../common/winapi.h"
#elif defined(HAVE_GETPID) || defined(HAVE_GETTID)
- #include <sys/types.h>
- #include <unistd.h>
+#include <sys/types.h>
+#include <unistd.h>
#endif
#include <time.h> // time
#include <mt19937ar.h> // init_genrand, genrand_int32, genrand_res53
@@ -17,34 +17,34 @@
/// Initializes the random number generator with an appropriate seed.
void rnd_init(void)
{
- uint32 seed = gettick();
- seed += (uint32)time(NULL);
+ uint32 seed = gettick();
+ seed += (uint32)time(NULL);
#if defined(WIN32)
- seed += GetCurrentProcessId();
- seed += GetCurrentThreadId();
+ seed += GetCurrentProcessId();
+ seed += GetCurrentThreadId();
#else
#if defined(HAVE_GETPID)
- seed += (uint32)getpid();
+ seed += (uint32)getpid();
#endif // HAVE_GETPID
#if defined(HAVE_GETTID)
- seed += (uint32)gettid();
+ seed += (uint32)gettid();
#endif // HAVE_GETTID
#endif
- init_genrand(seed);
+ init_genrand(seed);
}
/// Initializes the random number generator.
void rnd_seed(uint32 seed)
{
- init_genrand(seed);
+ init_genrand(seed);
}
/// Generates a random number in the interval [0, SINT32_MAX]
int32 rnd(void)
{
- return (int32)genrand_int31();
+ return (int32)genrand_int31();
}
@@ -52,7 +52,7 @@ int32 rnd(void)
/// 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);
+ return (uint32)(rnd_uniform()*dice_faces);
}
@@ -60,9 +60,9 @@ uint32 rnd_roll(uint32 dice_faces)
/// 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));
+ if (min >= max)
+ return min;
+ return min + (int32)(rnd_uniform()*(max-min+1));
}
@@ -70,7 +70,7 @@ int32 rnd_value(int32 min, int32 max)
/// 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
+ return ((uint32)genrand_int32())*(1.0/4294967296.0);// divided by 2^32
}
@@ -79,5 +79,5 @@ double rnd_uniform(void)
/// NOTE: 53 bits is the maximum precision of a double
double rnd_uniform53(void)
{
- return genrand_res53();
+ return genrand_res53();
}
diff --git a/src/common/showmsg.c b/src/common/showmsg.c
index 609ae3c50..cfa1587e5 100644
--- a/src/common/showmsg.c
+++ b/src/common/showmsg.c
@@ -15,33 +15,33 @@
#include "libconfig.h"
#ifdef WIN32
- #include "../common/winapi.h"
-
- #ifdef DEBUGLOGMAP
- #define DEBUGLOGPATH "log\\map-server.log"
- #else
- #ifdef DEBUGLOGCHAR
- #define DEBUGLOGPATH "log\\char-server.log"
- #else
- #ifdef DEBUGLOGLOGIN
- #define DEBUGLOGPATH "log\\login-server.log"
- #endif
- #endif
- #endif
+#include "../common/winapi.h"
+
+#ifdef DEBUGLOGMAP
+#define DEBUGLOGPATH "log\\map-server.log"
+#else
+#ifdef DEBUGLOGCHAR
+#define DEBUGLOGPATH "log\\char-server.log"
+#else
+#ifdef DEBUGLOGLOGIN
+#define DEBUGLOGPATH "log\\login-server.log"
+#endif
+#endif
+#endif
#else
- #include <unistd.h>
-
- #ifdef DEBUGLOGMAP
- #define DEBUGLOGPATH "log/map-server.log"
- #else
- #ifdef DEBUGLOGCHAR
- #define DEBUGLOGPATH "log/char-server.log"
- #else
- #ifdef DEBUGLOGLOGIN
- #define DEBUGLOGPATH "log/login-server.log"
- #endif
- #endif
- #endif
+#include <unistd.h>
+
+#ifdef DEBUGLOGMAP
+#define DEBUGLOGPATH "log/map-server.log"
+#else
+#ifdef DEBUGLOGCHAR
+#define DEBUGLOGPATH "log/char-server.log"
+#else
+#ifdef DEBUGLOGLOGIN
+#define DEBUGLOGPATH "log/login-server.log"
+#endif
+#endif
+#endif
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -60,41 +60,41 @@ int console_msg_log = 0;//[Ind] msg error logging
#define SBUF_SIZE 2054 // never put less that what's required for the debug message
-#define NEWBUF(buf) \
- struct { \
- char s_[SBUF_SIZE]; \
- StringBuf *d_; \
- char *v_; \
- int l_; \
- } buf ={"",NULL,NULL,0}; \
-//define NEWBUF
-
-#define BUFVPRINTF(buf,fmt,args) \
- buf.l_ = vsnprintf(buf.s_, SBUF_SIZE, fmt, args); \
- if( buf.l_ >= 0 && buf.l_ < SBUF_SIZE ) \
- {/* static buffer */ \
- buf.v_ = buf.s_; \
- } \
- else \
- {/* dynamic buffer */ \
- buf.d_ = StringBuf_Malloc(); \
- buf.l_ = StringBuf_Vprintf(buf.d_, fmt, args); \
- buf.v_ = StringBuf_Value(buf.d_); \
- ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.\n", buf.l_+1);\
- } \
-//define BUFVPRINTF
+#define NEWBUF(buf) \
+ struct { \
+ char s_[SBUF_SIZE]; \
+ StringBuf *d_; \
+ char *v_; \
+ int l_; \
+ } buf ={"",NULL,NULL,0}; \
+ //define NEWBUF
+
+#define BUFVPRINTF(buf,fmt,args) \
+ buf.l_ = vsnprintf(buf.s_, SBUF_SIZE, fmt, args); \
+ if( buf.l_ >= 0 && buf.l_ < SBUF_SIZE ) \
+ {/* static buffer */ \
+ buf.v_ = buf.s_; \
+ } \
+ else \
+ {/* dynamic buffer */ \
+ buf.d_ = StringBuf_Malloc(); \
+ buf.l_ = StringBuf_Vprintf(buf.d_, fmt, args); \
+ buf.v_ = StringBuf_Value(buf.d_); \
+ ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.\n", buf.l_+1);\
+ } \
+ //define BUFVPRINTF
#define BUFVAL(buf) buf.v_
#define BUFLEN(buf) buf.l_
-#define FREEBUF(buf) \
- if( buf.d_ ) \
- { \
- StringBuf_Free(buf.d_); \
- buf.d_ = NULL; \
- } \
- buf.v_ = NULL; \
-//define FREEBUF
+#define FREEBUF(buf) \
+ if( buf.d_ ) \
+ { \
+ StringBuf_Free(buf.d_); \
+ buf.d_ = NULL; \
+ } \
+ buf.v_ = NULL; \
+ //define FREEBUF
///////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
@@ -104,38 +104,38 @@ int console_msg_log = 0;//[Ind] msg error logging
// ansi compatible printf with control sequence parser for windows
// fast hack, handle with care, not everything implemented
//
-// \033[#;...;#m - Set Graphics Rendition (SGR)
+// \033[#;...;#m - Set Graphics Rendition (SGR)
//
-// printf("\x1b[1;31;40m"); // Bright red on black
-// printf("\x1b[3;33;45m"); // Blinking yellow on magenta (blink not implemented)
-// printf("\x1b[1;30;47m"); // Bright black (grey) on dim white
+// printf("\x1b[1;31;40m"); // Bright red on black
+// printf("\x1b[3;33;45m"); // Blinking yellow on magenta (blink not implemented)
+// printf("\x1b[1;30;47m"); // Bright black (grey) on dim white
//
// Style Foreground Background
-// 1st Digit 2nd Digit 3rd Digit RGB
-// 0 - Reset 30 - Black 40 - Black 000
-// 1 - FG Bright 31 - Red 41 - Red 100
-// 2 - Unknown 32 - Green 42 - Green 010
-// 3 - Blink 33 - Yellow 43 - Yellow 110
-// 4 - Underline 34 - Blue 44 - Blue 001
-// 5 - BG Bright 35 - Magenta 45 - Magenta 101
-// 6 - Unknown 36 - Cyan 46 - Cyan 011
-// 7 - Reverse 37 - White 47 - White 111
+// 1st Digit 2nd Digit 3rd Digit RGB
+// 0 - Reset 30 - Black 40 - Black 000
+// 1 - FG Bright 31 - Red 41 - Red 100
+// 2 - Unknown 32 - Green 42 - Green 010
+// 3 - Blink 33 - Yellow 43 - Yellow 110
+// 4 - Underline 34 - Blue 44 - Blue 001
+// 5 - BG Bright 35 - Magenta 45 - Magenta 101
+// 6 - Unknown 36 - Cyan 46 - Cyan 011
+// 7 - Reverse 37 - White 47 - White 111
// 8 - Concealed (invisible)
//
// \033[#A - Cursor Up (CUU)
-// Moves the cursor up by the specified number of lines without changing columns.
+// Moves the cursor up by the specified number of lines without changing columns.
// If the cursor is already on the top line, this sequence is ignored. \e[A is equivalent to \e[1A.
//
// \033[#B - Cursor Down (CUD)
-// Moves the cursor down by the specified number of lines without changing columns.
+// Moves the cursor down by the specified number of lines without changing columns.
// If the cursor is already on the bottom line, this sequence is ignored. \e[B is equivalent to \e[1B.
//
// \033[#C - Cursor Forward (CUF)
-// Moves the cursor forward by the specified number of columns without changing lines.
+// Moves the cursor forward by the specified number of columns without changing lines.
// If the cursor is already in the rightmost column, this sequence is ignored. \e[C is equivalent to \e[1C.
//
// \033[#D - Cursor Backward (CUB)
-// Moves the cursor back by the specified number of columns without changing lines.
+// Moves the cursor back by the specified number of columns without changing lines.
// If the cursor is already in the leftmost column, this sequence is ignored. \e[D is equivalent to \e[1D.
//
// \033[#E - Cursor Next Line (CNL)
@@ -148,15 +148,15 @@ int console_msg_log = 0;//[Ind] msg error logging
// Moves the cursor to indicated column in current row. \e[G is equivalent to \e[1G.
//
// \033[#;#H - Cursor Position (CUP)
-// Moves the cursor to the specified position. The first # specifies the line number,
-// the second # specifies the column. If you do not specify a position, the cursor moves to the home position:
+// Moves the cursor to the specified position. The first # specifies the line number,
+// the second # specifies the column. If you do not specify a position, the cursor moves to the home position:
// the upper-left corner of the screen (line 1, column 1).
//
// \033[#;#f - Horizontal & Vertical Position
// (same as \033[#;#H)
//
// \033[s - Save Cursor Position (SCP)
-// The current cursor position is saved.
+// The current cursor position is saved.
//
// \033[u - Restore cursor position (RCP)
// Restores the cursor position saved with the (SCP) sequence \033[s.
@@ -194,331 +194,295 @@ Escape sequences for Select Character Set
#define is_console(handle) (FILE_TYPE_CHAR==GetFileType(handle))
///////////////////////////////////////////////////////////////////////////////
-int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
+int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
{
- /////////////////////////////////////////////////////////////////
- /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
- static COORD saveposition = {0,0};
- */
-
- /////////////////////////////////////////////////////////////////
- DWORD written;
- char *p, *q;
- NEWBUF(tempbuf); // temporary buffer
-
- if(!fmt || !*fmt)
- return 0;
-
- // Print everything to the buffer
- BUFVPRINTF(tempbuf,fmt,argptr);
-
- if( !is_console(handle) && stdout_with_ansisequence )
- {
- WriteFile(handle, BUFVAL(tempbuf), BUFLEN(tempbuf), &written, 0);
- return 0;
- }
-
- // start with processing
- p = BUFVAL(tempbuf);
- while ((q = strchr(p, 0x1b)) != NULL)
- { // find the escape character
- if( 0==WriteConsole(handle, p, (DWORD)(q-p), &written, 0) ) // write up to the escape
- WriteFile(handle, p, (DWORD)(q-p), &written, 0);
-
- if( q[1]!='[' )
- { // write the escape char (whatever purpose it has)
- if(0==WriteConsole(handle, q, 1, &written, 0) )
- WriteFile(handle,q, 1, &written, 0);
- p=q+1; //and start searching again
- }
- else
- { // from here, we will skip the '\033['
- // we break at the first unprocessible position
- // assuming regular text is starting there
- uint8 numbers[16], numpoint=0;
- CONSOLE_SCREEN_BUFFER_INFO info;
-
- // initialize
- GetConsoleScreenBufferInfo(handle, &info);
- memset(numbers,0,sizeof(numbers));
-
- // skip escape and bracket
- q=q+2;
- for(;;)
- {
- if( ISDIGIT(*q) )
- { // add number to number array, only accept 2digits, shift out the rest
- // so // \033[123456789m will become \033[89m
- numbers[numpoint] = (numbers[numpoint]<<4) | (*q-'0');
- ++q;
- // and next character
- continue;
- }
- else if( *q == ';' )
- { // delimiter
- if(numpoint<sizeof(numbers)/sizeof(*numbers))
- { // go to next array position
- numpoint++;
- }
- else
- { // array is full, so we 'forget' the first value
- memmove(numbers,numbers+1,sizeof(numbers)/sizeof(*numbers)-1);
- numbers[sizeof(numbers)/sizeof(*numbers)-1]=0;
- }
- ++q;
- // and next number
- continue;
- }
- else if( *q == 'm' )
- { // \033[#;...;#m - Set Graphics Rendition (SGR)
- uint8 i;
- for(i=0; i<= numpoint; ++i)
- {
- if( 0x00 == (0xF0 & numbers[i]) )
- { // upper nibble 0
- if( 0 == numbers[i] )
- { // reset
- info.wAttributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
- }
- else if( 1==numbers[i] )
- { // set foreground intensity
- info.wAttributes |= FOREGROUND_INTENSITY;
- }
- else if( 5==numbers[i] )
- { // set background intensity
- info.wAttributes |= BACKGROUND_INTENSITY;
- }
- else if( 7==numbers[i] )
- { // reverse colors (just xor them)
- info.wAttributes ^= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
- BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
- }
- //case '2': // not existing
- //case '3': // blinking (not implemented)
- //case '4': // unterline (not implemented)
- //case '6': // not existing
- //case '8': // concealed (not implemented)
- //case '9': // not existing
- }
- else if( 0x20 == (0xF0 & numbers[i]) )
- { // off
-
- if( 1==numbers[i] )
- { // set foreground intensity off
- info.wAttributes &= ~FOREGROUND_INTENSITY;
- }
- else if( 5==numbers[i] )
- { // set background intensity off
- info.wAttributes &= ~BACKGROUND_INTENSITY;
- }
- else if( 7==numbers[i] )
- { // reverse colors (just xor them)
- info.wAttributes ^= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
- BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
- }
- }
- else if( 0x30 == (0xF0 & numbers[i]) )
- { // foreground
- uint8 num = numbers[i]&0x0F;
- if(num==9) info.wAttributes |= FOREGROUND_INTENSITY;
- if(num>7) num=7; // set white for 37, 38 and 39
- info.wAttributes &= ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
- if( (num & 0x01)>0 ) // lowest bit set = red
- info.wAttributes |= FOREGROUND_RED;
- if( (num & 0x02)>0 ) // second bit set = green
- info.wAttributes |= FOREGROUND_GREEN;
- if( (num & 0x04)>0 ) // third bit set = blue
- info.wAttributes |= FOREGROUND_BLUE;
- }
- else if( 0x40 == (0xF0 & numbers[i]) )
- { // background
- uint8 num = numbers[i]&0x0F;
- if(num==9) info.wAttributes |= BACKGROUND_INTENSITY;
- if(num>7) num=7; // set white for 47, 48 and 49
- info.wAttributes &= ~(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
- if( (num & 0x01)>0 ) // lowest bit set = red
- info.wAttributes |= BACKGROUND_RED;
- if( (num & 0x02)>0 ) // second bit set = green
- info.wAttributes |= BACKGROUND_GREEN;
- if( (num & 0x04)>0 ) // third bit set = blue
- info.wAttributes |= BACKGROUND_BLUE;
- }
- }
- // set the attributes
- SetConsoleTextAttribute(handle, info.wAttributes);
- }
- else if( *q=='J' )
- { // \033[#J - Erase Display (ED)
- // \033[0J - Clears the screen from cursor to end of display. The cursor position is unchanged.
- // \033[1J - Clears the screen from start to cursor. The cursor position is unchanged.
- // \033[2J - Clears the screen and moves the cursor to the home position (line 1, column 1).
- uint8 num = (numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F);
- int cnt;
- DWORD tmp;
- COORD origin = {0,0};
- if(num==1)
- { // chars from start up to and including cursor
- cnt = info.dwSize.X * info.dwCursorPosition.Y + info.dwCursorPosition.X + 1;
- }
- else if(num==2)
- { // Number of chars on screen.
- cnt = info.dwSize.X * info.dwSize.Y;
- SetConsoleCursorPosition(handle, origin);
- }
- else// 0 and default
- { // number of chars from cursor to end
- origin = info.dwCursorPosition;
- cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X;
- }
- FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, &tmp);
- FillConsoleOutputCharacter(handle, ' ', cnt, origin, &tmp);
- }
- else if( *q=='K' )
- { // \033[K : clear line from actual position to end of the line
- // \033[0K - Clears all characters from the cursor position to the end of the line.
- // \033[1K - Clears all characters from start of line to the cursor position.
- // \033[2K - Clears all characters of the whole line.
-
- uint8 num = (numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F);
- COORD origin = {0,info.dwCursorPosition.Y}; //warning C4204
- SHORT cnt;
- DWORD tmp;
- if(num==1)
- {
- cnt = info.dwCursorPosition.X + 1;
- }
- else if(num==2)
- {
- cnt = info.dwSize.X;
- }
- else// 0 and default
- {
- origin = info.dwCursorPosition;
- cnt = info.dwSize.X - info.dwCursorPosition.X; // how many spaces until line is full
- }
- FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, &tmp);
- FillConsoleOutputCharacter(handle, ' ', cnt, origin, &tmp);
- }
- else if( *q == 'H' || *q == 'f' )
- { // \033[#;#H - Cursor Position (CUP)
- // \033[#;#f - Horizontal & Vertical Position
- // The first # specifies the line number, the second # specifies the column.
- // The default for both is 1
- info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+((numbers[numpoint]&0x0F)-1):0;
- info.dwCursorPosition.Y = (numpoint && numbers[numpoint-1])?(numbers[numpoint-1]>>4)*10+((numbers[numpoint-1]&0x0F)-1):0;
-
- if( info.dwCursorPosition.X >= info.dwSize.X ) info.dwCursorPosition.Y = info.dwSize.X-1;
- if( info.dwCursorPosition.Y >= info.dwSize.Y ) info.dwCursorPosition.Y = info.dwSize.Y-1;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q=='s' )
- { // \033[s - Save Cursor Position (SCP)
- /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo(handle, &info);
- saveposition = info.dwCursorPosition;
- */
- }
- else if( *q=='u' )
- { // \033[u - Restore cursor position (RCP)
- /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
- SetConsoleCursorPosition(handle, saveposition);
- */
- }
- else if( *q == 'A' )
- { // \033[#A - Cursor Up (CUU)
- // Moves the cursor UP # number of lines
- info.dwCursorPosition.Y -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
-
- if( info.dwCursorPosition.Y < 0 )
- info.dwCursorPosition.Y = 0;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'B' )
- { // \033[#B - Cursor Down (CUD)
- // Moves the cursor DOWN # number of lines
- info.dwCursorPosition.Y += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
-
- if( info.dwCursorPosition.Y >= info.dwSize.Y )
- info.dwCursorPosition.Y = info.dwSize.Y-1;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'C' )
- { // \033[#C - Cursor Forward (CUF)
- // Moves the cursor RIGHT # number of columns
- info.dwCursorPosition.X += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
-
- if( info.dwCursorPosition.X >= info.dwSize.X )
- info.dwCursorPosition.X = info.dwSize.X-1;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'D' )
- { // \033[#D - Cursor Backward (CUB)
- // Moves the cursor LEFT # number of columns
- info.dwCursorPosition.X -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
-
- if( info.dwCursorPosition.X < 0 )
- info.dwCursorPosition.X = 0;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'E' )
- { // \033[#E - Cursor Next Line (CNL)
- // Moves the cursor down the indicated # of rows, to column 1
- info.dwCursorPosition.Y += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
- info.dwCursorPosition.X = 0;
-
- if( info.dwCursorPosition.Y >= info.dwSize.Y )
- info.dwCursorPosition.Y = info.dwSize.Y-1;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'F' )
- { // \033[#F - Cursor Preceding Line (CPL)
- // Moves the cursor up the indicated # of rows, to column 1.
- info.dwCursorPosition.Y -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
- info.dwCursorPosition.X = 0;
-
- if( info.dwCursorPosition.Y < 0 )
- info.dwCursorPosition.Y = 0;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'G' )
- { // \033[#G - Cursor Horizontal Absolute (CHA)
- // Moves the cursor to indicated column in current row.
- info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+((numbers[numpoint]&0x0F)-1):0;
-
- if( info.dwCursorPosition.X >= info.dwSize.X )
- info.dwCursorPosition.X = info.dwSize.X-1;
- SetConsoleCursorPosition(handle, info.dwCursorPosition);
- }
- else if( *q == 'L' || *q == 'M' || *q == '@' || *q == 'P')
- { // not implemented, just skip
- }
- else
- { // no number nor valid sequencer
- // something is fishy, we break and give the current char free
- --q;
- }
- // skip the sequencer and search again
- p = q+1;
- break;
- }// end while
- }
- }
- if (*p) // write the rest of the buffer
- if( 0==WriteConsole(handle, p, (DWORD)strlen(p), &written, 0) )
- WriteFile(handle, p, (DWORD)strlen(p), &written, 0);
- FREEBUF(tempbuf);
- return 0;
+ /////////////////////////////////////////////////////////////////
+ /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
+ static COORD saveposition = {0,0};
+ */
+
+ /////////////////////////////////////////////////////////////////
+ DWORD written;
+ char *p, *q;
+ NEWBUF(tempbuf); // temporary buffer
+
+ if (!fmt || !*fmt)
+ return 0;
+
+ // Print everything to the buffer
+ BUFVPRINTF(tempbuf,fmt,argptr);
+
+ if (!is_console(handle) && stdout_with_ansisequence) {
+ WriteFile(handle, BUFVAL(tempbuf), BUFLEN(tempbuf), &written, 0);
+ return 0;
+ }
+
+ // start with processing
+ p = BUFVAL(tempbuf);
+ while ((q = strchr(p, 0x1b)) != NULL) {
+ // find the escape character
+ if (0==WriteConsole(handle, p, (DWORD)(q-p), &written, 0)) // write up to the escape
+ WriteFile(handle, p, (DWORD)(q-p), &written, 0);
+
+ if (q[1]!='[') {
+ // write the escape char (whatever purpose it has)
+ if (0==WriteConsole(handle, q, 1, &written, 0))
+ WriteFile(handle,q, 1, &written, 0);
+ p=q+1; //and start searching again
+ } else {
+ // from here, we will skip the '\033['
+ // we break at the first unprocessible position
+ // assuming regular text is starting there
+ uint8 numbers[16], numpoint=0;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+
+ // initialize
+ GetConsoleScreenBufferInfo(handle, &info);
+ memset(numbers,0,sizeof(numbers));
+
+ // skip escape and bracket
+ q=q+2;
+ for (;;) {
+ if (ISDIGIT(*q)) {
+ // add number to number array, only accept 2digits, shift out the rest
+ // so // \033[123456789m will become \033[89m
+ numbers[numpoint] = (numbers[numpoint]<<4) | (*q-'0');
+ ++q;
+ // and next character
+ continue;
+ } else if (*q == ';') {
+ // delimiter
+ if (numpoint<sizeof(numbers)/sizeof(*numbers)) {
+ // go to next array position
+ numpoint++;
+ } else {
+ // array is full, so we 'forget' the first value
+ memmove(numbers,numbers+1,sizeof(numbers)/sizeof(*numbers)-1);
+ numbers[sizeof(numbers)/sizeof(*numbers)-1]=0;
+ }
+ ++q;
+ // and next number
+ continue;
+ } else if (*q == 'm') {
+ // \033[#;...;#m - Set Graphics Rendition (SGR)
+ uint8 i;
+ for (i=0; i<= numpoint; ++i) {
+ if (0x00 == (0xF0 & numbers[i])) {
+ // upper nibble 0
+ if (0 == numbers[i]) {
+ // reset
+ info.wAttributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+ } else if (1==numbers[i]) {
+ // set foreground intensity
+ info.wAttributes |= FOREGROUND_INTENSITY;
+ } else if (5==numbers[i]) {
+ // set background intensity
+ info.wAttributes |= BACKGROUND_INTENSITY;
+ } else if (7==numbers[i]) {
+ // reverse colors (just xor them)
+ info.wAttributes ^= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
+ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
+ }
+ //case '2': // not existing
+ //case '3': // blinking (not implemented)
+ //case '4': // unterline (not implemented)
+ //case '6': // not existing
+ //case '8': // concealed (not implemented)
+ //case '9': // not existing
+ } else if (0x20 == (0xF0 & numbers[i])) {
+ // off
+
+ if (1==numbers[i]) {
+ // set foreground intensity off
+ info.wAttributes &= ~FOREGROUND_INTENSITY;
+ } else if (5==numbers[i]) {
+ // set background intensity off
+ info.wAttributes &= ~BACKGROUND_INTENSITY;
+ } else if (7==numbers[i]) {
+ // reverse colors (just xor them)
+ info.wAttributes ^= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
+ BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
+ }
+ } else if (0x30 == (0xF0 & numbers[i])) {
+ // foreground
+ uint8 num = numbers[i]&0x0F;
+ if (num==9) info.wAttributes |= FOREGROUND_INTENSITY;
+ if (num>7) num=7; // set white for 37, 38 and 39
+ info.wAttributes &= ~(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
+ if ((num & 0x01)>0) // lowest bit set = red
+ info.wAttributes |= FOREGROUND_RED;
+ if ((num & 0x02)>0) // second bit set = green
+ info.wAttributes |= FOREGROUND_GREEN;
+ if ((num & 0x04)>0) // third bit set = blue
+ info.wAttributes |= FOREGROUND_BLUE;
+ } else if (0x40 == (0xF0 & numbers[i])) {
+ // background
+ uint8 num = numbers[i]&0x0F;
+ if (num==9) info.wAttributes |= BACKGROUND_INTENSITY;
+ if (num>7) num=7; // set white for 47, 48 and 49
+ info.wAttributes &= ~(BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
+ if ((num & 0x01)>0) // lowest bit set = red
+ info.wAttributes |= BACKGROUND_RED;
+ if ((num & 0x02)>0) // second bit set = green
+ info.wAttributes |= BACKGROUND_GREEN;
+ if ((num & 0x04)>0) // third bit set = blue
+ info.wAttributes |= BACKGROUND_BLUE;
+ }
+ }
+ // set the attributes
+ SetConsoleTextAttribute(handle, info.wAttributes);
+ } else if (*q=='J') {
+ // \033[#J - Erase Display (ED)
+ // \033[0J - Clears the screen from cursor to end of display. The cursor position is unchanged.
+ // \033[1J - Clears the screen from start to cursor. The cursor position is unchanged.
+ // \033[2J - Clears the screen and moves the cursor to the home position (line 1, column 1).
+ uint8 num = (numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F);
+ int cnt;
+ DWORD tmp;
+ COORD origin = {0,0};
+ if (num==1) {
+ // chars from start up to and including cursor
+ cnt = info.dwSize.X * info.dwCursorPosition.Y + info.dwCursorPosition.X + 1;
+ } else if (num==2) {
+ // Number of chars on screen.
+ cnt = info.dwSize.X * info.dwSize.Y;
+ SetConsoleCursorPosition(handle, origin);
+ } else { // 0 and default
+ // number of chars from cursor to end
+ origin = info.dwCursorPosition;
+ cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X;
+ }
+ FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, &tmp);
+ FillConsoleOutputCharacter(handle, ' ', cnt, origin, &tmp);
+ } else if (*q=='K') {
+ // \033[K : clear line from actual position to end of the line
+ // \033[0K - Clears all characters from the cursor position to the end of the line.
+ // \033[1K - Clears all characters from start of line to the cursor position.
+ // \033[2K - Clears all characters of the whole line.
+
+ uint8 num = (numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F);
+ COORD origin = {0,info.dwCursorPosition.Y}; //warning C4204
+ SHORT cnt;
+ DWORD tmp;
+ if (num==1) {
+ cnt = info.dwCursorPosition.X + 1;
+ } else if (num==2) {
+ cnt = info.dwSize.X;
+ } else { // 0 and default
+ origin = info.dwCursorPosition;
+ cnt = info.dwSize.X - info.dwCursorPosition.X; // how many spaces until line is full
+ }
+ FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, &tmp);
+ FillConsoleOutputCharacter(handle, ' ', cnt, origin, &tmp);
+ } else if (*q == 'H' || *q == 'f') {
+ // \033[#;#H - Cursor Position (CUP)
+ // \033[#;#f - Horizontal & Vertical Position
+ // The first # specifies the line number, the second # specifies the column.
+ // The default for both is 1
+ info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+((numbers[numpoint]&0x0F)-1):0;
+ info.dwCursorPosition.Y = (numpoint && numbers[numpoint-1])?(numbers[numpoint-1]>>4)*10+((numbers[numpoint-1]&0x0F)-1):0;
+
+ if (info.dwCursorPosition.X >= info.dwSize.X) info.dwCursorPosition.Y = info.dwSize.X-1;
+ if (info.dwCursorPosition.Y >= info.dwSize.Y) info.dwCursorPosition.Y = info.dwSize.Y-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q=='s') {
+ // \033[s - Save Cursor Position (SCP)
+ /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo(handle, &info);
+ saveposition = info.dwCursorPosition;
+ */
+ } else if (*q=='u') {
+ // \033[u - Restore cursor position (RCP)
+ /* XXX Two streams are being used. Disabled to avoid inconsistency [flaviojs]
+ SetConsoleCursorPosition(handle, saveposition);
+ */
+ } else if (*q == 'A') {
+ // \033[#A - Cursor Up (CUU)
+ // Moves the cursor UP # number of lines
+ info.dwCursorPosition.Y -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if (info.dwCursorPosition.Y < 0)
+ info.dwCursorPosition.Y = 0;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'B') {
+ // \033[#B - Cursor Down (CUD)
+ // Moves the cursor DOWN # number of lines
+ info.dwCursorPosition.Y += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if (info.dwCursorPosition.Y >= info.dwSize.Y)
+ info.dwCursorPosition.Y = info.dwSize.Y-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'C') {
+ // \033[#C - Cursor Forward (CUF)
+ // Moves the cursor RIGHT # number of columns
+ info.dwCursorPosition.X += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if (info.dwCursorPosition.X >= info.dwSize.X)
+ info.dwCursorPosition.X = info.dwSize.X-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'D') {
+ // \033[#D - Cursor Backward (CUB)
+ // Moves the cursor LEFT # number of columns
+ info.dwCursorPosition.X -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+
+ if (info.dwCursorPosition.X < 0)
+ info.dwCursorPosition.X = 0;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'E') {
+ // \033[#E - Cursor Next Line (CNL)
+ // Moves the cursor down the indicated # of rows, to column 1
+ info.dwCursorPosition.Y += (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+ info.dwCursorPosition.X = 0;
+
+ if (info.dwCursorPosition.Y >= info.dwSize.Y)
+ info.dwCursorPosition.Y = info.dwSize.Y-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'F') {
+ // \033[#F - Cursor Preceding Line (CPL)
+ // Moves the cursor up the indicated # of rows, to column 1.
+ info.dwCursorPosition.Y -= (numbers[numpoint])?(numbers[numpoint]>>4)*10+(numbers[numpoint]&0x0F):1;
+ info.dwCursorPosition.X = 0;
+
+ if (info.dwCursorPosition.Y < 0)
+ info.dwCursorPosition.Y = 0;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'G') {
+ // \033[#G - Cursor Horizontal Absolute (CHA)
+ // Moves the cursor to indicated column in current row.
+ info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+((numbers[numpoint]&0x0F)-1):0;
+
+ if (info.dwCursorPosition.X >= info.dwSize.X)
+ info.dwCursorPosition.X = info.dwSize.X-1;
+ SetConsoleCursorPosition(handle, info.dwCursorPosition);
+ } else if (*q == 'L' || *q == 'M' || *q == '@' || *q == 'P') {
+ // not implemented, just skip
+ } else {
+ // no number nor valid sequencer
+ // something is fishy, we break and give the current char free
+ --q;
+ }
+ // skip the sequencer and search again
+ p = q+1;
+ break;
+ }// end while
+ }
+ }
+ if (*p) // write the rest of the buffer
+ if (0==WriteConsole(handle, p, (DWORD)strlen(p), &written, 0))
+ WriteFile(handle, p, (DWORD)strlen(p), &written, 0);
+ FREEBUF(tempbuf);
+ return 0;
}
-int FPRINTF(HANDLE handle, const char *fmt, ...)
+int FPRINTF(HANDLE handle, const char *fmt, ...)
{
- int ret;
- va_list argptr;
- va_start(argptr, fmt);
- ret = VFPRINTF(handle,fmt,argptr);
- va_end(argptr);
- return ret;
+ int ret;
+ va_list argptr;
+ va_start(argptr, fmt);
+ ret = VFPRINTF(handle,fmt,argptr);
+ va_end(argptr);
+ return ret;
}
#define FFLUSH(handle)
@@ -532,129 +496,109 @@ int FPRINTF(HANDLE handle, const char *fmt, ...)
#define is_console(file) (0!=isatty(fileno(file)))
//vprintf_without_ansiformats
-int VFPRINTF(FILE *file, const char *fmt, va_list argptr)
+int VFPRINTF(FILE *file, const char *fmt, va_list argptr)
{
- char *p, *q;
- NEWBUF(tempbuf); // temporary buffer
-
- if(!fmt || !*fmt)
- return 0;
-
- if( is_console(file) || stdout_with_ansisequence )
- {
- vfprintf(file, fmt, argptr);
- return 0;
- }
-
- // Print everything to the buffer
- BUFVPRINTF(tempbuf,fmt,argptr);
-
- // start with processing
- p = BUFVAL(tempbuf);
- while ((q = strchr(p, 0x1b)) != NULL)
- { // find the escape character
- fprintf(file, "%.*s", (int)(q-p), p); // write up to the escape
- if( q[1]!='[' )
- { // write the escape char (whatever purpose it has)
- fprintf(file, "%.*s", 1, q);
- p=q+1; //and start searching again
- }
- else
- { // from here, we will skip the '\033['
- // we break at the first unprocessible position
- // assuming regular text is starting there
-
- // skip escape and bracket
- q=q+2;
- while(1)
- {
- if( ISDIGIT(*q) )
- {
- ++q;
- // and next character
- continue;
- }
- else if( *q == ';' )
- { // delimiter
- ++q;
- // and next number
- continue;
- }
- else if( *q == 'm' )
- { // \033[#;...;#m - Set Graphics Rendition (SGR)
- // set the attributes
- }
- else if( *q=='J' )
- { // \033[#J - Erase Display (ED)
- }
- else if( *q=='K' )
- { // \033[K : clear line from actual position to end of the line
- }
- else if( *q == 'H' || *q == 'f' )
- { // \033[#;#H - Cursor Position (CUP)
- // \033[#;#f - Horizontal & Vertical Position
- }
- else if( *q=='s' )
- { // \033[s - Save Cursor Position (SCP)
- }
- else if( *q=='u' )
- { // \033[u - Restore cursor position (RCP)
- }
- else if( *q == 'A' )
- { // \033[#A - Cursor Up (CUU)
- // Moves the cursor UP # number of lines
- }
- else if( *q == 'B' )
- { // \033[#B - Cursor Down (CUD)
- // Moves the cursor DOWN # number of lines
- }
- else if( *q == 'C' )
- { // \033[#C - Cursor Forward (CUF)
- // Moves the cursor RIGHT # number of columns
- }
- else if( *q == 'D' )
- { // \033[#D - Cursor Backward (CUB)
- // Moves the cursor LEFT # number of columns
- }
- else if( *q == 'E' )
- { // \033[#E - Cursor Next Line (CNL)
- // Moves the cursor down the indicated # of rows, to column 1
- }
- else if( *q == 'F' )
- { // \033[#F - Cursor Preceding Line (CPL)
- // Moves the cursor up the indicated # of rows, to column 1.
- }
- else if( *q == 'G' )
- { // \033[#G - Cursor Horizontal Absolute (CHA)
- // Moves the cursor to indicated column in current row.
- }
- else if( *q == 'L' || *q == 'M' || *q == '@' || *q == 'P')
- { // not implemented, just skip
- }
- else
- { // no number nor valid sequencer
- // something is fishy, we break and give the current char free
- --q;
- }
- // skip the sequencer and search again
- p = q+1;
- break;
- }// end while
- }
- }
- if (*p) // write the rest of the buffer
- fprintf(file, "%s", p);
- FREEBUF(tempbuf);
- return 0;
+ char *p, *q;
+ NEWBUF(tempbuf); // temporary buffer
+
+ if (!fmt || !*fmt)
+ return 0;
+
+ if (is_console(file) || stdout_with_ansisequence) {
+ vfprintf(file, fmt, argptr);
+ return 0;
+ }
+
+ // Print everything to the buffer
+ BUFVPRINTF(tempbuf,fmt,argptr);
+
+ // start with processing
+ p = BUFVAL(tempbuf);
+ while ((q = strchr(p, 0x1b)) != NULL) {
+ // find the escape character
+ fprintf(file, "%.*s", (int)(q-p), p); // write up to the escape
+ if (q[1]!='[') {
+ // write the escape char (whatever purpose it has)
+ fprintf(file, "%.*s", 1, q);
+ p=q+1; //and start searching again
+ } else {
+ // from here, we will skip the '\033['
+ // we break at the first unprocessible position
+ // assuming regular text is starting there
+
+ // skip escape and bracket
+ q=q+2;
+ while (1) {
+ if (ISDIGIT(*q)) {
+ ++q;
+ // and next character
+ continue;
+ } else if (*q == ';') {
+ // delimiter
+ ++q;
+ // and next number
+ continue;
+ } else if (*q == 'm') {
+ // \033[#;...;#m - Set Graphics Rendition (SGR)
+ // set the attributes
+ } else if (*q=='J') {
+ // \033[#J - Erase Display (ED)
+ } else if (*q=='K') {
+ // \033[K : clear line from actual position to end of the line
+ } else if (*q == 'H' || *q == 'f') {
+ // \033[#;#H - Cursor Position (CUP)
+ // \033[#;#f - Horizontal & Vertical Position
+ } else if (*q=='s') {
+ // \033[s - Save Cursor Position (SCP)
+ } else if (*q=='u') {
+ // \033[u - Restore cursor position (RCP)
+ } else if (*q == 'A') {
+ // \033[#A - Cursor Up (CUU)
+ // Moves the cursor UP # number of lines
+ } else if (*q == 'B') {
+ // \033[#B - Cursor Down (CUD)
+ // Moves the cursor DOWN # number of lines
+ } else if (*q == 'C') {
+ // \033[#C - Cursor Forward (CUF)
+ // Moves the cursor RIGHT # number of columns
+ } else if (*q == 'D') {
+ // \033[#D - Cursor Backward (CUB)
+ // Moves the cursor LEFT # number of columns
+ } else if (*q == 'E') {
+ // \033[#E - Cursor Next Line (CNL)
+ // Moves the cursor down the indicated # of rows, to column 1
+ } else if (*q == 'F') {
+ // \033[#F - Cursor Preceding Line (CPL)
+ // Moves the cursor up the indicated # of rows, to column 1.
+ } else if (*q == 'G') {
+ // \033[#G - Cursor Horizontal Absolute (CHA)
+ // Moves the cursor to indicated column in current row.
+ } else if (*q == 'L' || *q == 'M' || *q == '@' || *q == 'P') {
+ // not implemented, just skip
+ } else {
+ // no number nor valid sequencer
+ // something is fishy, we break and give the current char free
+ --q;
+ }
+ // skip the sequencer and search again
+ p = q+1;
+ break;
+ }// end while
+ }
+ }
+ if (*p) // write the rest of the buffer
+ fprintf(file, "%s", p);
+ FREEBUF(tempbuf);
+ return 0;
}
-int FPRINTF(FILE *file, const char *fmt, ...)
+int FPRINTF(FILE *file, const char *fmt, ...)
{
- int ret;
- va_list argptr;
- va_start(argptr, fmt);
- ret = VFPRINTF(file,fmt,argptr);
- va_end(argptr);
- return ret;
+ int ret;
+ va_list argptr;
+ va_start(argptr, fmt);
+ ret = VFPRINTF(file,fmt,argptr);
+ va_end(argptr);
+ return ret;
}
#define FFLUSH fflush
@@ -677,216 +621,225 @@ char timestamp_format[20] = ""; //For displaying Timestamps
int _vShowMessage(enum msg_type flag, const char *string, va_list ap)
{
- va_list apcopy;
- char prefix[100];
+ va_list apcopy;
+ char prefix[100];
#if defined(DEBUGLOGMAP) || defined(DEBUGLOGCHAR) || defined(DEBUGLOGLOGIN)
- FILE *fp;
+ FILE *fp;
#endif
-
- if (!string || *string == '\0') {
- ShowError("Empty string passed to _vShowMessage().\n");
- return 1;
- }
- /**
- * For the buildbot, these result in a EXIT_FAILURE from core.c when done reading the params.
- **/
+
+ if (!string || *string == '\0') {
+ ShowError("Empty string passed to _vShowMessage().\n");
+ return 1;
+ }
+ /**
+ * For the buildbot, these result in a EXIT_FAILURE from core.c when done reading the params.
+ **/
#if defined(BUILDBOT)
- if( flag == MSG_WARNING ||
- flag == MSG_ERROR ||
- flag == MSG_SQL ) {
- buildbotflag = 1;
- }
+ if (flag == MSG_WARNING ||
+ flag == MSG_ERROR ||
+ flag == MSG_SQL) {
+ buildbotflag = 1;
+ }
#endif
- if(
- ( flag == MSG_WARNING && console_msg_log&1 ) ||
- ( ( flag == MSG_ERROR || flag == MSG_SQL ) && console_msg_log&2 ) ||
- ( flag == MSG_DEBUG && console_msg_log&4 ) ) {//[Ind]
- FILE *log = NULL;
- if( (log = fopen(SERVER_TYPE == ATHENA_SERVER_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) {
- char timestring[255];
- time_t curtime;
- time(&curtime);
- strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
- fprintf(log,"(%s) [ %s ] : ",
- timestring,
- flag == MSG_WARNING ? "Warning" :
- flag == MSG_ERROR ? "Error" :
- flag == MSG_SQL ? "SQL Error" :
- flag == MSG_DEBUG ? "Debug" :
- "Unknown");
- va_copy(apcopy, ap);
- vfprintf(log,string,apcopy);
- va_end(apcopy);
- fclose(log);
- }
- }
- if(
- (flag == MSG_INFORMATION && msg_silent&1) ||
- (flag == MSG_STATUS && msg_silent&2) ||
- (flag == MSG_NOTICE && msg_silent&4) ||
- (flag == MSG_WARNING && msg_silent&8) ||
- (flag == MSG_ERROR && msg_silent&16) ||
- (flag == MSG_SQL && msg_silent&16) ||
- (flag == MSG_DEBUG && msg_silent&32)
- )
- return 0; //Do not print it.
-
- if (timestamp_format[0] && flag != MSG_NONE)
- { //Display time format. [Skotlex]
- time_t t = time(NULL);
- strftime(prefix, 80, timestamp_format, localtime(&t));
- } else prefix[0]='\0';
-
- switch (flag) {
- case MSG_NONE: // direct printf replacement
- break;
- case MSG_STATUS: //Bright Green (To inform about good things)
- strcat(prefix,CL_GREEN"[Status]"CL_RESET":");
- break;
- case MSG_SQL: //Bright Violet (For dumping out anything related with SQL) <- Actually, this is mostly used for SQL errors with the database, as successes can as well just be anything else... [Skotlex]
- strcat(prefix,CL_MAGENTA"[SQL]"CL_RESET":");
- break;
- case MSG_INFORMATION: //Bright White (Variable information)
- strcat(prefix,CL_WHITE"[Info]"CL_RESET":");
- break;
- case MSG_NOTICE: //Bright White (Less than a warning)
- strcat(prefix,CL_WHITE"[Notice]"CL_RESET":");
- break;
- case MSG_WARNING: //Bright Yellow
- strcat(prefix,CL_YELLOW"[Warning]"CL_RESET":");
- break;
- case MSG_DEBUG: //Bright Cyan, important stuff!
- strcat(prefix,CL_CYAN"[Debug]"CL_RESET":");
- break;
- case MSG_ERROR: //Bright Red (Regular errors)
- strcat(prefix,CL_RED"[Error]"CL_RESET":");
- break;
- case MSG_FATALERROR: //Bright Red (Fatal errors, abort(); if possible)
- strcat(prefix,CL_RED"[Fatal Error]"CL_RESET":");
- break;
- default:
- ShowError("In function _vShowMessage() -> Invalid flag passed.\n");
- return 1;
- }
-
- if (flag == MSG_ERROR || flag == MSG_FATALERROR || flag == MSG_SQL)
- { //Send Errors to StdErr [Skotlex]
- FPRINTF(STDERR, "%s ", prefix);
- va_copy(apcopy, ap);
- VFPRINTF(STDERR, string, apcopy);
- va_end(apcopy);
- FFLUSH(STDERR);
- } else {
- if (flag != MSG_NONE)
- FPRINTF(STDOUT, "%s ", prefix);
- va_copy(apcopy, ap);
- VFPRINTF(STDOUT, string, apcopy);
- va_end(apcopy);
- FFLUSH(STDOUT);
- }
+ if (
+ (flag == MSG_WARNING && console_msg_log&1) ||
+ ((flag == MSG_ERROR || flag == MSG_SQL) && console_msg_log&2) ||
+ (flag == MSG_DEBUG && console_msg_log&4)) { //[Ind]
+ FILE *log = NULL;
+ if ((log = fopen(SERVER_TYPE == ATHENA_SERVER_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+"))) {
+ char timestring[255];
+ time_t curtime;
+ time(&curtime);
+ strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
+ fprintf(log,"(%s) [ %s ] : ",
+ timestring,
+ flag == MSG_WARNING ? "Warning" :
+ flag == MSG_ERROR ? "Error" :
+ flag == MSG_SQL ? "SQL Error" :
+ flag == MSG_DEBUG ? "Debug" :
+ "Unknown");
+ va_copy(apcopy, ap);
+ vfprintf(log,string,apcopy);
+ va_end(apcopy);
+ fclose(log);
+ }
+ }
+ if (
+ (flag == MSG_INFORMATION && msg_silent&1) ||
+ (flag == MSG_STATUS && msg_silent&2) ||
+ (flag == MSG_NOTICE && msg_silent&4) ||
+ (flag == MSG_WARNING && msg_silent&8) ||
+ (flag == MSG_ERROR && msg_silent&16) ||
+ (flag == MSG_SQL && msg_silent&16) ||
+ (flag == MSG_DEBUG && msg_silent&32)
+ )
+ return 0; //Do not print it.
+
+ if (timestamp_format[0] && flag != MSG_NONE) {
+ //Display time format. [Skotlex]
+ time_t t = time(NULL);
+ strftime(prefix, 80, timestamp_format, localtime(&t));
+ } else prefix[0]='\0';
+
+ switch (flag) {
+ case MSG_NONE: // direct printf replacement
+ break;
+ case MSG_STATUS: //Bright Green (To inform about good things)
+ strcat(prefix,CL_GREEN"[Status]"CL_RESET":");
+ break;
+ case MSG_SQL: //Bright Violet (For dumping out anything related with SQL) <- Actually, this is mostly used for SQL errors with the database, as successes can as well just be anything else... [Skotlex]
+ strcat(prefix,CL_MAGENTA"[SQL]"CL_RESET":");
+ break;
+ case MSG_INFORMATION: //Bright White (Variable information)
+ strcat(prefix,CL_WHITE"[Info]"CL_RESET":");
+ break;
+ case MSG_NOTICE: //Bright White (Less than a warning)
+ strcat(prefix,CL_WHITE"[Notice]"CL_RESET":");
+ break;
+ case MSG_WARNING: //Bright Yellow
+ strcat(prefix,CL_YELLOW"[Warning]"CL_RESET":");
+ break;
+ case MSG_DEBUG: //Bright Cyan, important stuff!
+ strcat(prefix,CL_CYAN"[Debug]"CL_RESET":");
+ break;
+ case MSG_ERROR: //Bright Red (Regular errors)
+ strcat(prefix,CL_RED"[Error]"CL_RESET":");
+ break;
+ case MSG_FATALERROR: //Bright Red (Fatal errors, abort(); if possible)
+ strcat(prefix,CL_RED"[Fatal Error]"CL_RESET":");
+ break;
+ default:
+ ShowError("In function _vShowMessage() -> Invalid flag passed.\n");
+ return 1;
+ }
+
+ if (flag == MSG_ERROR || flag == MSG_FATALERROR || flag == MSG_SQL) {
+ //Send Errors to StdErr [Skotlex]
+ FPRINTF(STDERR, "%s ", prefix);
+ va_copy(apcopy, ap);
+ VFPRINTF(STDERR, string, apcopy);
+ va_end(apcopy);
+ FFLUSH(STDERR);
+ } else {
+ if (flag != MSG_NONE)
+ FPRINTF(STDOUT, "%s ", prefix);
+ va_copy(apcopy, ap);
+ VFPRINTF(STDOUT, string, apcopy);
+ va_end(apcopy);
+ FFLUSH(STDOUT);
+ }
#if defined(DEBUGLOGMAP) || defined(DEBUGLOGCHAR) || defined(DEBUGLOGLOGIN)
- if(strlen(DEBUGLOGPATH) > 0) {
- fp=fopen(DEBUGLOGPATH,"a");
- if (fp == NULL) {
- FPRINTF(STDERR, CL_RED"[ERROR]"CL_RESET": Could not open '"CL_WHITE"%s"CL_RESET"', access denied.\n", DEBUGLOGPATH);
- FFLUSH(STDERR);
- } else {
- fprintf(fp,"%s ", prefix);
- va_copy(apcopy, ap);
- vfprintf(fp,string,apcopy);
- va_end(apcopy);
- fclose(fp);
- }
- } else {
- FPRINTF(STDERR, CL_RED"[ERROR]"CL_RESET": DEBUGLOGPATH not defined!\n");
- FFLUSH(STDERR);
- }
+ if (strlen(DEBUGLOGPATH) > 0) {
+ fp=fopen(DEBUGLOGPATH,"a");
+ if (fp == NULL) {
+ FPRINTF(STDERR, CL_RED"[ERROR]"CL_RESET": Could not open '"CL_WHITE"%s"CL_RESET"', access denied.\n", DEBUGLOGPATH);
+ FFLUSH(STDERR);
+ } else {
+ fprintf(fp,"%s ", prefix);
+ va_copy(apcopy, ap);
+ vfprintf(fp,string,apcopy);
+ va_end(apcopy);
+ fclose(fp);
+ }
+ } else {
+ FPRINTF(STDERR, CL_RED"[ERROR]"CL_RESET": DEBUGLOGPATH not defined!\n");
+ FFLUSH(STDERR);
+ }
#endif
- return 0;
+ return 0;
}
void ClearScreen(void)
{
#ifndef _WIN32
- ShowMessage(CL_CLS); // to prevent empty string passed messages
+ ShowMessage(CL_CLS); // to prevent empty string passed messages
#endif
}
int _ShowMessage(enum msg_type flag, const char *string, ...)
{
- int ret;
- va_list ap;
- va_start(ap, string);
- ret = _vShowMessage(flag, string, ap);
- va_end(ap);
- return ret;
+ int ret;
+ va_list ap;
+ va_start(ap, string);
+ ret = _vShowMessage(flag, string, ap);
+ va_end(ap);
+ return ret;
}
// direct printf replacement
-void ShowMessage(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_NONE, string, ap);
- va_end(ap);
+void ShowMessage(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_NONE, string, ap);
+ va_end(ap);
}
-void ShowStatus(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_STATUS, string, ap);
- va_end(ap);
+void ShowStatus(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_STATUS, string, ap);
+ va_end(ap);
}
-void ShowSQL(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_SQL, string, ap);
- va_end(ap);
+void ShowSQL(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_SQL, string, ap);
+ va_end(ap);
}
-void ShowInfo(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_INFORMATION, string, ap);
- va_end(ap);
+void ShowInfo(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_INFORMATION, string, ap);
+ va_end(ap);
}
-void ShowNotice(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_NOTICE, string, ap);
- va_end(ap);
+void ShowNotice(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_NOTICE, string, ap);
+ va_end(ap);
}
-void ShowWarning(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_WARNING, string, ap);
- va_end(ap);
+void ShowWarning(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_WARNING, string, ap);
+ va_end(ap);
}
void ShowConfigWarning(config_setting_t *config, const char *string, ...)
{
- StringBuf buf;
- va_list ap;
- StringBuf_Init(&buf);
- StringBuf_AppendStr(&buf, string);
- StringBuf_Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config));
- va_start(ap, string);
- _vShowMessage(MSG_WARNING, StringBuf_Value(&buf), ap);
- va_end(ap);
- StringBuf_Destroy(&buf);
+ StringBuf buf;
+ va_list ap;
+ StringBuf_Init(&buf);
+ StringBuf_AppendStr(&buf, string);
+ StringBuf_Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config));
+ va_start(ap, string);
+ _vShowMessage(MSG_WARNING, StringBuf_Value(&buf), ap);
+ va_end(ap);
+ StringBuf_Destroy(&buf);
}
-void ShowDebug(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_DEBUG, string, ap);
- va_end(ap);
+void ShowDebug(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_DEBUG, string, ap);
+ va_end(ap);
}
-void ShowError(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_ERROR, string, ap);
- va_end(ap);
+void ShowError(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_ERROR, string, ap);
+ va_end(ap);
}
-void ShowFatalError(const char *string, ...) {
- va_list ap;
- va_start(ap, string);
- _vShowMessage(MSG_FATALERROR, string, ap);
- va_end(ap);
+void ShowFatalError(const char *string, ...)
+{
+ va_list ap;
+ va_start(ap, string);
+ _vShowMessage(MSG_FATALERROR, string, ap);
+ va_end(ap);
}
diff --git a/src/common/showmsg.h b/src/common/showmsg.h
index 0d6cb5c9f..8c2b5bd42 100644
--- a/src/common/showmsg.h
+++ b/src/common/showmsg.h
@@ -14,58 +14,58 @@
// \033[0m : reset color parameter
// \033[1m : use bold for font
-#define CL_RESET "\033[0m"
-#define CL_CLS "\033[2J"
-#define CL_CLL "\033[K"
+#define CL_RESET "\033[0m"
+#define CL_CLS "\033[2J"
+#define CL_CLL "\033[K"
// font settings
-#define CL_BOLD "\033[1m"
-#define CL_NORM CL_RESET
-#define CL_NORMAL CL_RESET
-#define CL_NONE CL_RESET
+#define CL_BOLD "\033[1m"
+#define CL_NORM CL_RESET
+#define CL_NORMAL CL_RESET
+#define CL_NONE CL_RESET
// foreground color and bold font (bright color on windows)
-#define CL_WHITE "\033[1;37m"
-#define CL_GRAY "\033[1;30m"
-#define CL_RED "\033[1;31m"
-#define CL_GREEN "\033[1;32m"
-#define CL_YELLOW "\033[1;33m"
-#define CL_BLUE "\033[1;34m"
-#define CL_MAGENTA "\033[1;35m"
-#define CL_CYAN "\033[1;36m"
+#define CL_WHITE "\033[1;37m"
+#define CL_GRAY "\033[1;30m"
+#define CL_RED "\033[1;31m"
+#define CL_GREEN "\033[1;32m"
+#define CL_YELLOW "\033[1;33m"
+#define CL_BLUE "\033[1;34m"
+#define CL_MAGENTA "\033[1;35m"
+#define CL_CYAN "\033[1;36m"
// background color
-#define CL_BG_BLACK "\033[40m"
-#define CL_BG_RED "\033[41m"
-#define CL_BG_GREEN "\033[42m"
-#define CL_BG_YELLOW "\033[43m"
-#define CL_BG_BLUE "\033[44m"
-#define CL_BG_MAGENTA "\033[45m"
-#define CL_BG_CYAN "\033[46m"
-#define CL_BG_WHITE "\033[47m"
+#define CL_BG_BLACK "\033[40m"
+#define CL_BG_RED "\033[41m"
+#define CL_BG_GREEN "\033[42m"
+#define CL_BG_YELLOW "\033[43m"
+#define CL_BG_BLUE "\033[44m"
+#define CL_BG_MAGENTA "\033[45m"
+#define CL_BG_CYAN "\033[46m"
+#define CL_BG_WHITE "\033[47m"
// foreground color and normal font (normal color on windows)
-#define CL_LT_BLACK "\033[0;30m"
-#define CL_LT_RED "\033[0;31m"
-#define CL_LT_GREEN "\033[0;32m"
-#define CL_LT_YELLOW "\033[0;33m"
-#define CL_LT_BLUE "\033[0;34m"
-#define CL_LT_MAGENTA "\033[0;35m"
-#define CL_LT_CYAN "\033[0;36m"
-#define CL_LT_WHITE "\033[0;37m"
+#define CL_LT_BLACK "\033[0;30m"
+#define CL_LT_RED "\033[0;31m"
+#define CL_LT_GREEN "\033[0;32m"
+#define CL_LT_YELLOW "\033[0;33m"
+#define CL_LT_BLUE "\033[0;34m"
+#define CL_LT_MAGENTA "\033[0;35m"
+#define CL_LT_CYAN "\033[0;36m"
+#define CL_LT_WHITE "\033[0;37m"
// foreground color and bold font (bright color on windows)
-#define CL_BT_BLACK "\033[1;30m"
-#define CL_BT_RED "\033[1;31m"
-#define CL_BT_GREEN "\033[1;32m"
-#define CL_BT_YELLOW "\033[1;33m"
-#define CL_BT_BLUE "\033[1;34m"
-#define CL_BT_MAGENTA "\033[1;35m"
-#define CL_BT_CYAN "\033[1;36m"
-#define CL_BT_WHITE "\033[1;37m"
+#define CL_BT_BLACK "\033[1;30m"
+#define CL_BT_RED "\033[1;31m"
+#define CL_BT_GREEN "\033[1;32m"
+#define CL_BT_YELLOW "\033[1;33m"
+#define CL_BT_BLUE "\033[1;34m"
+#define CL_BT_MAGENTA "\033[1;35m"
+#define CL_BT_CYAN "\033[1;36m"
+#define CL_BT_WHITE "\033[1;37m"
-#define CL_WTBL "\033[37;44m" // white on blue
-#define CL_XXBL "\033[0;44m" // default on blue
-#define CL_PASS "\033[0;32;42m" // green on green
+#define CL_WTBL "\033[37;44m" // white on blue
+#define CL_XXBL "\033[0;44m" // default on blue
+#define CL_PASS "\033[0;32;42m" // green on green
-#define CL_SPACE " " // space aquivalent of the print messages
+#define CL_SPACE " " // space aquivalent of the print messages
extern int stdout_with_ansisequence; //If the color ansi sequences are to be used. [flaviojs]
extern int msg_silent; //Specifies how silent the console is. [Skotlex]
@@ -73,15 +73,15 @@ extern int console_msg_log; //Specifies what error messages to log. [Ind]
extern char timestamp_format[20]; //For displaying Timestamps [Skotlex]
enum msg_type {
- MSG_NONE,
- MSG_STATUS,
- MSG_SQL,
- MSG_INFORMATION,
- MSG_NOTICE,
- MSG_WARNING,
- MSG_DEBUG,
- MSG_ERROR,
- MSG_FATALERROR
+ MSG_NONE,
+ MSG_STATUS,
+ MSG_SQL,
+ MSG_INFORMATION,
+ MSG_NOTICE,
+ MSG_WARNING,
+ MSG_DEBUG,
+ MSG_ERROR,
+ MSG_FATALERROR
};
extern void ClearScreen(void);
diff --git a/src/common/socket.c b/src/common/socket.c
index d24a9c1d8..4a6e01459 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -15,35 +15,35 @@
#include <sys/types.h>
#ifdef WIN32
- #include "../common/winapi.h"
+#include "../common/winapi.h"
#else
- #include <errno.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <net/if.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <sys/ioctl.h>
- #include <netdb.h>
- #include <arpa/inet.h>
-
- #ifndef SIOCGIFCONF
- #include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori]
- #endif
- #ifndef FIONBIO
- #include <sys/filio.h> // FIONBIO on Solaris [FlavioJS]
- #endif
-
- #ifdef HAVE_SETRLIMIT
- #include <sys/resource.h>
- #endif
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#ifndef SIOCGIFCONF
+#include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori]
+#endif
+#ifndef FIONBIO
+#include <sys/filio.h> // FIONBIO on Solaris [FlavioJS]
+#endif
+
+#ifdef HAVE_SETRLIMIT
+#include <sys/resource.h>
+#endif
#endif
/////////////////////////////////////////////////////////////////////
#if defined(WIN32)
/////////////////////////////////////////////////////////////////////
-// windows portability layer
+// windows portability layer
typedef int socklen_t;
@@ -75,21 +75,21 @@ static int sock_arr_len = 0;
/// @return Fd or -1
int sock2fd(SOCKET s)
{
- int fd;
-
- // search for the socket
- for( fd = 1; fd < sock_arr_len; ++fd )
- if( sock_arr[fd] == s )
- break;// found the socket
- if( fd == sock_arr_len )
- return -1;// not found
- return fd;
+ int fd;
+
+ // search for the socket
+ for (fd = 1; fd < sock_arr_len; ++fd)
+ if (sock_arr[fd] == s)
+ break;// found the socket
+ if (fd == sock_arr_len)
+ return -1;// not found
+ return fd;
}
/// Inserts the socket into the global array of sockets.
/// Returns a new fd associated with the socket.
-/// If there are too many sockets it closes the socket, sets an error and
+/// If there are too many sockets it closes the socket, sets an error and
// returns -1 instead.
/// Since fd 0 is reserved, it returns values in the range [1,FD_SETSIZE[.
///
@@ -97,61 +97,61 @@ int sock2fd(SOCKET s)
/// @return New fd or -1
int sock2newfd(SOCKET s)
{
- int fd;
-
- // find an empty position
- for( fd = 1; fd < sock_arr_len; ++fd )
- if( sock_arr[fd] == INVALID_SOCKET )
- break;// empty position
- if( fd == ARRAYLENGTH(sock_arr) )
- {// too many sockets
- closesocket(s);
- WSASetLastError(WSAEMFILE);
- return -1;
- }
- sock_arr[fd] = s;
- if( sock_arr_len <= fd )
- sock_arr_len = fd+1;
- return fd;
+ int fd;
+
+ // find an empty position
+ for (fd = 1; fd < sock_arr_len; ++fd)
+ if (sock_arr[fd] == INVALID_SOCKET)
+ break;// empty position
+ if (fd == ARRAYLENGTH(sock_arr)) {
+ // too many sockets
+ closesocket(s);
+ WSASetLastError(WSAEMFILE);
+ return -1;
+ }
+ sock_arr[fd] = s;
+ if (sock_arr_len <= fd)
+ sock_arr_len = fd+1;
+ return fd;
}
-int sAccept(int fd, struct sockaddr* addr, int* addrlen)
+int sAccept(int fd, struct sockaddr *addr, int *addrlen)
{
- SOCKET s;
+ SOCKET s;
- // accept connection
- s = accept(fd2sock(fd), addr, addrlen);
- if( s == INVALID_SOCKET )
- return -1;// error
- return sock2newfd(s);
+ // accept connection
+ s = accept(fd2sock(fd), addr, addrlen);
+ if (s == INVALID_SOCKET)
+ return -1;// error
+ return sock2newfd(s);
}
int sClose(int fd)
{
- int ret = closesocket(fd2sock(fd));
- fd2sock(fd) = INVALID_SOCKET;
- return ret;
+ int ret = closesocket(fd2sock(fd));
+ fd2sock(fd) = INVALID_SOCKET;
+ return ret;
}
int sSocket(int af, int type, int protocol)
{
- SOCKET s;
+ SOCKET s;
- // create socket
- s = socket(af,type,protocol);
- if( s == INVALID_SOCKET )
- return -1;// error
- return sock2newfd(s);
+ // create socket
+ s = socket(af,type,protocol);
+ if (s == INVALID_SOCKET)
+ return -1;// error
+ return sock2newfd(s);
}
-char* sErr(int code)
+char *sErr(int code)
{
- static char sbuf[512];
- // strerror does not handle socket codes
- if( FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
- code, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR)&sbuf, sizeof(sbuf), NULL) == 0 )
- snprintf(sbuf, sizeof(sbuf), "unknown error");
- return sbuf;
+ static char sbuf[512];
+ // strerror does not handle socket codes
+ if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
+ code, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR)&sbuf, sizeof(sbuf), NULL) == 0)
+ snprintf(sbuf, sizeof(sbuf), "unknown error");
+ return sbuf;
}
#define sBind(fd,name,namelen) bind(fd2sock(fd),name,namelen)
@@ -205,7 +205,7 @@ char* sErr(int code)
/////////////////////////////////////////////////////////////////////
#ifndef MSG_NOSIGNAL
- #define MSG_NOSIGNAL 0
+#define MSG_NOSIGNAL 0
#endif
fd_set readfds;
@@ -230,7 +230,7 @@ static size_t socket_max_client_packet = 24576;
// The connection is closed if it goes over the limit.
#define WFIFO_MAX (1*1024*1024)
-struct socket_data* session[FD_SETSIZE];
+struct socket_data *session[FD_SETSIZE];
#ifdef SEND_SHORTLIST
int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that
@@ -241,387 +241,390 @@ uint32 send_shortlist_set[(FD_SETSIZE+31)/32];// to know if specific fd's are al
static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse);
#ifndef MINICORE
- int ip_rules = 1;
- static int connect_check(uint32 ip);
+int ip_rules = 1;
+static int connect_check(uint32 ip);
#endif
-const char* error_msg(void)
+const char *error_msg(void)
{
- static char buf[512];
- int code = sErrno;
- snprintf(buf, sizeof(buf), "error %d: %s", code, sErr(code));
- return buf;
+ static char buf[512];
+ int code = sErrno;
+ snprintf(buf, sizeof(buf), "error %d: %s", code, sErr(code));
+ return buf;
}
/*======================================
- * CORE : Default processing functions
+ * CORE : Default processing functions
*--------------------------------------*/
-int null_recv(int fd) { return 0; }
-int null_send(int fd) { return 0; }
-int null_parse(int fd) { return 0; }
+int null_recv(int fd)
+{
+ return 0;
+}
+int null_send(int fd)
+{
+ return 0;
+}
+int null_parse(int fd)
+{
+ return 0;
+}
ParseFunc default_func_parse = null_parse;
void set_defaultparse(ParseFunc defaultparse)
{
- default_func_parse = defaultparse;
+ default_func_parse = defaultparse;
}
/*======================================
- * CORE : Socket options
+ * CORE : Socket options
*--------------------------------------*/
void set_nonblocking(int fd, unsigned long yes)
{
- // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s.
- // The argp parameter is zero if nonblocking is to be disabled.
- if( sIoctl(fd, FIONBIO, &yes) != 0 )
- ShowError("set_nonblocking: Failed to set socket #%d to non-blocking mode (%s) - Please report this!!!\n", fd, error_msg());
+ // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s.
+ // The argp parameter is zero if nonblocking is to be disabled.
+ if (sIoctl(fd, FIONBIO, &yes) != 0)
+ ShowError("set_nonblocking: Failed to set socket #%d to non-blocking mode (%s) - Please report this!!!\n", fd, error_msg());
}
void setsocketopts(int fd)
{
- int yes = 1; // reuse fix
+ int yes = 1; // reuse fix
#if !defined(WIN32)
- // set SO_REAUSEADDR to true, unix only. on windows this option causes
- // the previous owner of the socket to give up, which is not desirable
- // in most cases, neither compatible with unix.
- sSetsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof(yes));
+ // set SO_REAUSEADDR to true, unix only. on windows this option causes
+ // the previous owner of the socket to give up, which is not desirable
+ // in most cases, neither compatible with unix.
+ sSetsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof(yes));
#ifdef SO_REUSEPORT
- sSetsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof(yes));
+ sSetsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof(yes));
#endif
#endif
- // Set the socket into no-delay mode; otherwise packets get delayed for up to 200ms, likely creating server-side lag.
- // The RO protocol is mainly single-packet request/response, plus the FIFO model already does packet grouping anyway.
- sSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes));
-
- // force the socket into no-wait, graceful-close mode (should be the default, but better make sure)
- //(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp)
- {
- struct linger opt;
- opt.l_onoff = 0; // SO_DONTLINGER
- opt.l_linger = 0; // Do not care
- if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&opt, sizeof(opt)) )
- ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
- }
+ // Set the socket into no-delay mode; otherwise packets get delayed for up to 200ms, likely creating server-side lag.
+ // The RO protocol is mainly single-packet request/response, plus the FIFO model already does packet grouping anyway.
+ sSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes));
+
+ // force the socket into no-wait, graceful-close mode (should be the default, but better make sure)
+ //(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp)
+ {
+ struct linger opt;
+ opt.l_onoff = 0; // SO_DONTLINGER
+ opt.l_linger = 0; // Do not care
+ if (sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&opt, sizeof(opt)))
+ ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
+ }
}
/*======================================
- * CORE : Socket Sub Function
+ * CORE : Socket Sub Function
*--------------------------------------*/
void set_eof(int fd)
{
- if( session_isActive(fd) )
- {
+ if (session_isActive(fd)) {
#ifdef SEND_SHORTLIST
- // Add this socket to the shortlist for eof handling.
- send_shortlist_add_fd(fd);
+ // Add this socket to the shortlist for eof handling.
+ send_shortlist_add_fd(fd);
#endif
- session[fd]->flag.eof = 1;
- }
+ session[fd]->flag.eof = 1;
+ }
}
int recv_to_fifo(int fd)
{
- int len;
-
- if( !session_isActive(fd) )
- return -1;
-
- len = sRecv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0);
-
- if( len == SOCKET_ERROR )
- {//An exception has occured
- if( sErrno != S_EWOULDBLOCK ) {
- //ShowDebug("recv_to_fifo: %s, closing connection #%d\n", error_msg(), fd);
- set_eof(fd);
- }
- return 0;
- }
-
- if( len == 0 )
- {//Normal connection end.
- set_eof(fd);
- return 0;
- }
-
- session[fd]->rdata_size += len;
- session[fd]->rdata_tick = last_tick;
- return 0;
+ int len;
+
+ if (!session_isActive(fd))
+ return -1;
+
+ len = sRecv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0);
+
+ if (len == SOCKET_ERROR) {
+ //An exception has occured
+ if (sErrno != S_EWOULDBLOCK) {
+ //ShowDebug("recv_to_fifo: %s, closing connection #%d\n", error_msg(), fd);
+ set_eof(fd);
+ }
+ return 0;
+ }
+
+ if (len == 0) {
+ //Normal connection end.
+ set_eof(fd);
+ return 0;
+ }
+
+ session[fd]->rdata_size += len;
+ session[fd]->rdata_tick = last_tick;
+ return 0;
}
int send_from_fifo(int fd)
{
- int len;
+ int len;
- if( !session_isValid(fd) )
- return -1;
+ if (!session_isValid(fd))
+ return -1;
- if( session[fd]->wdata_size == 0 )
- return 0; // nothing to send
+ if (session[fd]->wdata_size == 0)
+ return 0; // nothing to send
- len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, MSG_NOSIGNAL);
+ len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, MSG_NOSIGNAL);
- if( len == SOCKET_ERROR )
- {//An exception has occured
- if( sErrno != S_EWOULDBLOCK ) {
- //ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd);
- session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
- set_eof(fd);
- }
- return 0;
- }
+ if (len == SOCKET_ERROR) {
+ //An exception has occured
+ if (sErrno != S_EWOULDBLOCK) {
+ //ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd);
+ session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
+ set_eof(fd);
+ }
+ return 0;
+ }
- if( len > 0 )
- {
- // some data could not be transferred?
- // shift unsent data to the beginning of the queue
- if( (size_t)len < session[fd]->wdata_size )
- memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len);
+ if (len > 0) {
+ // some data could not be transferred?
+ // shift unsent data to the beginning of the queue
+ if ((size_t)len < session[fd]->wdata_size)
+ memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len);
- session[fd]->wdata_size -= len;
- }
+ session[fd]->wdata_size -= len;
+ }
- return 0;
+ return 0;
}
/// Best effort - there's no warranty that the data will be sent.
void flush_fifo(int fd)
{
- if(session[fd] != NULL)
- session[fd]->func_send(fd);
+ if (session[fd] != NULL)
+ session[fd]->func_send(fd);
}
void flush_fifos(void)
{
- int i;
- for(i = 1; i < fd_max; i++)
- flush_fifo(i);
+ int i;
+ for (i = 1; i < fd_max; i++)
+ flush_fifo(i);
}
/*======================================
- * CORE : Connection functions
+ * CORE : Connection functions
*--------------------------------------*/
int connect_client(int listen_fd)
{
- int fd;
- struct sockaddr_in client_address;
- socklen_t len;
-
- len = sizeof(client_address);
-
- fd = sAccept(listen_fd, (struct sockaddr*)&client_address, &len);
- if ( fd == -1 ) {
- ShowError("connect_client: accept failed (%s)!\n", error_msg());
- return -1;
- }
- if( fd == 0 )
- {// reserved
- ShowError("connect_client: Socket #0 is reserved - Please report this!!!\n");
- sClose(fd);
- return -1;
- }
- if( fd >= FD_SETSIZE )
- {// socket number too big
- ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
- sClose(fd);
- return -1;
- }
-
- setsocketopts(fd);
- set_nonblocking(fd, 1);
+ int fd;
+ struct sockaddr_in client_address;
+ socklen_t len;
+
+ len = sizeof(client_address);
+
+ fd = sAccept(listen_fd, (struct sockaddr *)&client_address, &len);
+ if (fd == -1) {
+ ShowError("connect_client: accept failed (%s)!\n", error_msg());
+ return -1;
+ }
+ if (fd == 0) {
+ // reserved
+ ShowError("connect_client: Socket #0 is reserved - Please report this!!!\n");
+ sClose(fd);
+ return -1;
+ }
+ if (fd >= FD_SETSIZE) {
+ // socket number too big
+ ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
+ sClose(fd);
+ return -1;
+ }
+
+ setsocketopts(fd);
+ set_nonblocking(fd, 1);
#ifndef MINICORE
- if( ip_rules && !connect_check(ntohl(client_address.sin_addr.s_addr)) ) {
- do_close(fd);
- return -1;
- }
+ if (ip_rules && !connect_check(ntohl(client_address.sin_addr.s_addr))) {
+ do_close(fd);
+ return -1;
+ }
#endif
- if( fd_max <= fd ) fd_max = fd + 1;
- sFD_SET(fd,&readfds);
+ if (fd_max <= fd) fd_max = fd + 1;
+ sFD_SET(fd,&readfds);
- create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
- session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr);
+ create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
+ session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr);
- return fd;
+ return fd;
}
int make_listen_bind(uint32 ip, uint16 port)
{
- struct sockaddr_in server_address;
- int fd;
- int result;
-
- fd = sSocket(AF_INET, SOCK_STREAM, 0);
-
- if( fd == -1 )
- {
- ShowError("make_listen_bind: socket creation failed (%s)!\n", error_msg());
- exit(EXIT_FAILURE);
- }
- if( fd == 0 )
- {// reserved
- ShowError("make_listen_bind: Socket #0 is reserved - Please report this!!!\n");
- sClose(fd);
- return -1;
- }
- if( fd >= FD_SETSIZE )
- {// socket number too big
- ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
- sClose(fd);
- return -1;
- }
-
- setsocketopts(fd);
- set_nonblocking(fd, 1);
-
- server_address.sin_family = AF_INET;
- server_address.sin_addr.s_addr = htonl(ip);
- server_address.sin_port = htons(port);
-
- result = sBind(fd, (struct sockaddr*)&server_address, sizeof(server_address));
- if( result == SOCKET_ERROR ) {
- ShowError("make_listen_bind: bind failed (socket #%d, %s)!\n", fd, error_msg());
- exit(EXIT_FAILURE);
- }
- result = sListen(fd,5);
- if( result == SOCKET_ERROR ) {
- ShowError("make_listen_bind: listen failed (socket #%d, %s)!\n", fd, error_msg());
- exit(EXIT_FAILURE);
- }
-
- if(fd_max <= fd) fd_max = fd + 1;
- sFD_SET(fd, &readfds);
-
- create_session(fd, connect_client, null_send, null_parse);
- session[fd]->client_addr = 0; // just listens
- session[fd]->rdata_tick = 0; // disable timeouts on this socket
-
- return fd;
+ struct sockaddr_in server_address;
+ int fd;
+ int result;
+
+ fd = sSocket(AF_INET, SOCK_STREAM, 0);
+
+ if (fd == -1) {
+ ShowError("make_listen_bind: socket creation failed (%s)!\n", error_msg());
+ exit(EXIT_FAILURE);
+ }
+ if (fd == 0) {
+ // reserved
+ ShowError("make_listen_bind: Socket #0 is reserved - Please report this!!!\n");
+ sClose(fd);
+ return -1;
+ }
+ if (fd >= FD_SETSIZE) {
+ // socket number too big
+ ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
+ sClose(fd);
+ return -1;
+ }
+
+ setsocketopts(fd);
+ set_nonblocking(fd, 1);
+
+ server_address.sin_family = AF_INET;
+ server_address.sin_addr.s_addr = htonl(ip);
+ server_address.sin_port = htons(port);
+
+ result = sBind(fd, (struct sockaddr *)&server_address, sizeof(server_address));
+ if (result == SOCKET_ERROR) {
+ ShowError("make_listen_bind: bind failed (socket #%d, %s)!\n", fd, error_msg());
+ exit(EXIT_FAILURE);
+ }
+ result = sListen(fd,5);
+ if (result == SOCKET_ERROR) {
+ ShowError("make_listen_bind: listen failed (socket #%d, %s)!\n", fd, error_msg());
+ exit(EXIT_FAILURE);
+ }
+
+ if (fd_max <= fd) fd_max = fd + 1;
+ sFD_SET(fd, &readfds);
+
+ create_session(fd, connect_client, null_send, null_parse);
+ session[fd]->client_addr = 0; // just listens
+ session[fd]->rdata_tick = 0; // disable timeouts on this socket
+
+ return fd;
}
-int make_connection(uint32 ip, uint16 port, bool silent) {
- struct sockaddr_in remote_address;
- int fd;
- int result;
-
- fd = sSocket(AF_INET, SOCK_STREAM, 0);
-
- if (fd == -1) {
- ShowError("make_connection: socket creation failed (%s)!\n", error_msg());
- return -1;
- }
- if( fd == 0 )
- {// reserved
- ShowError("make_connection: Socket #0 is reserved - Please report this!!!\n");
- sClose(fd);
- return -1;
- }
- if( fd >= FD_SETSIZE )
- {// socket number too big
- ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
- sClose(fd);
- return -1;
- }
-
- setsocketopts(fd);
-
- remote_address.sin_family = AF_INET;
- remote_address.sin_addr.s_addr = htonl(ip);
- remote_address.sin_port = htons(port);
-
- if( !silent )
- ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
-
- result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
- if( result == SOCKET_ERROR ) {
- if( !silent )
- ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
- do_close(fd);
- return -1;
- }
- //Now the socket can be made non-blocking. [Skotlex]
- set_nonblocking(fd, 1);
-
- if (fd_max <= fd) fd_max = fd + 1;
- sFD_SET(fd,&readfds);
-
- create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
- session[fd]->client_addr = ntohl(remote_address.sin_addr.s_addr);
-
- return fd;
+int make_connection(uint32 ip, uint16 port, bool silent)
+{
+ struct sockaddr_in remote_address;
+ int fd;
+ int result;
+
+ fd = sSocket(AF_INET, SOCK_STREAM, 0);
+
+ if (fd == -1) {
+ ShowError("make_connection: socket creation failed (%s)!\n", error_msg());
+ return -1;
+ }
+ if (fd == 0) {
+ // reserved
+ ShowError("make_connection: Socket #0 is reserved - Please report this!!!\n");
+ sClose(fd);
+ return -1;
+ }
+ if (fd >= FD_SETSIZE) {
+ // socket number too big
+ ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
+ sClose(fd);
+ return -1;
+ }
+
+ setsocketopts(fd);
+
+ remote_address.sin_family = AF_INET;
+ remote_address.sin_addr.s_addr = htonl(ip);
+ remote_address.sin_port = htons(port);
+
+ if (!silent)
+ ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
+
+ result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
+ if (result == SOCKET_ERROR) {
+ if (!silent)
+ ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
+ do_close(fd);
+ return -1;
+ }
+ //Now the socket can be made non-blocking. [Skotlex]
+ set_nonblocking(fd, 1);
+
+ if (fd_max <= fd) fd_max = fd + 1;
+ sFD_SET(fd,&readfds);
+
+ create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
+ session[fd]->client_addr = ntohl(remote_address.sin_addr.s_addr);
+
+ return fd;
}
static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse)
{
- CREATE(session[fd], struct socket_data, 1);
- CREATE(session[fd]->rdata, unsigned char, RFIFO_SIZE);
- CREATE(session[fd]->wdata, unsigned char, WFIFO_SIZE);
- session[fd]->max_rdata = RFIFO_SIZE;
- session[fd]->max_wdata = WFIFO_SIZE;
- session[fd]->func_recv = func_recv;
- session[fd]->func_send = func_send;
- session[fd]->func_parse = func_parse;
- session[fd]->rdata_tick = last_tick;
- return 0;
+ CREATE(session[fd], struct socket_data, 1);
+ CREATE(session[fd]->rdata, unsigned char, RFIFO_SIZE);
+ CREATE(session[fd]->wdata, unsigned char, WFIFO_SIZE);
+ session[fd]->max_rdata = RFIFO_SIZE;
+ session[fd]->max_wdata = WFIFO_SIZE;
+ session[fd]->func_recv = func_recv;
+ session[fd]->func_send = func_send;
+ session[fd]->func_parse = func_parse;
+ session[fd]->rdata_tick = last_tick;
+ return 0;
}
static void delete_session(int fd)
{
- if( session_isValid(fd) )
- {
- aFree(session[fd]->rdata);
- aFree(session[fd]->wdata);
- aFree(session[fd]->session_data);
- aFree(session[fd]);
- session[fd] = NULL;
- }
+ if (session_isValid(fd)) {
+ aFree(session[fd]->rdata);
+ aFree(session[fd]->wdata);
+ aFree(session[fd]->session_data);
+ aFree(session[fd]);
+ session[fd] = NULL;
+ }
}
int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size)
{
- if( !session_isValid(fd) )
- return 0;
-
- if( session[fd]->max_rdata != rfifo_size && session[fd]->rdata_size < rfifo_size) {
- RECREATE(session[fd]->rdata, unsigned char, rfifo_size);
- session[fd]->max_rdata = rfifo_size;
- }
-
- if( session[fd]->max_wdata != wfifo_size && session[fd]->wdata_size < wfifo_size) {
- RECREATE(session[fd]->wdata, unsigned char, wfifo_size);
- session[fd]->max_wdata = wfifo_size;
- }
- return 0;
+ if (!session_isValid(fd))
+ return 0;
+
+ if (session[fd]->max_rdata != rfifo_size && session[fd]->rdata_size < rfifo_size) {
+ RECREATE(session[fd]->rdata, unsigned char, rfifo_size);
+ session[fd]->max_rdata = rfifo_size;
+ }
+
+ if (session[fd]->max_wdata != wfifo_size && session[fd]->wdata_size < wfifo_size) {
+ RECREATE(session[fd]->wdata, unsigned char, wfifo_size);
+ session[fd]->max_wdata = wfifo_size;
+ }
+ return 0;
}
int realloc_writefifo(int fd, size_t addition)
{
- size_t newsize;
-
- if( !session_isValid(fd) ) // might not happen
- return 0;
-
- if( session[fd]->wdata_size + addition > session[fd]->max_wdata )
- { // grow rule; grow in multiples of WFIFO_SIZE
- newsize = WFIFO_SIZE;
- while( session[fd]->wdata_size + addition > newsize ) newsize += WFIFO_SIZE;
- }
- else
- if( session[fd]->max_wdata >= (size_t)2*(session[fd]->flag.server?FIFOSIZE_SERVERLINK:WFIFO_SIZE)
- && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
- { // shrink rule, shrink by 2 when only a quarter of the fifo is used, don't shrink below nominal size.
- newsize = session[fd]->max_wdata / 2;
- }
- else // no change
- return 0;
-
- RECREATE(session[fd]->wdata, unsigned char, newsize);
- session[fd]->max_wdata = newsize;
-
- return 0;
+ size_t newsize;
+
+ if (!session_isValid(fd)) // might not happen
+ return 0;
+
+ if (session[fd]->wdata_size + addition > session[fd]->max_wdata) {
+ // grow rule; grow in multiples of WFIFO_SIZE
+ newsize = WFIFO_SIZE;
+ while (session[fd]->wdata_size + addition > newsize) newsize += WFIFO_SIZE;
+ } else if (session[fd]->max_wdata >= (size_t)2*(session[fd]->flag.server?FIFOSIZE_SERVERLINK:WFIFO_SIZE)
+ && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata) {
+ // shrink rule, shrink by 2 when only a quarter of the fifo is used, don't shrink below nominal size.
+ newsize = session[fd]->max_wdata / 2;
+ } else // no change
+ return 0;
+
+ RECREATE(session[fd]->wdata, unsigned char, newsize);
+ session[fd]->max_wdata = newsize;
+
+ return 0;
}
/// advance the RFIFO cursor (marking 'len' bytes as processed)
@@ -629,197 +632,186 @@ int RFIFOSKIP(int fd, size_t len)
{
struct socket_data *s;
- if ( !session_isActive(fd) )
- return 0;
+ if (!session_isActive(fd))
+ return 0;
- s = session[fd];
+ s = session[fd];
- if ( s->rdata_size < s->rdata_pos + len ) {
- ShowError("RFIFOSKIP: skipped past end of read buffer! Adjusting from %d to %d (session #%d)\n", len, RFIFOREST(fd), fd);
- len = RFIFOREST(fd);
- }
+ if (s->rdata_size < s->rdata_pos + len) {
+ ShowError("RFIFOSKIP: skipped past end of read buffer! Adjusting from %d to %d (session #%d)\n", len, RFIFOREST(fd), fd);
+ len = RFIFOREST(fd);
+ }
- s->rdata_pos = s->rdata_pos + len;
- return 0;
+ s->rdata_pos = s->rdata_pos + len;
+ return 0;
}
/// advance the WFIFO cursor (marking 'len' bytes for sending)
int WFIFOSET(int fd, size_t len)
{
- size_t newreserve;
- struct socket_data* s = session[fd];
-
- if( !session_isValid(fd) || s->wdata == NULL )
- return 0;
-
- // we have written len bytes to the buffer already before calling WFIFOSET
- if(s->wdata_size+len > s->max_wdata)
- { // actually there was a buffer overflow already
- uint32 ip = s->client_addr;
- ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %u bytes on a %u/%u bytes buffer.\n", fd, CONVIP(ip), (unsigned int)len, (unsigned int)s->wdata_size, (unsigned int)s->max_wdata);
- ShowDebug("Likely command that caused it: 0x%x\n", (*(uint16*)(s->wdata + s->wdata_size)));
- // no other chance, make a better fifo model
- exit(EXIT_FAILURE);
- }
-
- if( len > 0xFFFF )
- {
- // dynamic packets allow up to UINT16_MAX bytes (<packet_id>.W <packet_len>.W ...)
- // all known fixed-size packets are within this limit, so use the same limit
- ShowFatalError("WFIFOSET: Packet 0x%x is too big. (len=%u, max=%u)\n", (*(uint16*)(s->wdata + s->wdata_size)), (unsigned int)len, 0xFFFF);
- exit(EXIT_FAILURE);
- }
- else if( len == 0 )
- {
- // abuses the fact, that the code that did WFIFOHEAD(fd,0), already wrote
- // the packet type into memory, even if it could have overwritten vital data
- // this can happen when a new packet was added on map-server, but packet len table was not updated
- ShowWarning("WFIFOSET: Attempted to send zero-length packet, most likely 0x%04x (please report this).\n", WFIFOW(fd,0));
- return 0;
- }
-
- if( !s->flag.server ) {
-
- if( len > socket_max_client_packet ) {// see declaration of socket_max_client_packet for details
- ShowError("WFIFOSET: Dropped too large client packet 0x%04x (length=%u, max=%u).\n", WFIFOW(fd,0), len, socket_max_client_packet);
- return 0;
- }
-
- if( s->wdata_size+len > WFIFO_MAX ) {// reached maximum write fifo size
- ShowError("WFIFOSET: Maximum write buffer size for client connection %d exceeded, most likely caused by packet 0x%04x (len=%u, ip=%lu.%lu.%lu.%lu).\n", fd, WFIFOW(fd,0), len, CONVIP(s->client_addr));
- set_eof(fd);
- return 0;
- }
-
- }
- s->wdata_size += len;
- //If the interserver has 200% of its normal size full, flush the data.
- if( s->flag.server && s->wdata_size >= 2*FIFOSIZE_SERVERLINK )
- flush_fifo(fd);
-
- // always keep a WFIFO_SIZE reserve in the buffer
- // For inter-server connections, let the reserve be 1/4th of the link size.
- newreserve = s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE;
-
- // readjust the buffer to include the chosen reserve
- realloc_writefifo(fd, newreserve);
+ size_t newreserve;
+ struct socket_data *s = session[fd];
+
+ if (!session_isValid(fd) || s->wdata == NULL)
+ return 0;
+
+ // we have written len bytes to the buffer already before calling WFIFOSET
+ if (s->wdata_size+len > s->max_wdata) {
+ // actually there was a buffer overflow already
+ uint32 ip = s->client_addr;
+ ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %u bytes on a %u/%u bytes buffer.\n", fd, CONVIP(ip), (unsigned int)len, (unsigned int)s->wdata_size, (unsigned int)s->max_wdata);
+ ShowDebug("Likely command that caused it: 0x%x\n", (*(uint16 *)(s->wdata + s->wdata_size)));
+ // no other chance, make a better fifo model
+ exit(EXIT_FAILURE);
+ }
+
+ if (len > 0xFFFF) {
+ // dynamic packets allow up to UINT16_MAX bytes (<packet_id>.W <packet_len>.W ...)
+ // all known fixed-size packets are within this limit, so use the same limit
+ ShowFatalError("WFIFOSET: Packet 0x%x is too big. (len=%u, max=%u)\n", (*(uint16 *)(s->wdata + s->wdata_size)), (unsigned int)len, 0xFFFF);
+ exit(EXIT_FAILURE);
+ } else if (len == 0) {
+ // abuses the fact, that the code that did WFIFOHEAD(fd,0), already wrote
+ // the packet type into memory, even if it could have overwritten vital data
+ // this can happen when a new packet was added on map-server, but packet len table was not updated
+ ShowWarning("WFIFOSET: Attempted to send zero-length packet, most likely 0x%04x (please report this).\n", WFIFOW(fd,0));
+ return 0;
+ }
+
+ if (!s->flag.server) {
+
+ if (len > socket_max_client_packet) { // see declaration of socket_max_client_packet for details
+ ShowError("WFIFOSET: Dropped too large client packet 0x%04x (length=%u, max=%u).\n", WFIFOW(fd,0), len, socket_max_client_packet);
+ return 0;
+ }
+
+ if (s->wdata_size+len > WFIFO_MAX) { // reached maximum write fifo size
+ ShowError("WFIFOSET: Maximum write buffer size for client connection %d exceeded, most likely caused by packet 0x%04x (len=%u, ip=%lu.%lu.%lu.%lu).\n", fd, WFIFOW(fd,0), len, CONVIP(s->client_addr));
+ set_eof(fd);
+ return 0;
+ }
+
+ }
+ s->wdata_size += len;
+ //If the interserver has 200% of its normal size full, flush the data.
+ if (s->flag.server && s->wdata_size >= 2*FIFOSIZE_SERVERLINK)
+ flush_fifo(fd);
+
+ // always keep a WFIFO_SIZE reserve in the buffer
+ // For inter-server connections, let the reserve be 1/4th of the link size.
+ newreserve = s->flag.server ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE;
+
+ // readjust the buffer to include the chosen reserve
+ realloc_writefifo(fd, newreserve);
#ifdef SEND_SHORTLIST
- send_shortlist_add_fd(fd);
+ send_shortlist_add_fd(fd);
#endif
- return 0;
+ return 0;
}
int do_sockets(int next)
{
- fd_set rfd;
- struct timeval timeout;
- int ret,i;
+ fd_set rfd;
+ struct timeval timeout;
+ int ret,i;
- // PRESEND Timers are executed before do_sendrecv and can send packets and/or set sessions to eof.
- // Send remaining data and process client-side disconnects here.
+ // PRESEND Timers are executed before do_sendrecv and can send packets and/or set sessions to eof.
+ // Send remaining data and process client-side disconnects here.
#ifdef SEND_SHORTLIST
- send_shortlist_do_sends();
+ send_shortlist_do_sends();
#else
- for (i = 1; i < fd_max; i++)
- {
- if(!session[i])
- continue;
-
- if(session[i]->wdata_size)
- session[i]->func_send(i);
- }
+ for (i = 1; i < fd_max; i++) {
+ if (!session[i])
+ continue;
+
+ if (session[i]->wdata_size)
+ session[i]->func_send(i);
+ }
#endif
- // can timeout until the next tick
- timeout.tv_sec = next/1000;
- timeout.tv_usec = next%1000*1000;
+ // can timeout until the next tick
+ timeout.tv_sec = next/1000;
+ timeout.tv_usec = next%1000*1000;
- memcpy(&rfd, &readfds, sizeof(rfd));
- ret = sSelect(fd_max, &rfd, NULL, NULL, &timeout);
+ memcpy(&rfd, &readfds, sizeof(rfd));
+ ret = sSelect(fd_max, &rfd, NULL, NULL, &timeout);
- if( ret == SOCKET_ERROR )
- {
- if( sErrno != S_EINTR )
- {
- ShowFatalError("do_sockets: select() failed, %s!\n", error_msg());
- exit(EXIT_FAILURE);
- }
- return 0; // interrupted by a signal, just loop and try again
- }
+ if (ret == SOCKET_ERROR) {
+ if (sErrno != S_EINTR) {
+ ShowFatalError("do_sockets: select() failed, %s!\n", error_msg());
+ exit(EXIT_FAILURE);
+ }
+ return 0; // interrupted by a signal, just loop and try again
+ }
- last_tick = time(NULL);
+ last_tick = time(NULL);
#if defined(WIN32)
- // on windows, enumerating all members of the fd_set is way faster if we access the internals
- for( i = 0; i < (int)rfd.fd_count; ++i )
- {
- int fd = sock2fd(rfd.fd_array[i]);
- if( session[fd] )
- session[fd]->func_recv(fd);
- }
+ // on windows, enumerating all members of the fd_set is way faster if we access the internals
+ for (i = 0; i < (int)rfd.fd_count; ++i) {
+ int fd = sock2fd(rfd.fd_array[i]);
+ if (session[fd])
+ session[fd]->func_recv(fd);
+ }
#else
- // otherwise assume that the fd_set is a bit-array and enumerate it in a standard way
- for( i = 1; ret && i < fd_max; ++i )
- {
- if(sFD_ISSET(i,&rfd) && session[i])
- {
- session[i]->func_recv(i);
- --ret;
- }
- }
+ // otherwise assume that the fd_set is a bit-array and enumerate it in a standard way
+ for (i = 1; ret && i < fd_max; ++i) {
+ if (sFD_ISSET(i,&rfd) && session[i]) {
+ session[i]->func_recv(i);
+ --ret;
+ }
+ }
#endif
- // POSTSEND Send remaining data and handle eof sessions.
+ // POSTSEND Send remaining data and handle eof sessions.
#ifdef SEND_SHORTLIST
- send_shortlist_do_sends();
+ send_shortlist_do_sends();
#else
- for (i = 1; i < fd_max; i++)
- {
- if(!session[i])
- continue;
-
- if(session[i]->wdata_size)
- session[i]->func_send(i);
-
- if(session[i]->flag.eof) //func_send can't free a session, this is safe.
- { //Finally, even if there is no data to parse, connections signalled eof should be closed, so we call parse_func [Skotlex]
- session[i]->func_parse(i); //This should close the session immediately.
- }
- }
+ for (i = 1; i < fd_max; i++) {
+ if (!session[i])
+ continue;
+
+ if (session[i]->wdata_size)
+ session[i]->func_send(i);
+
+ if (session[i]->flag.eof) { //func_send can't free a session, this is safe.
+ //Finally, even if there is no data to parse, connections signalled eof should be closed, so we call parse_func [Skotlex]
+ session[i]->func_parse(i); //This should close the session immediately.
+ }
+ }
#endif
- // parse input data on each socket
- for(i = 1; i < fd_max; i++)
- {
- if(!session[i])
- continue;
-
- if (session[i]->rdata_tick && DIFF_TICK(last_tick, session[i]->rdata_tick) > stall_time) {
- if( session[i]->flag.server ) {/* server is special */
- if( session[i]->flag.ping != 2 )/* only update if necessary otherwise it'd resend the ping unnecessarily */
- session[i]->flag.ping = 1;
- } else {
- ShowInfo("Session #%d timed out\n", i);
- set_eof(i);
- }
- }
-
- session[i]->func_parse(i);
-
- if(!session[i])
- continue;
-
- // after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed)
- if (session[i]->rdata_size == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) {
- set_eof(i);
- continue;
- }
- RFIFOFLUSH(i);
- }
-
- return 0;
+ // parse input data on each socket
+ for (i = 1; i < fd_max; i++) {
+ if (!session[i])
+ continue;
+
+ if (session[i]->rdata_tick && DIFF_TICK(last_tick, session[i]->rdata_tick) > stall_time) {
+ if (session[i]->flag.server) { /* server is special */
+ if (session[i]->flag.ping != 2) /* only update if necessary otherwise it'd resend the ping unnecessarily */
+ session[i]->flag.ping = 1;
+ } else {
+ ShowInfo("Session #%d timed out\n", i);
+ set_eof(i);
+ }
+ }
+
+ session[i]->func_parse(i);
+
+ if (!session[i])
+ continue;
+
+ // after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed)
+ if (session[i]->rdata_size == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) {
+ set_eof(i);
+ continue;
+ }
+ RFIFOFLUSH(i);
+ }
+
+ return 0;
}
//////////////////////////////
@@ -828,26 +820,26 @@ int do_sockets(int next)
// IP rules and DDoS protection
typedef struct _connect_history {
- struct _connect_history* next;
- uint32 ip;
- uint32 tick;
- int count;
- unsigned ddos : 1;
+ struct _connect_history *next;
+ uint32 ip;
+ uint32 tick;
+ int count;
+ unsigned ddos : 1;
} ConnectHistory;
typedef struct _access_control {
- uint32 ip;
- uint32 mask;
+ uint32 ip;
+ uint32 mask;
} AccessControl;
enum _aco {
- ACO_DENY_ALLOW,
- ACO_ALLOW_DENY,
- ACO_MUTUAL_FAILURE
+ ACO_DENY_ALLOW,
+ ACO_ALLOW_DENY,
+ ACO_MUTUAL_FAILURE
};
-static AccessControl* access_allow = NULL;
-static AccessControl* access_deny = NULL;
+static AccessControl *access_allow = NULL;
+static AccessControl *access_deny = NULL;
static int access_order = ACO_DENY_ALLOW;
static int access_allownum = 0;
static int access_denynum = 0;
@@ -857,7 +849,7 @@ static int ddos_interval = 3*1000;
static int ddos_autoreset = 10*60*1000;
/// Connection history, an array of linked lists.
/// The array's index for any ip is ip&0xFFFF
-static ConnectHistory* connect_history[0x10000];
+static ConnectHistory *connect_history[0x10000];
static int connect_check_(uint32 ip);
@@ -865,11 +857,11 @@ static int connect_check_(uint32 ip);
/// @see connect_check_()
static int connect_check(uint32 ip)
{
- int result = connect_check_(ip);
- if( access_debug ) {
- ShowInfo("connect_check: Connection from %d.%d.%d.%d %s\n", CONVIP(ip),result ? "allowed." : "denied!");
- }
- return result;
+ int result = connect_check_(ip);
+ if (access_debug) {
+ ShowInfo("connect_check: Connection from %d.%d.%d.%d %s\n", CONVIP(ip),result ? "allowed." : "denied!");
+ }
+ return result;
}
/// Verifies if the IP can connect.
@@ -877,504 +869,494 @@ static int connect_check(uint32 ip)
/// 1 or 2 : Connection Accepted
static int connect_check_(uint32 ip)
{
- ConnectHistory* hist = connect_history[ip&0xFFFF];
- int i;
- int is_allowip = 0;
- int is_denyip = 0;
- int connect_ok = 0;
-
- // Search the allow list
- for( i=0; i < access_allownum; ++i ){
- if( (ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask) ){
- if( access_debug ){
- ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
- CONVIP(ip),
- CONVIP(access_allow[i].ip),
- CONVIP(access_allow[i].mask));
- }
- is_allowip = 1;
- break;
- }
- }
- // Search the deny list
- for( i=0; i < access_denynum; ++i ){
- if( (ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask) ){
- if( access_debug ){
- ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
- CONVIP(ip),
- CONVIP(access_deny[i].ip),
- CONVIP(access_deny[i].mask));
- }
- is_denyip = 1;
- break;
- }
- }
- // Decide connection status
- // 0 : Reject
- // 1 : Accept
- // 2 : Unconditional Accept (accepts even if flagged as DDoS)
- switch(access_order) {
- case ACO_DENY_ALLOW:
- default:
- if( is_denyip )
- connect_ok = 0; // Reject
- else if( is_allowip )
- connect_ok = 2; // Unconditional Accept
- else
- connect_ok = 1; // Accept
- break;
- case ACO_ALLOW_DENY:
- if( is_allowip )
- connect_ok = 2; // Unconditional Accept
- else if( is_denyip )
- connect_ok = 0; // Reject
- else
- connect_ok = 1; // Accept
- break;
- case ACO_MUTUAL_FAILURE:
- if( is_allowip && !is_denyip )
- connect_ok = 2; // Unconditional Accept
- else
- connect_ok = 0; // Reject
- break;
- }
-
- // Inspect connection history
- while( hist ) {
- if( ip == hist->ip )
- {// IP found
- if( hist->ddos )
- {// flagged as DDoS
- return (connect_ok == 2 ? 1 : 0);
- } else if( DIFF_TICK(gettick(),hist->tick) < ddos_interval )
- {// connection within ddos_interval
- hist->tick = gettick();
- if( hist->count++ >= ddos_count )
- {// DDoS attack detected
- hist->ddos = 1;
- ShowWarning("connect_check: DDoS Attack detected from %d.%d.%d.%d!\n", CONVIP(ip));
- return (connect_ok == 2 ? 1 : 0);
- }
- return connect_ok;
- } else
- {// not within ddos_interval, clear data
- hist->tick = gettick();
- hist->count = 0;
- return connect_ok;
- }
- }
- hist = hist->next;
- }
- // IP not found, add to history
- CREATE(hist, ConnectHistory, 1);
- memset(hist, 0, sizeof(ConnectHistory));
- hist->ip = ip;
- hist->tick = gettick();
- hist->next = connect_history[ip&0xFFFF];
- connect_history[ip&0xFFFF] = hist;
- return connect_ok;
+ ConnectHistory *hist = connect_history[ip&0xFFFF];
+ int i;
+ int is_allowip = 0;
+ int is_denyip = 0;
+ int connect_ok = 0;
+
+ // Search the allow list
+ for (i=0; i < access_allownum; ++i) {
+ if ((ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask)) {
+ if (access_debug) {
+ ShowInfo("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
+ CONVIP(ip),
+ CONVIP(access_allow[i].ip),
+ CONVIP(access_allow[i].mask));
+ }
+ is_allowip = 1;
+ break;
+ }
+ }
+ // Search the deny list
+ for (i=0; i < access_denynum; ++i) {
+ if ((ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask)) {
+ if (access_debug) {
+ ShowInfo("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n",
+ CONVIP(ip),
+ CONVIP(access_deny[i].ip),
+ CONVIP(access_deny[i].mask));
+ }
+ is_denyip = 1;
+ break;
+ }
+ }
+ // Decide connection status
+ // 0 : Reject
+ // 1 : Accept
+ // 2 : Unconditional Accept (accepts even if flagged as DDoS)
+ switch (access_order) {
+ case ACO_DENY_ALLOW:
+ default:
+ if (is_denyip)
+ connect_ok = 0; // Reject
+ else if (is_allowip)
+ connect_ok = 2; // Unconditional Accept
+ else
+ connect_ok = 1; // Accept
+ break;
+ case ACO_ALLOW_DENY:
+ if (is_allowip)
+ connect_ok = 2; // Unconditional Accept
+ else if (is_denyip)
+ connect_ok = 0; // Reject
+ else
+ connect_ok = 1; // Accept
+ break;
+ case ACO_MUTUAL_FAILURE:
+ if (is_allowip && !is_denyip)
+ connect_ok = 2; // Unconditional Accept
+ else
+ connect_ok = 0; // Reject
+ break;
+ }
+
+ // Inspect connection history
+ while (hist) {
+ if (ip == hist->ip) {
+ // IP found
+ if (hist->ddos) {
+ // flagged as DDoS
+ return (connect_ok == 2 ? 1 : 0);
+ } else if (DIFF_TICK(gettick(),hist->tick) < ddos_interval) {
+ // connection within ddos_interval
+ hist->tick = gettick();
+ if (hist->count++ >= ddos_count) {
+ // DDoS attack detected
+ hist->ddos = 1;
+ ShowWarning("connect_check: DDoS Attack detected from %d.%d.%d.%d!\n", CONVIP(ip));
+ return (connect_ok == 2 ? 1 : 0);
+ }
+ return connect_ok;
+ } else {
+ // not within ddos_interval, clear data
+ hist->tick = gettick();
+ hist->count = 0;
+ return connect_ok;
+ }
+ }
+ hist = hist->next;
+ }
+ // IP not found, add to history
+ CREATE(hist, ConnectHistory, 1);
+ memset(hist, 0, sizeof(ConnectHistory));
+ hist->ip = ip;
+ hist->tick = gettick();
+ hist->next = connect_history[ip&0xFFFF];
+ connect_history[ip&0xFFFF] = hist;
+ return connect_ok;
}
/// Timer function.
/// Deletes old connection history records.
static int connect_check_clear(int tid, unsigned int tick, int id, intptr_t data)
{
- int i;
- int clear = 0;
- int list = 0;
- ConnectHistory root;
- ConnectHistory* prev_hist;
- ConnectHistory* hist;
-
- for( i=0; i < 0x10000 ; ++i ){
- prev_hist = &root;
- root.next = hist = connect_history[i];
- while( hist ){
- if( (!hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_interval*3) ||
- (hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_autoreset) )
- {// Remove connection history
- prev_hist->next = hist->next;
- aFree(hist);
- hist = prev_hist->next;
- clear++;
- } else {
- prev_hist = hist;
- hist = hist->next;
- }
- list++;
- }
- connect_history[i] = root.next;
- }
- if( access_debug ){
- ShowInfo("connect_check_clear: Cleared %d of %d from IP list.\n", clear, list);
- }
- return list;
+ int i;
+ int clear = 0;
+ int list = 0;
+ ConnectHistory root;
+ ConnectHistory *prev_hist;
+ ConnectHistory *hist;
+
+ for (i=0; i < 0x10000 ; ++i) {
+ prev_hist = &root;
+ root.next = hist = connect_history[i];
+ while (hist) {
+ if ((!hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_interval*3) ||
+ (hist->ddos && DIFF_TICK(tick,hist->tick) > ddos_autoreset)) {
+ // Remove connection history
+ prev_hist->next = hist->next;
+ aFree(hist);
+ hist = prev_hist->next;
+ clear++;
+ } else {
+ prev_hist = hist;
+ hist = hist->next;
+ }
+ list++;
+ }
+ connect_history[i] = root.next;
+ }
+ if (access_debug) {
+ ShowInfo("connect_check_clear: Cleared %d of %d from IP list.\n", clear, list);
+ }
+ return list;
}
/// Parses the ip address and mask and puts it into acc.
/// Returns 1 is successful, 0 otherwise.
-int access_ipmask(const char* str, AccessControl* acc)
+int access_ipmask(const char *str, AccessControl *acc)
{
- uint32 ip;
- uint32 mask;
- unsigned int a[4];
- unsigned int m[4];
- int n;
-
- if( strcmp(str,"all") == 0 ) {
- ip = 0;
- mask = 0;
- } else {
- if( ((n=sscanf(str,"%u.%u.%u.%u/%u.%u.%u.%u",a,a+1,a+2,a+3,m,m+1,m+2,m+3)) != 8 && // not an ip + standard mask
- (n=sscanf(str,"%u.%u.%u.%u/%u",a,a+1,a+2,a+3,m)) != 5 && // not an ip + bit mask
- (n=sscanf(str,"%u.%u.%u.%u",a,a+1,a+2,a+3)) != 4 ) || // not an ip
- a[0] > 255 || a[1] > 255 || a[2] > 255 || a[3] > 255 || // invalid ip
- (n == 8 && (m[0] > 255 || m[1] > 255 || m[2] > 255 || m[3] > 255)) || // invalid standard mask
- (n == 5 && m[0] > 32) ){ // invalid bit mask
- return 0;
- }
- ip = MAKEIP(a[0],a[1],a[2],a[3]);
- if( n == 8 )
- {// standard mask
- mask = MAKEIP(m[0],m[1],m[2],m[3]);
- } else if( n == 5 )
- {// bit mask
- mask = 0;
- while( m[0] ){
- mask = (mask >> 1) | 0x80000000;
- --m[0];
- }
- } else
- {// just this ip
- mask = 0xFFFFFFFF;
- }
- }
- if( access_debug ){
- ShowInfo("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n", CONVIP(ip), CONVIP(mask));
- }
- acc->ip = ip;
- acc->mask = mask;
- return 1;
+ uint32 ip;
+ uint32 mask;
+ unsigned int a[4];
+ unsigned int m[4];
+ int n;
+
+ if (strcmp(str,"all") == 0) {
+ ip = 0;
+ mask = 0;
+ } else {
+ if (((n=sscanf(str,"%u.%u.%u.%u/%u.%u.%u.%u",a,a+1,a+2,a+3,m,m+1,m+2,m+3)) != 8 && // not an ip + standard mask
+ (n=sscanf(str,"%u.%u.%u.%u/%u",a,a+1,a+2,a+3,m)) != 5 && // not an ip + bit mask
+ (n=sscanf(str,"%u.%u.%u.%u",a,a+1,a+2,a+3)) != 4) || // not an ip
+ a[0] > 255 || a[1] > 255 || a[2] > 255 || a[3] > 255 || // invalid ip
+ (n == 8 && (m[0] > 255 || m[1] > 255 || m[2] > 255 || m[3] > 255)) || // invalid standard mask
+ (n == 5 && m[0] > 32)) { // invalid bit mask
+ return 0;
+ }
+ ip = MAKEIP(a[0],a[1],a[2],a[3]);
+ if (n == 8) {
+ // standard mask
+ mask = MAKEIP(m[0],m[1],m[2],m[3]);
+ } else if (n == 5) {
+ // bit mask
+ mask = 0;
+ while (m[0]) {
+ mask = (mask >> 1) | 0x80000000;
+ --m[0];
+ }
+ } else {
+ // just this ip
+ mask = 0xFFFFFFFF;
+ }
+ }
+ if (access_debug) {
+ ShowInfo("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n", CONVIP(ip), CONVIP(mask));
+ }
+ acc->ip = ip;
+ acc->mask = mask;
+ return 1;
}
//////////////////////////////
#endif
//////////////////////////////
-int socket_config_read(const char* cfgName)
+int socket_config_read(const char *cfgName)
{
- char line[1024],w1[1024],w2[1024];
- FILE *fp;
-
- fp = fopen(cfgName, "r");
- if(fp == NULL) {
- ShowError("File not found: %s\n", cfgName);
- return 1;
- }
-
- while(fgets(line, sizeof(line), fp))
- {
- if(line[0] == '/' && line[1] == '/')
- continue;
- if(sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
- continue;
-
- if (!strcmpi(w1, "stall_time")) {
- stall_time = atoi(w2);
- if( stall_time < 3 )
- stall_time = 3;/* a minimum is required to refrain it from killing itself */
- }
+ char line[1024],w1[1024],w2[1024];
+ FILE *fp;
+
+ fp = fopen(cfgName, "r");
+ if (fp == NULL) {
+ ShowError("File not found: %s\n", cfgName);
+ return 1;
+ }
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '/' && line[1] == '/')
+ continue;
+ if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+ continue;
+
+ if (!strcmpi(w1, "stall_time")) {
+ stall_time = atoi(w2);
+ if (stall_time < 3)
+ stall_time = 3;/* a minimum is required to refrain it from killing itself */
+ }
#ifndef MINICORE
- else if (!strcmpi(w1, "enable_ip_rules")) {
- ip_rules = config_switch(w2);
- } else if (!strcmpi(w1, "order")) {
- if (!strcmpi(w2, "deny,allow"))
- access_order = ACO_DENY_ALLOW;
- else if (!strcmpi(w2, "allow,deny"))
- access_order = ACO_ALLOW_DENY;
- else if (!strcmpi(w2, "mutual-failure"))
- access_order = ACO_MUTUAL_FAILURE;
- } else if (!strcmpi(w1, "allow")) {
- RECREATE(access_allow, AccessControl, access_allownum+1);
- if (access_ipmask(w2, &access_allow[access_allownum]))
- ++access_allownum;
- else
- ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
- } else if (!strcmpi(w1, "deny")) {
- RECREATE(access_deny, AccessControl, access_denynum+1);
- if (access_ipmask(w2, &access_deny[access_denynum]))
- ++access_denynum;
- else
- ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
- }
- else if (!strcmpi(w1,"ddos_interval"))
- ddos_interval = atoi(w2);
- else if (!strcmpi(w1,"ddos_count"))
- ddos_count = atoi(w2);
- else if (!strcmpi(w1,"ddos_autoreset"))
- ddos_autoreset = atoi(w2);
- else if (!strcmpi(w1,"debug"))
- access_debug = config_switch(w2);
- else if (!strcmpi(w1,"socket_max_client_packet"))
- socket_max_client_packet = strtoul(w2, NULL, 0);
+ else if (!strcmpi(w1, "enable_ip_rules")) {
+ ip_rules = config_switch(w2);
+ } else if (!strcmpi(w1, "order")) {
+ if (!strcmpi(w2, "deny,allow"))
+ access_order = ACO_DENY_ALLOW;
+ else if (!strcmpi(w2, "allow,deny"))
+ access_order = ACO_ALLOW_DENY;
+ else if (!strcmpi(w2, "mutual-failure"))
+ access_order = ACO_MUTUAL_FAILURE;
+ } else if (!strcmpi(w1, "allow")) {
+ RECREATE(access_allow, AccessControl, access_allownum+1);
+ if (access_ipmask(w2, &access_allow[access_allownum]))
+ ++access_allownum;
+ else
+ ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
+ } else if (!strcmpi(w1, "deny")) {
+ RECREATE(access_deny, AccessControl, access_denynum+1);
+ if (access_ipmask(w2, &access_deny[access_denynum]))
+ ++access_denynum;
+ else
+ ShowError("socket_config_read: Invalid ip or ip range '%s'!\n", line);
+ } else if (!strcmpi(w1,"ddos_interval"))
+ ddos_interval = atoi(w2);
+ else if (!strcmpi(w1,"ddos_count"))
+ ddos_count = atoi(w2);
+ else if (!strcmpi(w1,"ddos_autoreset"))
+ ddos_autoreset = atoi(w2);
+ else if (!strcmpi(w1,"debug"))
+ access_debug = config_switch(w2);
+ else if (!strcmpi(w1,"socket_max_client_packet"))
+ socket_max_client_packet = strtoul(w2, NULL, 0);
#endif
- else if (!strcmpi(w1, "import"))
- socket_config_read(w2);
- else
- ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
- }
-
- fclose(fp);
- return 0;
+ else if (!strcmpi(w1, "import"))
+ socket_config_read(w2);
+ else
+ ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
+ }
+
+ fclose(fp);
+ return 0;
}
void socket_final(void)
{
- int i;
+ int i;
#ifndef MINICORE
- ConnectHistory* hist;
- ConnectHistory* next_hist;
-
- for( i=0; i < 0x10000; ++i ){
- hist = connect_history[i];
- while( hist ){
- next_hist = hist->next;
- aFree(hist);
- hist = next_hist;
- }
- }
- if( access_allow )
- aFree(access_allow);
- if( access_deny )
- aFree(access_deny);
+ ConnectHistory *hist;
+ ConnectHistory *next_hist;
+
+ for (i=0; i < 0x10000; ++i) {
+ hist = connect_history[i];
+ while (hist) {
+ next_hist = hist->next;
+ aFree(hist);
+ hist = next_hist;
+ }
+ }
+ if (access_allow)
+ aFree(access_allow);
+ if (access_deny)
+ aFree(access_deny);
#endif
- for( i = 1; i < fd_max; i++ )
- if(session[i])
- do_close(i);
+ for (i = 1; i < fd_max; i++)
+ if (session[i])
+ do_close(i);
- // session[0] ‚̃_ƒ~[ƒf[ƒ^‚ðíœ
- aFree(session[0]->rdata);
- aFree(session[0]->wdata);
- aFree(session[0]);
+ // session[0] ‚̃_ƒ~[ƒf[ƒ^‚ðíœ
+ aFree(session[0]->rdata);
+ aFree(session[0]->wdata);
+ aFree(session[0]);
}
/// 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
- sClose(fd); // We don't really care if these closing functions return an error, we are just shutting down and not reusing this socket.
- if (session[fd]) delete_session(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
+ sClose(fd); // We don't really care if these closing functions return an error, we are just shutting down and not reusing this socket.
+ if (session[fd]) delete_session(fd);
}
/// Retrieve local ips in host byte order.
/// Uses loopback is no address is found.
-int socket_getips(uint32* ips, int max)
+int socket_getips(uint32 *ips, int max)
{
- int num = 0;
+ int num = 0;
- if( ips == NULL || max <= 0 )
- return 0;
+ if (ips == NULL || max <= 0)
+ return 0;
#ifdef WIN32
- {
- char fullhost[255];
- u_long** a;
- struct hostent* hent;
-
- // XXX This should look up the local IP addresses in the registry
- // instead of calling gethostbyname. However, the way IP addresses
- // are stored in the registry is annoyingly complex, so I'll leave
- // this as T.B.D. [Meruru]
- if( gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR )
- {
- ShowError("socket_getips: No hostname defined!\n");
- return 0;
- }
- else
- {
- hent = gethostbyname(fullhost);
- if( hent == NULL ){
- ShowError("socket_getips: Cannot resolve our own hostname to an IP address\n");
- return 0;
- }
- a = (u_long**)hent->h_addr_list;
- for( ; a[num] != NULL && num < max; ++num)
- ips[num] = (uint32)ntohl(*a[num]);
- }
- }
+ {
+ char fullhost[255];
+ u_long **a;
+ struct hostent *hent;
+
+ // XXX This should look up the local IP addresses in the registry
+ // instead of calling gethostbyname. However, the way IP addresses
+ // are stored in the registry is annoyingly complex, so I'll leave
+ // this as T.B.D. [Meruru]
+ if (gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR) {
+ ShowError("socket_getips: No hostname defined!\n");
+ return 0;
+ } else {
+ hent = gethostbyname(fullhost);
+ if (hent == NULL) {
+ ShowError("socket_getips: Cannot resolve our own hostname to an IP address\n");
+ return 0;
+ }
+ a = (u_long **)hent->h_addr_list;
+ for (; a[num] != NULL && num < max; ++num)
+ ips[num] = (uint32)ntohl(*a[num]);
+ }
+ }
#else // not WIN32
- {
- int pos;
- int fd;
- char buf[2*16*sizeof(struct ifreq)];
- struct ifconf ic;
- struct ifreq* ir;
- struct sockaddr_in* a;
- u_long ad;
-
- fd = sSocket(AF_INET, SOCK_STREAM, 0);
-
- memset(buf, 0x00, sizeof(buf));
-
- // The ioctl call will fail with Invalid Argument if there are more
- // interfaces than will fit in the buffer
- ic.ifc_len = sizeof(buf);
- ic.ifc_buf = buf;
- if( sIoctl(fd, SIOCGIFCONF, &ic) == -1 )
- {
- ShowError("socket_getips: SIOCGIFCONF failed!\n");
- return 0;
- }
- else
- {
- for( pos=0; pos < ic.ifc_len && num < max; )
- {
- ir = (struct ifreq*)(buf+pos);
- a = (struct sockaddr_in*) &(ir->ifr_addr);
- if( a->sin_family == AF_INET ){
- ad = ntohl(a->sin_addr.s_addr);
- if( ad != INADDR_LOOPBACK && ad != INADDR_ANY )
- ips[num++] = (uint32)ad;
- }
- #if (defined(BSD) && BSD >= 199103) || defined(_AIX) || defined(__APPLE__)
- pos += ir->ifr_addr.sa_len + sizeof(ir->ifr_name);
- #else// not AIX or APPLE
- pos += sizeof(struct ifreq);
- #endif//not AIX or APPLE
- }
- }
- sClose(fd);
- }
+ {
+ int pos;
+ int fd;
+ char buf[2*16*sizeof(struct ifreq)];
+ struct ifconf ic;
+ struct ifreq *ir;
+ struct sockaddr_in *a;
+ u_long ad;
+
+ fd = sSocket(AF_INET, SOCK_STREAM, 0);
+
+ memset(buf, 0x00, sizeof(buf));
+
+ // The ioctl call will fail with Invalid Argument if there are more
+ // interfaces than will fit in the buffer
+ ic.ifc_len = sizeof(buf);
+ ic.ifc_buf = buf;
+ if (sIoctl(fd, SIOCGIFCONF, &ic) == -1) {
+ ShowError("socket_getips: SIOCGIFCONF failed!\n");
+ return 0;
+ } else {
+ for (pos=0; pos < ic.ifc_len && num < max;) {
+ ir = (struct ifreq *)(buf+pos);
+ a = (struct sockaddr_in *) &(ir->ifr_addr);
+ if (a->sin_family == AF_INET) {
+ ad = ntohl(a->sin_addr.s_addr);
+ if (ad != INADDR_LOOPBACK && ad != INADDR_ANY)
+ ips[num++] = (uint32)ad;
+ }
+#if (defined(BSD) && BSD >= 199103) || defined(_AIX) || defined(__APPLE__)
+ pos += ir->ifr_addr.sa_len + sizeof(ir->ifr_name);
+#else// not AIX or APPLE
+ pos += sizeof(struct ifreq);
+#endif//not AIX or APPLE
+ }
+ }
+ sClose(fd);
+ }
#endif // not W32
- // Use loopback if no ips are found
- if( num == 0 )
- ips[num++] = (uint32)INADDR_LOOPBACK;
+ // Use loopback if no ips are found
+ if (num == 0)
+ ips[num++] = (uint32)INADDR_LOOPBACK;
- return num;
+ return num;
}
void socket_init(void)
{
- char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf";
- unsigned int rlim_cur = FD_SETSIZE;
+ char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf";
+ unsigned int rlim_cur = FD_SETSIZE;
#ifdef WIN32
- {// Start up windows networking
- WSADATA wsaData;
- WORD wVersionRequested = MAKEWORD(2, 0);
- if( WSAStartup(wVersionRequested, &wsaData) != 0 )
- {
- ShowError("socket_init: WinSock not available!\n");
- return;
- }
- if( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0 )
- {
- ShowError("socket_init: WinSock version mismatch (2.0 or compatible required)!\n");
- return;
- }
- }
+ {
+ // Start up windows networking
+ WSADATA wsaData;
+ WORD wVersionRequested = MAKEWORD(2, 0);
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
+ ShowError("socket_init: WinSock not available!\n");
+ return;
+ }
+ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
+ ShowError("socket_init: WinSock version mismatch (2.0 or compatible required)!\n");
+ return;
+ }
+ }
#elif defined(HAVE_SETRLIMIT) && !defined(CYGWIN)
- // NOTE: getrlimit and setrlimit have bogus behaviour in cygwin.
- // "Number of fds is virtually unlimited in cygwin" (sys/param.h)
- {// set socket limit to FD_SETSIZE
- struct rlimit rlp;
- if( 0 == getrlimit(RLIMIT_NOFILE, &rlp) )
- {
- rlp.rlim_cur = FD_SETSIZE;
- if( 0 != setrlimit(RLIMIT_NOFILE, &rlp) )
- {// failed, try setting the maximum too (permission to change system limits is required)
- rlp.rlim_max = FD_SETSIZE;
- if( 0 != setrlimit(RLIMIT_NOFILE, &rlp) )
- {// failed
- const char *errmsg = error_msg();
- int rlim_ori;
- // set to maximum allowed
- getrlimit(RLIMIT_NOFILE, &rlp);
- rlim_ori = (int)rlp.rlim_cur;
- rlp.rlim_cur = rlp.rlim_max;
- setrlimit(RLIMIT_NOFILE, &rlp);
- // report limit
- getrlimit(RLIMIT_NOFILE, &rlp);
- rlim_cur = rlp.rlim_cur;
- ShowWarning("socket_init: failed to set socket limit to %d, setting to maximum allowed (original limit=%d, current limit=%d, maximum allowed=%d, %s).\n", FD_SETSIZE, rlim_ori, (int)rlp.rlim_cur, (int)rlp.rlim_max, errmsg);
- }
- }
- }
- }
+ // NOTE: getrlimit and setrlimit have bogus behaviour in cygwin.
+ // "Number of fds is virtually unlimited in cygwin" (sys/param.h)
+ {
+ // set socket limit to FD_SETSIZE
+ struct rlimit rlp;
+ if (0 == getrlimit(RLIMIT_NOFILE, &rlp)) {
+ rlp.rlim_cur = FD_SETSIZE;
+ if (0 != setrlimit(RLIMIT_NOFILE, &rlp)) {
+ // failed, try setting the maximum too (permission to change system limits is required)
+ rlp.rlim_max = FD_SETSIZE;
+ if (0 != setrlimit(RLIMIT_NOFILE, &rlp)) {
+ // failed
+ const char *errmsg = error_msg();
+ int rlim_ori;
+ // set to maximum allowed
+ getrlimit(RLIMIT_NOFILE, &rlp);
+ rlim_ori = (int)rlp.rlim_cur;
+ rlp.rlim_cur = rlp.rlim_max;
+ setrlimit(RLIMIT_NOFILE, &rlp);
+ // report limit
+ getrlimit(RLIMIT_NOFILE, &rlp);
+ rlim_cur = rlp.rlim_cur;
+ ShowWarning("socket_init: failed to set socket limit to %d, setting to maximum allowed (original limit=%d, current limit=%d, maximum allowed=%d, %s).\n", FD_SETSIZE, rlim_ori, (int)rlp.rlim_cur, (int)rlp.rlim_max, errmsg);
+ }
+ }
+ }
+ }
#endif
- // Get initial local ips
- naddr_ = socket_getips(addr_,16);
+ // Get initial local ips
+ naddr_ = socket_getips(addr_,16);
- sFD_ZERO(&readfds);
+ sFD_ZERO(&readfds);
#if defined(SEND_SHORTLIST)
- memset(send_shortlist_set, 0, sizeof(send_shortlist_set));
+ memset(send_shortlist_set, 0, sizeof(send_shortlist_set));
#endif
- socket_config_read(SOCKET_CONF_FILENAME);
+ socket_config_read(SOCKET_CONF_FILENAME);
- // initialise last send-receive tick
- last_tick = time(NULL);
+ // initialise last send-receive tick
+ last_tick = time(NULL);
- // session[0] is now currently used for disconnected sessions of the map server, and as such,
- // should hold enough buffer (it is a vacuum so to speak) as it is never flushed. [Skotlex]
- create_session(0, null_recv, null_send, null_parse);
+ // session[0] is now currently used for disconnected sessions of the map server, and as such,
+ // should hold enough buffer (it is a vacuum so to speak) as it is never flushed. [Skotlex]
+ create_session(0, null_recv, null_send, null_parse);
#ifndef MINICORE
- // Delete old connection history every 5 minutes
- memset(connect_history, 0, sizeof(connect_history));
- add_timer_func_list(connect_check_clear, "connect_check_clear");
- add_timer_interval(gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
+ // Delete old connection history every 5 minutes
+ memset(connect_history, 0, sizeof(connect_history));
+ add_timer_func_list(connect_check_clear, "connect_check_clear");
+ add_timer_interval(gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
#endif
- ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur);
+ ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur);
}
bool session_isValid(int fd)
{
- return ( fd > 0 && fd < FD_SETSIZE && session[fd] != NULL );
+ return (fd > 0 && fd < FD_SETSIZE && session[fd] != NULL);
}
bool session_isActive(int fd)
{
- return ( session_isValid(fd) && !session[fd]->flag.eof );
+ return (session_isValid(fd) && !session[fd]->flag.eof);
}
// Resolves hostname into a numeric ip.
-uint32 host2ip(const char* hostname)
+uint32 host2ip(const char *hostname)
{
- struct hostent* h = gethostbyname(hostname);
- return (h != NULL) ? ntohl(*(uint32*)h->h_addr) : 0;
+ struct hostent *h = gethostbyname(hostname);
+ return (h != NULL) ? ntohl(*(uint32 *)h->h_addr) : 0;
}
// Converts a numeric ip into a dot-formatted string.
// Result is placed either into a user-provided buffer or a static system buffer.
-const char* ip2str(uint32 ip, char ip_str[16])
+const char *ip2str(uint32 ip, char ip_str[16])
{
- struct in_addr addr;
- addr.s_addr = htonl(ip);
- return (ip_str == NULL) ? inet_ntoa(addr) : strncpy(ip_str, inet_ntoa(addr), 16);
+ struct in_addr addr;
+ addr.s_addr = htonl(ip);
+ return (ip_str == NULL) ? inet_ntoa(addr) : strncpy(ip_str, inet_ntoa(addr), 16);
}
// Converts a dot-formatted ip string into a numeric ip.
-uint32 str2ip(const char* ip_str)
+uint32 str2ip(const char *ip_str)
{
- return ntohl(inet_addr(ip_str));
+ return ntohl(inet_addr(ip_str));
}
// Reorders bytes from network to little endian (Windows).
// Neccessary for sending port numbers to the RO client until Gravity notices that they forgot ntohs() calls.
uint16 ntows(uint16 netshort)
{
- return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8);
+ return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8);
}
#ifdef SEND_SHORTLIST
@@ -1382,75 +1364,70 @@ uint16 ntows(uint16 netshort)
// sending or eof handling.
void send_shortlist_add_fd(int fd)
{
- int i;
- int bit;
+ int i;
+ int bit;
- if( !session_isValid(fd) )
- return;// out of range
+ if (!session_isValid(fd))
+ return;// out of range
- i = fd/32;
- bit = fd%32;
+ i = fd/32;
+ bit = fd%32;
- if( (send_shortlist_set[i]>>bit)&1 )
- return;// already in the list
+ if ((send_shortlist_set[i]>>bit)&1)
+ return;// already in the list
- if( send_shortlist_count >= ARRAYLENGTH(send_shortlist_array) )
- {
- ShowDebug("send_shortlist_add_fd: shortlist is full, ignoring... (fd=%d shortlist.count=%d shortlist.length=%d)\n", fd, send_shortlist_count, ARRAYLENGTH(send_shortlist_array));
- return;
- }
+ if (send_shortlist_count >= ARRAYLENGTH(send_shortlist_array)) {
+ ShowDebug("send_shortlist_add_fd: shortlist is full, ignoring... (fd=%d shortlist.count=%d shortlist.length=%d)\n", fd, send_shortlist_count, ARRAYLENGTH(send_shortlist_array));
+ return;
+ }
- // set the bit
- send_shortlist_set[i] |= 1<<bit;
- // Add to the end of the shortlist array.
- send_shortlist_array[send_shortlist_count++] = fd;
+ // set the bit
+ send_shortlist_set[i] |= 1<<bit;
+ // Add to the end of the shortlist array.
+ send_shortlist_array[send_shortlist_count++] = fd;
}
// Do pending network sends and eof handling from the shortlist.
void send_shortlist_do_sends()
{
- int i;
-
- for( i = send_shortlist_count-1; i >= 0; --i )
- {
- int fd = send_shortlist_array[i];
- int idx = fd/32;
- int bit = fd%32;
-
- // Remove fd from shortlist, move the last fd to the current position
- --send_shortlist_count;
- send_shortlist_array[i] = send_shortlist_array[send_shortlist_count];
- send_shortlist_array[send_shortlist_count] = 0;
-
- if( fd <= 0 || fd >= FD_SETSIZE )
- {
- ShowDebug("send_shortlist_do_sends: fd is out of range, corrupted memory? (fd=%d)\n", fd);
- continue;
- }
- if( ((send_shortlist_set[idx]>>bit)&1) == 0 )
- {
- ShowDebug("send_shortlist_do_sends: fd is not set, why is it in the shortlist? (fd=%d)\n", fd);
- continue;
- }
- send_shortlist_set[idx]&=~(1<<bit);// unset fd
- // If this session still exists, perform send operations on it and
- // check for the eof state.
- if( session[fd] )
- {
- // Send data
- if( session[fd]->wdata_size )
- session[fd]->func_send(fd);
-
- // If it's been marked as eof, call the parse func on it so that
- // the socket will be immediately closed.
- if( session[fd]->flag.eof )
- session[fd]->func_parse(fd);
-
- // If the session still exists, is not eof and has things left to
- // be sent from it we'll re-add it to the shortlist.
- if( session[fd] && !session[fd]->flag.eof && session[fd]->wdata_size )
- send_shortlist_add_fd(fd);
- }
- }
+ int i;
+
+ for (i = send_shortlist_count-1; i >= 0; --i) {
+ int fd = send_shortlist_array[i];
+ int idx = fd/32;
+ int bit = fd%32;
+
+ // Remove fd from shortlist, move the last fd to the current position
+ --send_shortlist_count;
+ send_shortlist_array[i] = send_shortlist_array[send_shortlist_count];
+ send_shortlist_array[send_shortlist_count] = 0;
+
+ if (fd <= 0 || fd >= FD_SETSIZE) {
+ ShowDebug("send_shortlist_do_sends: fd is out of range, corrupted memory? (fd=%d)\n", fd);
+ continue;
+ }
+ if (((send_shortlist_set[idx]>>bit)&1) == 0) {
+ ShowDebug("send_shortlist_do_sends: fd is not set, why is it in the shortlist? (fd=%d)\n", fd);
+ continue;
+ }
+ send_shortlist_set[idx]&=~(1<<bit);// unset fd
+ // If this session still exists, perform send operations on it and
+ // check for the eof state.
+ if (session[fd]) {
+ // Send data
+ if (session[fd]->wdata_size)
+ session[fd]->func_send(fd);
+
+ // If it's been marked as eof, call the parse func on it so that
+ // the socket will be immediately closed.
+ if (session[fd]->flag.eof)
+ session[fd]->func_parse(fd);
+
+ // If the session still exists, is not eof and has things left to
+ // be sent from it we'll re-add it to the shortlist.
+ if (session[fd] && !session[fd]->flag.eof && session[fd]->wdata_size)
+ send_shortlist_add_fd(fd);
+ }
+ }
}
#endif
diff --git a/src/common/socket.h b/src/common/socket.h
index 7c0e02f5d..5c4008d62 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -1,18 +1,18 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _SOCKET_H_
+#ifndef _SOCKET_H_
#define _SOCKET_H_
#include "../common/cbasetypes.h"
#ifdef WIN32
- #include "../common/winapi.h"
- typedef long in_addr_t;
+#include "../common/winapi.h"
+typedef long in_addr_t;
#else
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#endif
#include <time.h>
@@ -38,15 +38,15 @@
#define RFIFOREST(fd) (session[fd]->flag.eof ? 0 : session[fd]->rdata_size - session[fd]->rdata_pos)
#define RFIFOFLUSH(fd) \
- do { \
- if(session[fd]->rdata_size == session[fd]->rdata_pos){ \
- session[fd]->rdata_size = session[fd]->rdata_pos = 0; \
- } else { \
- session[fd]->rdata_size -= session[fd]->rdata_pos; \
- memmove(session[fd]->rdata, session[fd]->rdata+session[fd]->rdata_pos, session[fd]->rdata_size); \
- session[fd]->rdata_pos = 0; \
- } \
- } while(0)
+ do { \
+ if(session[fd]->rdata_size == session[fd]->rdata_pos){ \
+ session[fd]->rdata_size = session[fd]->rdata_pos = 0; \
+ } else { \
+ session[fd]->rdata_size -= session[fd]->rdata_pos; \
+ memmove(session[fd]->rdata, session[fd]->rdata+session[fd]->rdata_pos, session[fd]->rdata_size); \
+ session[fd]->rdata_pos = 0; \
+ } \
+ } while(0)
// buffer I/O macros
#define RBUFP(p,pos) (((uint8*)(p)) + (pos))
@@ -71,33 +71,32 @@ typedef int (*RecvFunc)(int fd);
typedef int (*SendFunc)(int fd);
typedef int (*ParseFunc)(int fd);
-struct socket_data
-{
- struct {
- unsigned char eof : 1;
- unsigned char server : 1;
- unsigned char ping : 2;
- } flag;
+struct socket_data {
+ struct {
+ unsigned char eof : 1;
+ unsigned char server : 1;
+ unsigned char ping : 2;
+ } flag;
- uint32 client_addr; // remote client address
+ uint32 client_addr; // remote client address
- uint8 *rdata, *wdata;
- size_t max_rdata, max_wdata;
- size_t rdata_size, wdata_size;
- size_t rdata_pos;
- time_t rdata_tick; // time of last recv (for detecting timeouts); zero when timeout is disabled
+ uint8 *rdata, *wdata;
+ size_t max_rdata, max_wdata;
+ size_t rdata_size, wdata_size;
+ size_t rdata_pos;
+ time_t rdata_tick; // time of last recv (for detecting timeouts); zero when timeout is disabled
- RecvFunc func_recv;
- SendFunc func_send;
- ParseFunc func_parse;
+ RecvFunc func_recv;
+ SendFunc func_send;
+ ParseFunc func_parse;
- void* session_data; // stores application-specific data related to the session
+ void *session_data; // stores application-specific data related to the session
};
// Data prototype declaration
-extern struct socket_data* session[FD_SETSIZE];
+extern struct socket_data *session[FD_SETSIZE];
extern int fd_max;
@@ -131,21 +130,21 @@ extern void set_nonblocking(int fd, unsigned long yes);
void set_defaultparse(ParseFunc defaultparse);
// hostname/ip conversion functions
-uint32 host2ip(const char* hostname);
-const char* ip2str(uint32 ip, char ip_str[16]);
-uint32 str2ip(const char* ip_str);
+uint32 host2ip(const char *hostname);
+const char *ip2str(uint32 ip, char ip_str[16]);
+uint32 str2ip(const char *ip_str);
#define CONVIP(ip) ((ip)>>24)&0xFF,((ip)>>16)&0xFF,((ip)>>8)&0xFF,((ip)>>0)&0xFF
#define MAKEIP(a,b,c,d) (uint32)( ( ( (a)&0xFF ) << 24 ) | ( ( (b)&0xFF ) << 16 ) | ( ( (c)&0xFF ) << 8 ) | ( ( (d)&0xFF ) << 0 ) )
uint16 ntows(uint16 netshort);
-int socket_getips(uint32* ips, int max);
+int socket_getips(uint32 *ips, int max);
extern uint32 addr_[16]; // ip addresses of local host (host byte order)
extern int naddr_; // # of ip addresses
void set_eof(int fd);
-/// Use a shortlist of sockets instead of iterating all sessions for sockets
+/// Use a shortlist of sockets instead of iterating all sessions for sockets
/// that have data to send or need eof handling.
/// Adapted to use a static array instead of a linked list.
///
diff --git a/src/common/spinlock.h b/src/common/spinlock.h
index 3419bfdd5..8d1624b33 100644
--- a/src/common/spinlock.h
+++ b/src/common/spinlock.h
@@ -14,7 +14,7 @@
// For more information, see LICENCE in the main folder
//
//
-
+
#ifdef WIN32
#include "../common/winapi.h"
#endif
@@ -25,77 +25,81 @@
#ifdef WIN32
-typedef struct __declspec( align(64) ) SPIN_LOCK{
- volatile LONG lock;
- volatile LONG nest;
- volatile LONG sync_lock;
+typedef struct __declspec(align(64)) SPIN_LOCK {
+ volatile LONG lock;
+ volatile LONG nest;
+ volatile LONG sync_lock;
} SPIN_LOCK, *PSPIN_LOCK;
#else
-typedef struct SPIN_LOCK{
- volatile int32 lock;
- volatile int32 nest; // nesting level.
-
- volatile int32 sync_lock;
+typedef struct SPIN_LOCK {
+ volatile int32 lock;
+ volatile int32 nest; // nesting level.
+
+ volatile int32 sync_lock;
} __attribute__((aligned(64))) SPIN_LOCK, *PSPIN_LOCK;
#endif
-static forceinline void InitializeSpinLock(PSPIN_LOCK lck){
- lck->lock = 0;
- lck->nest = 0;
- lck->sync_lock = 0;
+static forceinline void InitializeSpinLock(PSPIN_LOCK lck)
+{
+ lck->lock = 0;
+ lck->nest = 0;
+ lck->sync_lock = 0;
}
-static forceinline void FinalizeSpinLock(PSPIN_LOCK lck){
- return;
+static forceinline void FinalizeSpinLock(PSPIN_LOCK lck)
+{
+ return;
}
#define getsynclock(l) { while(1){ if(InterlockedCompareExchange(l, 1, 0) == 0) break; rathread_yield(); } }
#define dropsynclock(l) { InterlockedExchange(l, 0); }
-static forceinline void EnterSpinLock(PSPIN_LOCK lck){
- int tid = rathread_get_tid();
-
- // Get Sync Lock && Check if the requester thread already owns the lock.
- // if it owns, increase nesting level
- getsynclock(&lck->sync_lock);
- if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){
- InterlockedIncrement(&lck->nest);
- dropsynclock(&lck->sync_lock);
- return; // Got Lock
- }
- // drop sync lock
- dropsynclock(&lck->sync_lock);
-
-
- // Spin until we've got it !
- while(1){
-
- if(InterlockedCompareExchange(&lck->lock, tid, 0) == 0){
-
- InterlockedIncrement(&lck->nest);
- return; // Got Lock
- }
-
- rathread_yield(); // Force ctxswitch to another thread.
- }
+static forceinline void EnterSpinLock(PSPIN_LOCK lck)
+{
+ int tid = rathread_get_tid();
+
+ // Get Sync Lock && Check if the requester thread already owns the lock.
+ // if it owns, increase nesting level
+ getsynclock(&lck->sync_lock);
+ if (InterlockedCompareExchange(&lck->lock, tid, tid) == tid) {
+ InterlockedIncrement(&lck->nest);
+ dropsynclock(&lck->sync_lock);
+ return; // Got Lock
+ }
+ // drop sync lock
+ dropsynclock(&lck->sync_lock);
+
+
+ // Spin until we've got it !
+ while (1) {
+
+ if (InterlockedCompareExchange(&lck->lock, tid, 0) == 0) {
+
+ InterlockedIncrement(&lck->nest);
+ return; // Got Lock
+ }
+
+ rathread_yield(); // Force ctxswitch to another thread.
+ }
}
-static forceinline void LeaveSpinLock(PSPIN_LOCK lck){
- int tid = rathread_get_tid();
+static forceinline void LeaveSpinLock(PSPIN_LOCK lck)
+{
+ int tid = rathread_get_tid();
+
+ getsynclock(&lck->sync_lock);
+
+ if (InterlockedCompareExchange(&lck->lock, tid, tid) == tid) { // this thread owns the lock.
+ if (InterlockedDecrement(&lck->nest) == 0)
+ InterlockedExchange(&lck->lock, 0); // Unlock!
+ }
- getsynclock(&lck->sync_lock);
-
- if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ // this thread owns the lock.
- if(InterlockedDecrement(&lck->nest) == 0)
- InterlockedExchange(&lck->lock, 0); // Unlock!
- }
-
- dropsynclock(&lck->sync_lock);
+ dropsynclock(&lck->sync_lock);
}
diff --git a/src/common/sql.c b/src/common/sql.c
index 800aa89b0..740da476d 100644
--- a/src/common/sql.c
+++ b/src/common/sql.c
@@ -18,41 +18,38 @@
/// Sql handle
-struct Sql
-{
- StringBuf buf;
- MYSQL handle;
- MYSQL_RES* result;
- MYSQL_ROW row;
- unsigned long* lengths;
- int keepalive;
+struct Sql {
+ StringBuf buf;
+ MYSQL handle;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ unsigned long *lengths;
+ int keepalive;
};
// Column length receiver.
// Takes care of the possible size missmatch between uint32 and unsigned long.
-struct s_column_length
-{
- uint32* out_length;
- unsigned long length;
+struct s_column_length {
+ uint32 *out_length;
+ unsigned long length;
};
typedef struct s_column_length s_column_length;
/// Sql statement
-struct SqlStmt
-{
- StringBuf buf;
- MYSQL_STMT* stmt;
- MYSQL_BIND* params;
- MYSQL_BIND* columns;
- s_column_length* column_lengths;
- size_t max_params;
- size_t max_columns;
- bool bind_params;
- bool bind_columns;
+struct SqlStmt {
+ StringBuf buf;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND *params;
+ MYSQL_BIND *columns;
+ s_column_length *column_lengths;
+ size_t max_params;
+ size_t max_columns;
+ bool bind_params;
+ bool bind_columns;
};
@@ -64,117 +61,111 @@ struct SqlStmt
/// Allocates and initializes a new Sql handle.
-Sql* Sql_Malloc(void)
+Sql *Sql_Malloc(void)
{
- Sql* self;
+ Sql *self;
- CREATE(self, Sql, 1);
- mysql_init(&self->handle);
- StringBuf_Init(&self->buf);
- self->lengths = NULL;
- self->result = NULL;
- self->keepalive = INVALID_TIMER;
+ CREATE(self, Sql, 1);
+ mysql_init(&self->handle);
+ StringBuf_Init(&self->buf);
+ self->lengths = NULL;
+ self->result = NULL;
+ self->keepalive = INVALID_TIMER;
- return self;
+ return self;
}
-static int Sql_P_Keepalive(Sql* self);
+static int Sql_P_Keepalive(Sql *self);
/// Establishes a connection.
-int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db)
+int Sql_Connect(Sql *self, const char *user, const char *passwd, const char *host, uint16 port, const char *db)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- StringBuf_Clear(&self->buf);
- if( !mysql_real_connect(&self->handle, host, user, passwd, db, (unsigned int)port, NULL/*unix_socket*/, 0/*clientflag*/) )
- {
- ShowSQL("%s\n", mysql_error(&self->handle));
- return SQL_ERROR;
- }
+ StringBuf_Clear(&self->buf);
+ if (!mysql_real_connect(&self->handle, host, user, passwd, db, (unsigned int)port, NULL/*unix_socket*/, 0/*clientflag*/)) {
+ ShowSQL("%s\n", mysql_error(&self->handle));
+ return SQL_ERROR;
+ }
- self->keepalive = Sql_P_Keepalive(self);
- if( self->keepalive == INVALID_TIMER )
- {
- ShowSQL("Failed to establish keepalive for DB connection!\n");
- return SQL_ERROR;
- }
+ self->keepalive = Sql_P_Keepalive(self);
+ if (self->keepalive == INVALID_TIMER) {
+ ShowSQL("Failed to establish keepalive for DB connection!\n");
+ return SQL_ERROR;
+ }
- return SQL_SUCCESS;
+ return SQL_SUCCESS;
}
/// Retrieves the timeout of the connection.
-int Sql_GetTimeout(Sql* self, uint32* out_timeout)
+int Sql_GetTimeout(Sql *self, uint32 *out_timeout)
{
- if( self && out_timeout && SQL_SUCCESS == Sql_Query(self, "SHOW VARIABLES LIKE 'wait_timeout'") )
- {
- char* data;
- size_t len;
- if( SQL_SUCCESS == Sql_NextRow(self) &&
- SQL_SUCCESS == Sql_GetData(self, 1, &data, &len) )
- {
- *out_timeout = (uint32)strtoul(data, NULL, 10);
- Sql_FreeResult(self);
- return SQL_SUCCESS;
- }
- Sql_FreeResult(self);
- }
- return SQL_ERROR;
+ if (self && out_timeout && SQL_SUCCESS == Sql_Query(self, "SHOW VARIABLES LIKE 'wait_timeout'")) {
+ char *data;
+ size_t len;
+ if (SQL_SUCCESS == Sql_NextRow(self) &&
+ SQL_SUCCESS == Sql_GetData(self, 1, &data, &len)) {
+ *out_timeout = (uint32)strtoul(data, NULL, 10);
+ Sql_FreeResult(self);
+ return SQL_SUCCESS;
+ }
+ Sql_FreeResult(self);
+ }
+ return SQL_ERROR;
}
/// Retrieves the name of the columns of a table into out_buf, with the separator after each name.
-int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_len, char sep)
+int Sql_GetColumnNames(Sql *self, const char *table, char *out_buf, size_t buf_len, char sep)
{
- char* data;
- size_t len;
- size_t off = 0;
+ char *data;
+ size_t len;
+ size_t off = 0;
- if( self == NULL || SQL_ERROR == Sql_Query(self, "EXPLAIN `%s`", table) )
- return SQL_ERROR;
+ if (self == NULL || SQL_ERROR == Sql_Query(self, "EXPLAIN `%s`", table))
+ return SQL_ERROR;
- out_buf[off] = '\0';
- while( SQL_SUCCESS == Sql_NextRow(self) && SQL_SUCCESS == Sql_GetData(self, 0, &data, &len) )
- {
- len = strnlen(data, len);
- if( off + len + 2 > buf_len )
- {
- ShowDebug("Sql_GetColumns: output buffer is too small\n");
- *out_buf = '\0';
- return SQL_ERROR;
- }
- memcpy(out_buf+off, data, len);
- off += len;
- out_buf[off++] = sep;
- }
- out_buf[off] = '\0';
- Sql_FreeResult(self);
- return SQL_SUCCESS;
+ out_buf[off] = '\0';
+ while (SQL_SUCCESS == Sql_NextRow(self) && SQL_SUCCESS == Sql_GetData(self, 0, &data, &len)) {
+ len = strnlen(data, len);
+ if (off + len + 2 > buf_len) {
+ ShowDebug("Sql_GetColumns: output buffer is too small\n");
+ *out_buf = '\0';
+ return SQL_ERROR;
+ }
+ memcpy(out_buf+off, data, len);
+ off += len;
+ out_buf[off++] = sep;
+ }
+ out_buf[off] = '\0';
+ Sql_FreeResult(self);
+ return SQL_SUCCESS;
}
/// Changes the encoding of the connection.
-int Sql_SetEncoding(Sql* self, const char* encoding)
+int Sql_SetEncoding(Sql *self, const char *encoding)
{
- if( self && mysql_set_character_set(&self->handle, encoding) == 0 )
- return SQL_SUCCESS;
- return SQL_ERROR;
+ if (self && mysql_set_character_set(&self->handle, encoding) == 0)
+ return SQL_SUCCESS;
+ return SQL_ERROR;
}
/// Pings the connection.
-int Sql_Ping(Sql* self)
+int Sql_Ping(Sql *self)
{
- if( self && mysql_ping(&self->handle) == 0 )
- return SQL_SUCCESS;
- return SQL_ERROR;
+ if (self && mysql_ping(&self->handle) == 0)
+ return SQL_SUCCESS;
+ return SQL_ERROR;
}
@@ -184,10 +175,10 @@ int Sql_Ping(Sql* self)
/// @private
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");
- Sql_Ping(self);
- return 0;
+ Sql *self = (Sql *)data;
+ ShowInfo("Pinging SQL server to keep connection alive...\n");
+ Sql_Ping(self);
+ return 0;
}
@@ -196,224 +187,213 @@ static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr_t dat
///
/// @return the keepalive timer id, or INVALID_TIMER
/// @private
-static int Sql_P_Keepalive(Sql* self)
+static int Sql_P_Keepalive(Sql *self)
{
- uint32 timeout, ping_interval;
+ uint32 timeout, ping_interval;
- // set a default value first
- timeout = 28800; // 8 hours
+ // set a default value first
+ timeout = 28800; // 8 hours
- // request the timeout value from the mysql server
- Sql_GetTimeout(self, &timeout);
+ // request the timeout value from the mysql server
+ Sql_GetTimeout(self, &timeout);
- if( timeout < 60 )
- timeout = 60;
+ if (timeout < 60)
+ timeout = 60;
- // 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_t)self, ping_interval*1000);
+ // 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_t)self, ping_interval*1000);
}
/// Escapes a string.
-size_t Sql_EscapeString(Sql* self, char *out_to, const char *from)
+size_t Sql_EscapeString(Sql *self, char *out_to, const char *from)
{
- if( self )
- return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)strlen(from));
- else
- return (size_t)mysql_escape_string(out_to, from, (unsigned long)strlen(from));
+ if (self)
+ return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)strlen(from));
+ else
+ return (size_t)mysql_escape_string(out_to, from, (unsigned long)strlen(from));
}
/// Escapes a string.
-size_t Sql_EscapeStringLen(Sql* self, char *out_to, const char *from, size_t from_len)
+size_t Sql_EscapeStringLen(Sql *self, char *out_to, const char *from, size_t from_len)
{
- if( self )
- return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)from_len);
- else
- return (size_t)mysql_escape_string(out_to, from, (unsigned long)from_len);
+ if (self)
+ return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)from_len);
+ else
+ return (size_t)mysql_escape_string(out_to, from, (unsigned long)from_len);
}
/// Executes a query.
-int Sql_Query(Sql* self, const char* query, ...)
+int Sql_Query(Sql *self, const char *query, ...)
{
- int res;
- va_list args;
+ int res;
+ va_list args;
- va_start(args, query);
- res = Sql_QueryV(self, query, args);
- va_end(args);
+ va_start(args, query);
+ res = Sql_QueryV(self, query, args);
+ va_end(args);
- return res;
+ return res;
}
/// Executes a query.
-int Sql_QueryV(Sql* self, const char* query, va_list args)
+int Sql_QueryV(Sql *self, const char *query, va_list args)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- Sql_FreeResult(self);
- StringBuf_Clear(&self->buf);
- StringBuf_Vprintf(&self->buf, query, args);
- if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
- {
- ShowSQL("DB error - %s\n", mysql_error(&self->handle));
- return SQL_ERROR;
- }
- self->result = mysql_store_result(&self->handle);
- if( mysql_errno(&self->handle) != 0 )
- {
- ShowSQL("DB error - %s\n", mysql_error(&self->handle));
- return SQL_ERROR;
- }
- return SQL_SUCCESS;
+ Sql_FreeResult(self);
+ StringBuf_Clear(&self->buf);
+ StringBuf_Vprintf(&self->buf, query, args);
+ if (mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf))) {
+ ShowSQL("DB error - %s\n", mysql_error(&self->handle));
+ return SQL_ERROR;
+ }
+ self->result = mysql_store_result(&self->handle);
+ if (mysql_errno(&self->handle) != 0) {
+ ShowSQL("DB error - %s\n", mysql_error(&self->handle));
+ return SQL_ERROR;
+ }
+ return SQL_SUCCESS;
}
/// Executes a query.
-int Sql_QueryStr(Sql* self, const char* query)
+int Sql_QueryStr(Sql *self, const char *query)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- Sql_FreeResult(self);
- StringBuf_Clear(&self->buf);
- StringBuf_AppendStr(&self->buf, query);
- if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
- {
- ShowSQL("DB error - %s\n", mysql_error(&self->handle));
- return SQL_ERROR;
- }
- self->result = mysql_store_result(&self->handle);
- if( mysql_errno(&self->handle) != 0 )
- {
- ShowSQL("DB error - %s\n", mysql_error(&self->handle));
- return SQL_ERROR;
- }
- return SQL_SUCCESS;
+ Sql_FreeResult(self);
+ StringBuf_Clear(&self->buf);
+ StringBuf_AppendStr(&self->buf, query);
+ if (mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf))) {
+ ShowSQL("DB error - %s\n", mysql_error(&self->handle));
+ return SQL_ERROR;
+ }
+ self->result = mysql_store_result(&self->handle);
+ if (mysql_errno(&self->handle) != 0) {
+ ShowSQL("DB error - %s\n", mysql_error(&self->handle));
+ return SQL_ERROR;
+ }
+ return SQL_SUCCESS;
}
/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query.
-uint64 Sql_LastInsertId(Sql* self)
+uint64 Sql_LastInsertId(Sql *self)
{
- if( self )
- return (uint64)mysql_insert_id(&self->handle);
- else
- return 0;
+ if (self)
+ return (uint64)mysql_insert_id(&self->handle);
+ else
+ return 0;
}
/// Returns the number of columns in each row of the result.
-uint32 Sql_NumColumns(Sql* self)
+uint32 Sql_NumColumns(Sql *self)
{
- if( self && self->result )
- return (uint32)mysql_num_fields(self->result);
- return 0;
+ if (self && self->result)
+ return (uint32)mysql_num_fields(self->result);
+ return 0;
}
/// Returns the number of rows in the result.
-uint64 Sql_NumRows(Sql* self)
+uint64 Sql_NumRows(Sql *self)
{
- if( self && self->result )
- return (uint64)mysql_num_rows(self->result);
- return 0;
+ if (self && self->result)
+ return (uint64)mysql_num_rows(self->result);
+ return 0;
}
/// Fetches the next row.
-int Sql_NextRow(Sql* self)
+int Sql_NextRow(Sql *self)
{
- if( self && self->result )
- {
- self->row = mysql_fetch_row(self->result);
- if( self->row )
- {
- self->lengths = mysql_fetch_lengths(self->result);
- return SQL_SUCCESS;
- }
- self->lengths = NULL;
- if( mysql_errno(&self->handle) == 0 )
- return SQL_NO_DATA;
- }
- return SQL_ERROR;
+ if (self && self->result) {
+ self->row = mysql_fetch_row(self->result);
+ if (self->row) {
+ self->lengths = mysql_fetch_lengths(self->result);
+ return SQL_SUCCESS;
+ }
+ self->lengths = NULL;
+ if (mysql_errno(&self->handle) == 0)
+ return SQL_NO_DATA;
+ }
+ return SQL_ERROR;
}
/// Gets the data of a column.
-int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len)
+int Sql_GetData(Sql *self, size_t col, char **out_buf, size_t *out_len)
{
- if( self && self->row )
- {
- if( col < Sql_NumColumns(self) )
- {
- if( out_buf ) *out_buf = self->row[col];
- if( out_len ) *out_len = (size_t)self->lengths[col];
- }
- else
- {// out of range - ignore
- if( out_buf ) *out_buf = NULL;
- if( out_len ) *out_len = 0;
- }
- return SQL_SUCCESS;
- }
- return SQL_ERROR;
+ if (self && self->row) {
+ if (col < Sql_NumColumns(self)) {
+ if (out_buf) *out_buf = self->row[col];
+ if (out_len) *out_len = (size_t)self->lengths[col];
+ } else {
+ // out of range - ignore
+ if (out_buf) *out_buf = NULL;
+ if (out_len) *out_len = 0;
+ }
+ return SQL_SUCCESS;
+ }
+ return SQL_ERROR;
}
/// Frees the result of the query.
-void Sql_FreeResult(Sql* self)
+void Sql_FreeResult(Sql *self)
{
- if( self && self->result )
- {
- mysql_free_result(self->result);
- self->result = NULL;
- self->row = NULL;
- self->lengths = NULL;
- }
+ if (self && self->result) {
+ mysql_free_result(self->result);
+ self->result = NULL;
+ self->row = NULL;
+ self->lengths = NULL;
+ }
}
/// Shows debug information (last query).
-void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug_line)
+void Sql_ShowDebug_(Sql *self, const char *debug_file, const unsigned long debug_line)
{
- if( self == NULL )
- ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line);
- else if( StringBuf_Length(&self->buf) > 0 )
- ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf));
- else
- ShowDebug("at %s:%lu\n", debug_file, debug_line);
+ if (self == NULL)
+ ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line);
+ else if (StringBuf_Length(&self->buf) > 0)
+ ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf));
+ else
+ ShowDebug("at %s:%lu\n", debug_file, debug_line);
}
/// Frees a Sql handle returned by Sql_Malloc.
-void Sql_Free(Sql* self)
+void Sql_Free(Sql *self)
{
- if( self )
- {
- Sql_FreeResult(self);
- StringBuf_Destroy(&self->buf);
- if( self->keepalive != INVALID_TIMER ) delete_timer(self->keepalive, Sql_P_KeepaliveTimer);
- aFree(self);
- }
+ if (self) {
+ Sql_FreeResult(self);
+ StringBuf_Destroy(&self->buf);
+ if (self->keepalive != INVALID_TIMER) delete_timer(self->keepalive, Sql_P_KeepaliveTimer);
+ aFree(self);
+ }
}
@@ -429,16 +409,19 @@ void Sql_Free(Sql* self)
/// @private
static enum enum_field_types Sql_P_SizeToMysqlIntType(int sz)
{
- switch( sz )
- {
- case 1: return MYSQL_TYPE_TINY;
- case 2: return MYSQL_TYPE_SHORT;
- case 4: return MYSQL_TYPE_LONG;
- case 8: return MYSQL_TYPE_LONGLONG;
- default:
- ShowDebug("SizeToMysqlIntType: unsupported size (%d)\n", sz);
- return MYSQL_TYPE_NULL;
- }
+ switch (sz) {
+ case 1:
+ return MYSQL_TYPE_TINY;
+ case 2:
+ return MYSQL_TYPE_SHORT;
+ case 4:
+ return MYSQL_TYPE_LONG;
+ case 8:
+ return MYSQL_TYPE_LONGLONG;
+ default:
+ ShowDebug("SizeToMysqlIntType: unsupported size (%d)\n", sz);
+ return MYSQL_TYPE_NULL;
+ }
}
@@ -446,74 +429,96 @@ static enum enum_field_types Sql_P_SizeToMysqlIntType(int sz)
/// Binds a parameter/result.
///
/// @private
-static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type, void* buffer, size_t buffer_len, unsigned long* out_length, int8* out_is_null)
-{
- memset(bind, 0, sizeof(MYSQL_BIND));
- switch( buffer_type )
- {
- case SQLDT_NULL: bind->buffer_type = MYSQL_TYPE_NULL;
- buffer_len = 0;// FIXME length = ? [FlavioJS]
- break;
- // fixed size
- case SQLDT_UINT8: bind->is_unsigned = 1;
- case SQLDT_INT8: bind->buffer_type = MYSQL_TYPE_TINY;
- buffer_len = 1;
- break;
- case SQLDT_UINT16: bind->is_unsigned = 1;
- case SQLDT_INT16: bind->buffer_type = MYSQL_TYPE_SHORT;
- buffer_len = 2;
- break;
- case SQLDT_UINT32: bind->is_unsigned = 1;
- case SQLDT_INT32: bind->buffer_type = MYSQL_TYPE_LONG;
- buffer_len = 4;
- break;
- case SQLDT_UINT64: bind->is_unsigned = 1;
- case SQLDT_INT64: bind->buffer_type = MYSQL_TYPE_LONGLONG;
- buffer_len = 8;
- break;
- // platform dependent size
- case SQLDT_UCHAR: bind->is_unsigned = 1;
- case SQLDT_CHAR: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(char));
- buffer_len = sizeof(char);
- break;
- case SQLDT_USHORT: bind->is_unsigned = 1;
- case SQLDT_SHORT: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(short));
- buffer_len = sizeof(short);
- break;
- case SQLDT_UINT: bind->is_unsigned = 1;
- case SQLDT_INT: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int));
- buffer_len = sizeof(int);
- break;
- case SQLDT_ULONG: bind->is_unsigned = 1;
- case SQLDT_LONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long));
- buffer_len = sizeof(long);
- break;
- case SQLDT_ULONGLONG: bind->is_unsigned = 1;
- case SQLDT_LONGLONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int64));
- buffer_len = sizeof(int64);
- break;
- // floating point
- case SQLDT_FLOAT: bind->buffer_type = MYSQL_TYPE_FLOAT;
- buffer_len = 4;
- break;
- case SQLDT_DOUBLE: bind->buffer_type = MYSQL_TYPE_DOUBLE;
- buffer_len = 8;
- break;
- // other
- case SQLDT_STRING:
- case SQLDT_ENUM: bind->buffer_type = MYSQL_TYPE_STRING;
- break;
- case SQLDT_BLOB: bind->buffer_type = MYSQL_TYPE_BLOB;
- break;
- default:
- ShowDebug("Sql_P_BindSqlDataType: unsupported buffer type (%d)\n", buffer_type);
- return SQL_ERROR;
- }
- bind->buffer = buffer;
- bind->buffer_length = (unsigned long)buffer_len;
- bind->length = out_length;
- bind->is_null = (my_bool*)out_is_null;
- return SQL_SUCCESS;
+static int Sql_P_BindSqlDataType(MYSQL_BIND *bind, enum SqlDataType buffer_type, void *buffer, size_t buffer_len, unsigned long *out_length, int8 *out_is_null)
+{
+ memset(bind, 0, sizeof(MYSQL_BIND));
+ switch (buffer_type) {
+ case SQLDT_NULL:
+ bind->buffer_type = MYSQL_TYPE_NULL;
+ buffer_len = 0;// FIXME length = ? [FlavioJS]
+ break;
+ // fixed size
+ case SQLDT_UINT8:
+ bind->is_unsigned = 1;
+ case SQLDT_INT8:
+ bind->buffer_type = MYSQL_TYPE_TINY;
+ buffer_len = 1;
+ break;
+ case SQLDT_UINT16:
+ bind->is_unsigned = 1;
+ case SQLDT_INT16:
+ bind->buffer_type = MYSQL_TYPE_SHORT;
+ buffer_len = 2;
+ break;
+ case SQLDT_UINT32:
+ bind->is_unsigned = 1;
+ case SQLDT_INT32:
+ bind->buffer_type = MYSQL_TYPE_LONG;
+ buffer_len = 4;
+ break;
+ case SQLDT_UINT64:
+ bind->is_unsigned = 1;
+ case SQLDT_INT64:
+ bind->buffer_type = MYSQL_TYPE_LONGLONG;
+ buffer_len = 8;
+ break;
+ // platform dependent size
+ case SQLDT_UCHAR:
+ bind->is_unsigned = 1;
+ case SQLDT_CHAR:
+ bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(char));
+ buffer_len = sizeof(char);
+ break;
+ case SQLDT_USHORT:
+ bind->is_unsigned = 1;
+ case SQLDT_SHORT:
+ bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(short));
+ buffer_len = sizeof(short);
+ break;
+ case SQLDT_UINT:
+ bind->is_unsigned = 1;
+ case SQLDT_INT:
+ bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int));
+ buffer_len = sizeof(int);
+ break;
+ case SQLDT_ULONG:
+ bind->is_unsigned = 1;
+ case SQLDT_LONG:
+ bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long));
+ buffer_len = sizeof(long);
+ break;
+ case SQLDT_ULONGLONG:
+ bind->is_unsigned = 1;
+ case SQLDT_LONGLONG:
+ bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int64));
+ buffer_len = sizeof(int64);
+ break;
+ // floating point
+ case SQLDT_FLOAT:
+ bind->buffer_type = MYSQL_TYPE_FLOAT;
+ buffer_len = 4;
+ break;
+ case SQLDT_DOUBLE:
+ bind->buffer_type = MYSQL_TYPE_DOUBLE;
+ buffer_len = 8;
+ break;
+ // other
+ case SQLDT_STRING:
+ case SQLDT_ENUM:
+ bind->buffer_type = MYSQL_TYPE_STRING;
+ break;
+ case SQLDT_BLOB:
+ bind->buffer_type = MYSQL_TYPE_BLOB;
+ break;
+ default:
+ ShowDebug("Sql_P_BindSqlDataType: unsupported buffer type (%d)\n", buffer_type);
+ return SQL_ERROR;
+ }
+ bind->buffer = buffer;
+ bind->buffer_length = (unsigned long)buffer_len;
+ bind->length = out_length;
+ bind->is_null = (my_bool *)out_is_null;
+ return SQL_SUCCESS;
}
@@ -521,38 +526,37 @@ static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type,
/// Prints debug information about a field (type and length).
///
/// @private
-static void Sql_P_ShowDebugMysqlFieldInfo(const char* prefix, enum enum_field_types type, int is_unsigned, unsigned long length, const char* length_postfix)
-{
- const char* sign = (is_unsigned ? "UNSIGNED " : "");
- const char* type_string;
- switch( type )
- {
- default:
- ShowDebug("%stype=%s%u, length=%d\n", prefix, sign, type, length);
- return;
+static void Sql_P_ShowDebugMysqlFieldInfo(const char *prefix, enum enum_field_types type, int is_unsigned, unsigned long length, const char *length_postfix)
+{
+ const char *sign = (is_unsigned ? "UNSIGNED " : "");
+ const char *type_string;
+ switch (type) {
+ default:
+ ShowDebug("%stype=%s%u, length=%d\n", prefix, sign, type, length);
+ return;
#define SHOW_DEBUG_OF(x) case x: type_string = #x; break
- SHOW_DEBUG_OF(MYSQL_TYPE_TINY);
- SHOW_DEBUG_OF(MYSQL_TYPE_SHORT);
- SHOW_DEBUG_OF(MYSQL_TYPE_LONG);
- SHOW_DEBUG_OF(MYSQL_TYPE_INT24);
- SHOW_DEBUG_OF(MYSQL_TYPE_LONGLONG);
- SHOW_DEBUG_OF(MYSQL_TYPE_DECIMAL);
- SHOW_DEBUG_OF(MYSQL_TYPE_FLOAT);
- SHOW_DEBUG_OF(MYSQL_TYPE_DOUBLE);
- SHOW_DEBUG_OF(MYSQL_TYPE_TIMESTAMP);
- SHOW_DEBUG_OF(MYSQL_TYPE_DATE);
- SHOW_DEBUG_OF(MYSQL_TYPE_TIME);
- SHOW_DEBUG_OF(MYSQL_TYPE_DATETIME);
- SHOW_DEBUG_OF(MYSQL_TYPE_YEAR);
- SHOW_DEBUG_OF(MYSQL_TYPE_STRING);
- SHOW_DEBUG_OF(MYSQL_TYPE_VAR_STRING);
- SHOW_DEBUG_OF(MYSQL_TYPE_BLOB);
- SHOW_DEBUG_OF(MYSQL_TYPE_SET);
- SHOW_DEBUG_OF(MYSQL_TYPE_ENUM);
- SHOW_DEBUG_OF(MYSQL_TYPE_NULL);
+ SHOW_DEBUG_OF(MYSQL_TYPE_TINY);
+ SHOW_DEBUG_OF(MYSQL_TYPE_SHORT);
+ SHOW_DEBUG_OF(MYSQL_TYPE_LONG);
+ SHOW_DEBUG_OF(MYSQL_TYPE_INT24);
+ SHOW_DEBUG_OF(MYSQL_TYPE_LONGLONG);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DECIMAL);
+ SHOW_DEBUG_OF(MYSQL_TYPE_FLOAT);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DOUBLE);
+ SHOW_DEBUG_OF(MYSQL_TYPE_TIMESTAMP);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DATE);
+ SHOW_DEBUG_OF(MYSQL_TYPE_TIME);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DATETIME);
+ SHOW_DEBUG_OF(MYSQL_TYPE_YEAR);
+ SHOW_DEBUG_OF(MYSQL_TYPE_STRING);
+ SHOW_DEBUG_OF(MYSQL_TYPE_VAR_STRING);
+ SHOW_DEBUG_OF(MYSQL_TYPE_BLOB);
+ SHOW_DEBUG_OF(MYSQL_TYPE_SET);
+ SHOW_DEBUG_OF(MYSQL_TYPE_ENUM);
+ SHOW_DEBUG_OF(MYSQL_TYPE_NULL);
#undef SHOW_DEBUG_TYPE_OF
- }
- ShowDebug("%stype=%s%s, length=%d%s\n", prefix, sign, type_string, length, length_postfix);
+ }
+ ShowDebug("%stype=%s%s, length=%d%s\n", prefix, sign, type_string, length, length_postfix);
}
@@ -560,389 +564,369 @@ static void Sql_P_ShowDebugMysqlFieldInfo(const char* prefix, enum enum_field_ty
/// Reports debug information about a truncated column.
///
/// @private
-static void SqlStmt_P_ShowDebugTruncatedColumn(SqlStmt* self, size_t i)
+static void SqlStmt_P_ShowDebugTruncatedColumn(SqlStmt *self, size_t i)
{
- MYSQL_RES* meta;
- MYSQL_FIELD* field;
- MYSQL_BIND* column;
+ MYSQL_RES *meta;
+ MYSQL_FIELD *field;
+ MYSQL_BIND *column;
- meta = mysql_stmt_result_metadata(self->stmt);
- field = mysql_fetch_field_direct(meta, (unsigned int)i);
- ShowSQL("DB error - data of field '%s' was truncated.\n", field->name);
- ShowDebug("column - %lu\n", (unsigned long)i);
- Sql_P_ShowDebugMysqlFieldInfo("data - ", field->type, field->flags&UNSIGNED_FLAG, self->column_lengths[i].length, "");
- column = &self->columns[i];
- if( column->buffer_type == MYSQL_TYPE_STRING )
- Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "+1(nul-terminator)");
- else
- Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "");
- mysql_free_result(meta);
+ meta = mysql_stmt_result_metadata(self->stmt);
+ field = mysql_fetch_field_direct(meta, (unsigned int)i);
+ ShowSQL("DB error - data of field '%s' was truncated.\n", field->name);
+ ShowDebug("column - %lu\n", (unsigned long)i);
+ Sql_P_ShowDebugMysqlFieldInfo("data - ", field->type, field->flags&UNSIGNED_FLAG, self->column_lengths[i].length, "");
+ column = &self->columns[i];
+ if (column->buffer_type == MYSQL_TYPE_STRING)
+ Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "+1(nul-terminator)");
+ else
+ Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "");
+ mysql_free_result(meta);
}
/// Allocates and initializes a new SqlStmt handle.
-SqlStmt* SqlStmt_Malloc(Sql* sql)
+SqlStmt *SqlStmt_Malloc(Sql *sql)
{
- SqlStmt* self;
- MYSQL_STMT* stmt;
+ SqlStmt *self;
+ MYSQL_STMT *stmt;
- if( sql == NULL )
- return NULL;
+ if (sql == NULL)
+ return NULL;
- stmt = mysql_stmt_init(&sql->handle);
- if( stmt == NULL )
- {
- ShowSQL("DB error - %s\n", mysql_error(&sql->handle));
- return NULL;
- }
- CREATE(self, SqlStmt, 1);
- StringBuf_Init(&self->buf);
- self->stmt = stmt;
- self->params = NULL;
- self->columns = NULL;
- self->column_lengths = NULL;
- self->max_params = 0;
- self->max_columns = 0;
- self->bind_params = false;
- self->bind_columns = false;
+ stmt = mysql_stmt_init(&sql->handle);
+ if (stmt == NULL) {
+ ShowSQL("DB error - %s\n", mysql_error(&sql->handle));
+ return NULL;
+ }
+ CREATE(self, SqlStmt, 1);
+ StringBuf_Init(&self->buf);
+ self->stmt = stmt;
+ self->params = NULL;
+ self->columns = NULL;
+ self->column_lengths = NULL;
+ self->max_params = 0;
+ self->max_columns = 0;
+ self->bind_params = false;
+ self->bind_columns = false;
- return self;
+ return self;
}
/// Prepares the statement.
-int SqlStmt_Prepare(SqlStmt* self, const char* query, ...)
+int SqlStmt_Prepare(SqlStmt *self, const char *query, ...)
{
- int res;
- va_list args;
+ int res;
+ va_list args;
- va_start(args, query);
- res = SqlStmt_PrepareV(self, query, args);
- va_end(args);
+ va_start(args, query);
+ res = SqlStmt_PrepareV(self, query, args);
+ va_end(args);
- return res;
+ return res;
}
/// Prepares the statement.
-int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args)
+int SqlStmt_PrepareV(SqlStmt *self, const char *query, va_list args)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- SqlStmt_FreeResult(self);
- StringBuf_Clear(&self->buf);
- StringBuf_Vprintf(&self->buf, query, args);
- if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
- {
- ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
- return SQL_ERROR;
- }
- self->bind_params = false;
+ SqlStmt_FreeResult(self);
+ StringBuf_Clear(&self->buf);
+ StringBuf_Vprintf(&self->buf, query, args);
+ if (mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf))) {
+ ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
+ return SQL_ERROR;
+ }
+ self->bind_params = false;
- return SQL_SUCCESS;
+ return SQL_SUCCESS;
}
/// Prepares the statement.
-int SqlStmt_PrepareStr(SqlStmt* self, const char* query)
+int SqlStmt_PrepareStr(SqlStmt *self, const char *query)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- SqlStmt_FreeResult(self);
- StringBuf_Clear(&self->buf);
- StringBuf_AppendStr(&self->buf, query);
- if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) )
- {
- ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
- return SQL_ERROR;
- }
- self->bind_params = false;
+ SqlStmt_FreeResult(self);
+ StringBuf_Clear(&self->buf);
+ StringBuf_AppendStr(&self->buf, query);
+ if (mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf))) {
+ ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
+ return SQL_ERROR;
+ }
+ self->bind_params = false;
- return SQL_SUCCESS;
+ return SQL_SUCCESS;
}
/// Returns the number of parameters in the prepared statement.
-size_t SqlStmt_NumParams(SqlStmt* self)
+size_t SqlStmt_NumParams(SqlStmt *self)
{
- if( self )
- return (size_t)mysql_stmt_param_count(self->stmt);
- else
- return 0;
+ if (self)
+ return (size_t)mysql_stmt_param_count(self->stmt);
+ else
+ return 0;
}
/// Binds a parameter to a buffer.
-int SqlStmt_BindParam(SqlStmt* self, size_t idx, enum SqlDataType buffer_type, void* buffer, size_t buffer_len)
+int SqlStmt_BindParam(SqlStmt *self, size_t idx, enum SqlDataType buffer_type, void *buffer, size_t buffer_len)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- if( !self->bind_params )
- {// initialize the bindings
- size_t i;
- size_t count;
+ if (!self->bind_params) {
+ // initialize the bindings
+ size_t i;
+ size_t count;
- count = SqlStmt_NumParams(self);
- if( self->max_params < count )
- {
- self->max_params = count;
- RECREATE(self->params, MYSQL_BIND, count);
- }
- memset(self->params, 0, count*sizeof(MYSQL_BIND));
- for( i = 0; i < count; ++i )
- self->params[i].buffer_type = MYSQL_TYPE_NULL;
- self->bind_params = true;
- }
- if( idx < self->max_params )
- return Sql_P_BindSqlDataType(self->params+idx, buffer_type, buffer, buffer_len, NULL, NULL);
- else
- return SQL_SUCCESS;// out of range - ignore
+ count = SqlStmt_NumParams(self);
+ if (self->max_params < count) {
+ self->max_params = count;
+ RECREATE(self->params, MYSQL_BIND, count);
+ }
+ memset(self->params, 0, count*sizeof(MYSQL_BIND));
+ for (i = 0; i < count; ++i)
+ self->params[i].buffer_type = MYSQL_TYPE_NULL;
+ self->bind_params = true;
+ }
+ if (idx < self->max_params)
+ return Sql_P_BindSqlDataType(self->params+idx, buffer_type, buffer, buffer_len, NULL, NULL);
+ else
+ return SQL_SUCCESS;// out of range - ignore
}
/// Executes the prepared statement.
-int SqlStmt_Execute(SqlStmt* self)
+int SqlStmt_Execute(SqlStmt *self)
{
- if( self == NULL )
- return SQL_ERROR;
+ if (self == NULL)
+ return SQL_ERROR;
- SqlStmt_FreeResult(self);
- if( (self->bind_params && mysql_stmt_bind_param(self->stmt, self->params)) ||
- mysql_stmt_execute(self->stmt) )
- {
- ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
- return SQL_ERROR;
- }
- self->bind_columns = false;
- if( mysql_stmt_store_result(self->stmt) )// store all the data
- {
- ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
- return SQL_ERROR;
- }
+ SqlStmt_FreeResult(self);
+ if ((self->bind_params && mysql_stmt_bind_param(self->stmt, self->params)) ||
+ mysql_stmt_execute(self->stmt)) {
+ ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
+ return SQL_ERROR;
+ }
+ self->bind_columns = false;
+ if (mysql_stmt_store_result(self->stmt)) { // store all the data
+ ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
+ return SQL_ERROR;
+ }
- return SQL_SUCCESS;
+ return SQL_SUCCESS;
}
/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement.
-uint64 SqlStmt_LastInsertId(SqlStmt* self)
+uint64 SqlStmt_LastInsertId(SqlStmt *self)
{
- if( self )
- return (uint64)mysql_stmt_insert_id(self->stmt);
- else
- return 0;
+ if (self)
+ return (uint64)mysql_stmt_insert_id(self->stmt);
+ else
+ return 0;
}
/// Returns the number of columns in each row of the result.
-size_t SqlStmt_NumColumns(SqlStmt* self)
+size_t SqlStmt_NumColumns(SqlStmt *self)
{
- if( self )
- return (size_t)mysql_stmt_field_count(self->stmt);
- else
- return 0;
+ if (self)
+ return (size_t)mysql_stmt_field_count(self->stmt);
+ else
+ return 0;
}
/// Binds the result of a column to a buffer.
-int SqlStmt_BindColumn(SqlStmt* self, size_t idx, enum SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null)
-{
- if( self == NULL )
- return SQL_ERROR;
-
- if( buffer_type == SQLDT_STRING || buffer_type == SQLDT_ENUM )
- {
- if( buffer_len < 1 )
- {
- ShowDebug("SqlStmt_BindColumn: buffer_len(%d) is too small, no room for the nul-terminator\n", buffer_len);
- return SQL_ERROR;
- }
- --buffer_len;// nul-terminator
- }
- if( !self->bind_columns )
- {// initialize the bindings
- size_t i;
- size_t cols;
-
- cols = SqlStmt_NumColumns(self);
- if( self->max_columns < cols )
- {
- self->max_columns = cols;
- RECREATE(self->columns, MYSQL_BIND, cols);
- RECREATE(self->column_lengths, s_column_length, cols);
- }
- memset(self->columns, 0, cols*sizeof(MYSQL_BIND));
- memset(self->column_lengths, 0, cols*sizeof(s_column_length));
- for( i = 0; i < cols; ++i )
- self->columns[i].buffer_type = MYSQL_TYPE_NULL;
- self->bind_columns = true;
- }
- if( idx < self->max_columns )
- {
- self->column_lengths[idx].out_length = out_length;
- return Sql_P_BindSqlDataType(self->columns+idx, buffer_type, buffer, buffer_len, &self->column_lengths[idx].length, out_is_null);
- }
- else
- {
- return SQL_SUCCESS;// out of range - ignore
- }
+int SqlStmt_BindColumn(SqlStmt *self, size_t idx, enum SqlDataType buffer_type, void *buffer, size_t buffer_len, uint32 *out_length, int8 *out_is_null)
+{
+ if (self == NULL)
+ return SQL_ERROR;
+
+ if (buffer_type == SQLDT_STRING || buffer_type == SQLDT_ENUM) {
+ if (buffer_len < 1) {
+ ShowDebug("SqlStmt_BindColumn: buffer_len(%d) is too small, no room for the nul-terminator\n", buffer_len);
+ return SQL_ERROR;
+ }
+ --buffer_len;// nul-terminator
+ }
+ if (!self->bind_columns) {
+ // initialize the bindings
+ size_t i;
+ size_t cols;
+
+ cols = SqlStmt_NumColumns(self);
+ if (self->max_columns < cols) {
+ self->max_columns = cols;
+ RECREATE(self->columns, MYSQL_BIND, cols);
+ RECREATE(self->column_lengths, s_column_length, cols);
+ }
+ memset(self->columns, 0, cols*sizeof(MYSQL_BIND));
+ memset(self->column_lengths, 0, cols*sizeof(s_column_length));
+ for (i = 0; i < cols; ++i)
+ self->columns[i].buffer_type = MYSQL_TYPE_NULL;
+ self->bind_columns = true;
+ }
+ if (idx < self->max_columns) {
+ self->column_lengths[idx].out_length = out_length;
+ return Sql_P_BindSqlDataType(self->columns+idx, buffer_type, buffer, buffer_len, &self->column_lengths[idx].length, out_is_null);
+ } else {
+ return SQL_SUCCESS;// out of range - ignore
+ }
}
/// Returns the number of rows in the result.
-uint64 SqlStmt_NumRows(SqlStmt* self)
+uint64 SqlStmt_NumRows(SqlStmt *self)
{
- if( self )
- return (uint64)mysql_stmt_num_rows(self->stmt);
- else
- return 0;
+ if (self)
+ return (uint64)mysql_stmt_num_rows(self->stmt);
+ else
+ return 0;
}
/// Fetches the next row.
-int SqlStmt_NextRow(SqlStmt* self)
-{
- int err;
- size_t i;
- size_t cols;
- MYSQL_BIND* column;
- unsigned long length;
-
- if( self == NULL )
- return SQL_ERROR;
-
- // bind columns
- if( self->bind_columns && mysql_stmt_bind_result(self->stmt, self->columns) )
- err = 1;// error binding columns
- else
- err = mysql_stmt_fetch(self->stmt);// fetch row
-
- // check for errors
- if( err == MYSQL_NO_DATA )
- return SQL_NO_DATA;
+int SqlStmt_NextRow(SqlStmt *self)
+{
+ int err;
+ size_t i;
+ size_t cols;
+ MYSQL_BIND *column;
+ unsigned long length;
+
+ if (self == NULL)
+ return SQL_ERROR;
+
+ // bind columns
+ if (self->bind_columns && mysql_stmt_bind_result(self->stmt, self->columns))
+ err = 1;// error binding columns
+ else
+ err = mysql_stmt_fetch(self->stmt);// fetch row
+
+ // check for errors
+ if (err == MYSQL_NO_DATA)
+ return SQL_NO_DATA;
#if defined(MYSQL_DATA_TRUNCATED)
- // MySQL 5.0/5.1 defines and returns MYSQL_DATA_TRUNCATED [FlavioJS]
- if( err == MYSQL_DATA_TRUNCATED )
- {
- my_bool truncated;
-
- if( !self->bind_columns )
- {
- ShowSQL("DB error - data truncated (unknown source, columns are not bound)\n");
- return SQL_ERROR;
- }
-
- // find truncated column
- cols = SqlStmt_NumColumns(self);
- for( i = 0; i < cols; ++i )
- {
- column = &self->columns[i];
- column->error = &truncated;
- mysql_stmt_fetch_column(self->stmt, column, (unsigned int)i, 0);
- column->error = NULL;
- if( truncated )
- {// report truncated column
- SqlStmt_P_ShowDebugTruncatedColumn(self, i);
- return SQL_ERROR;
- }
- }
- ShowSQL("DB error - data truncated (unknown source)\n");
- return SQL_ERROR;
- }
+ // MySQL 5.0/5.1 defines and returns MYSQL_DATA_TRUNCATED [FlavioJS]
+ if (err == MYSQL_DATA_TRUNCATED) {
+ my_bool truncated;
+
+ if (!self->bind_columns) {
+ ShowSQL("DB error - data truncated (unknown source, columns are not bound)\n");
+ return SQL_ERROR;
+ }
+
+ // find truncated column
+ cols = SqlStmt_NumColumns(self);
+ for (i = 0; i < cols; ++i) {
+ column = &self->columns[i];
+ column->error = &truncated;
+ mysql_stmt_fetch_column(self->stmt, column, (unsigned int)i, 0);
+ column->error = NULL;
+ if (truncated) {
+ // report truncated column
+ SqlStmt_P_ShowDebugTruncatedColumn(self, i);
+ return SQL_ERROR;
+ }
+ }
+ ShowSQL("DB error - data truncated (unknown source)\n");
+ return SQL_ERROR;
+ }
#endif
- if( err )
- {
- ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
- return SQL_ERROR;
- }
-
- // propagate column lengths and clear unused parts of string/enum/blob buffers
- cols = SqlStmt_NumColumns(self);
- for( i = 0; i < cols; ++i )
- {
- length = self->column_lengths[i].length;
- column = &self->columns[i];
+ if (err) {
+ ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt));
+ return SQL_ERROR;
+ }
+
+ // propagate column lengths and clear unused parts of string/enum/blob buffers
+ cols = SqlStmt_NumColumns(self);
+ for (i = 0; i < cols; ++i) {
+ length = self->column_lengths[i].length;
+ column = &self->columns[i];
#if !defined(MYSQL_DATA_TRUNCATED)
- // MySQL 4.1/(below?) returns success even if data is truncated, so we test truncation manually [FlavioJS]
- if( column->buffer_length < length )
- {// report truncated column
- if( column->buffer_type == MYSQL_TYPE_STRING || column->buffer_type == MYSQL_TYPE_BLOB )
- {// string/enum/blob column
- SqlStmt_P_ShowDebugTruncatedColumn(self, i);
- return SQL_ERROR;
- }
- // FIXME numeric types and null [FlavioJS]
- }
+ // MySQL 4.1/(below?) returns success even if data is truncated, so we test truncation manually [FlavioJS]
+ if (column->buffer_length < length) {
+ // report truncated column
+ if (column->buffer_type == MYSQL_TYPE_STRING || column->buffer_type == MYSQL_TYPE_BLOB) {
+ // string/enum/blob column
+ SqlStmt_P_ShowDebugTruncatedColumn(self, i);
+ return SQL_ERROR;
+ }
+ // FIXME numeric types and null [FlavioJS]
+ }
#endif
- if( self->column_lengths[i].out_length )
- *self->column_lengths[i].out_length = (uint32)length;
- if( column->buffer_type == MYSQL_TYPE_STRING )
- {// clear unused part of the string/enum buffer (and nul-terminate)
- memset((char*)column->buffer + length, 0, column->buffer_length - length + 1);
- }
- else if( column->buffer_type == MYSQL_TYPE_BLOB && length < column->buffer_length )
- {// clear unused part of the blob buffer
- memset((char*)column->buffer + length, 0, column->buffer_length - length);
- }
- }
+ if (self->column_lengths[i].out_length)
+ *self->column_lengths[i].out_length = (uint32)length;
+ if (column->buffer_type == MYSQL_TYPE_STRING) {
+ // clear unused part of the string/enum buffer (and nul-terminate)
+ memset((char *)column->buffer + length, 0, column->buffer_length - length + 1);
+ } else if (column->buffer_type == MYSQL_TYPE_BLOB && length < column->buffer_length) {
+ // clear unused part of the blob buffer
+ memset((char *)column->buffer + length, 0, column->buffer_length - length);
+ }
+ }
- return SQL_SUCCESS;
+ return SQL_SUCCESS;
}
/// Frees the result of the statement execution.
-void SqlStmt_FreeResult(SqlStmt* self)
+void SqlStmt_FreeResult(SqlStmt *self)
{
- if( self )
- mysql_stmt_free_result(self->stmt);
+ if (self)
+ mysql_stmt_free_result(self->stmt);
}
/// Shows debug information (with statement).
-void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned long debug_line)
+void SqlStmt_ShowDebug_(SqlStmt *self, const char *debug_file, const unsigned long debug_line)
{
- if( self == NULL )
- ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line);
- else if( StringBuf_Length(&self->buf) > 0 )
- ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf));
- else
- ShowDebug("at %s:%lu\n", debug_file, debug_line);
+ if (self == NULL)
+ ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line);
+ else if (StringBuf_Length(&self->buf) > 0)
+ ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf));
+ else
+ ShowDebug("at %s:%lu\n", debug_file, debug_line);
}
/// Frees a SqlStmt returned by SqlStmt_Malloc.
-void SqlStmt_Free(SqlStmt* self)
-{
- if( self )
- {
- SqlStmt_FreeResult(self);
- StringBuf_Destroy(&self->buf);
- mysql_stmt_close(self->stmt);
- if( self->params )
- aFree(self->params);
- if( self->columns )
- {
- aFree(self->columns);
- aFree(self->column_lengths);
- }
- aFree(self);
- }
+void SqlStmt_Free(SqlStmt *self)
+{
+ if (self) {
+ SqlStmt_FreeResult(self);
+ StringBuf_Destroy(&self->buf);
+ mysql_stmt_close(self->stmt);
+ if (self->params)
+ aFree(self->params);
+ if (self->columns) {
+ aFree(self->columns);
+ aFree(self->column_lengths);
+ }
+ aFree(self);
+ }
}
diff --git a/src/common/sql.h b/src/common/sql.h
index 898e2c778..4534061e0 100644
--- a/src/common/sql.h
+++ b/src/common/sql.h
@@ -21,39 +21,38 @@
/// Data type identifier.
/// String, enum and blob data types need the buffer length specified.
-enum SqlDataType
-{
- SQLDT_NULL,
- // fixed size
- SQLDT_INT8,
- SQLDT_INT16,
- SQLDT_INT32,
- SQLDT_INT64,
- SQLDT_UINT8,
- SQLDT_UINT16,
- SQLDT_UINT32,
- SQLDT_UINT64,
- // platform dependent size
- SQLDT_CHAR,
- SQLDT_SHORT,
- SQLDT_INT,
- SQLDT_LONG,
- SQLDT_LONGLONG,
- SQLDT_UCHAR,
- SQLDT_USHORT,
- SQLDT_UINT,
- SQLDT_ULONG,
- SQLDT_ULONGLONG,
- // floating point
- SQLDT_FLOAT,
- SQLDT_DOUBLE,
- // other
- SQLDT_STRING,
- SQLDT_ENUM,
- // Note: An ENUM is a string with restricted values. When an invalid value
- // is inserted, it is saved as an empty string (numerical value 0).
- SQLDT_BLOB,
- SQLDT_LASTID
+enum SqlDataType {
+ SQLDT_NULL,
+ // fixed size
+ SQLDT_INT8,
+ SQLDT_INT16,
+ SQLDT_INT32,
+ SQLDT_INT64,
+ SQLDT_UINT8,
+ SQLDT_UINT16,
+ SQLDT_UINT32,
+ SQLDT_UINT64,
+ // platform dependent size
+ SQLDT_CHAR,
+ SQLDT_SHORT,
+ SQLDT_INT,
+ SQLDT_LONG,
+ SQLDT_LONGLONG,
+ SQLDT_UCHAR,
+ SQLDT_USHORT,
+ SQLDT_UINT,
+ SQLDT_ULONG,
+ SQLDT_ULONGLONG,
+ // floating point
+ SQLDT_FLOAT,
+ SQLDT_DOUBLE,
+ // other
+ SQLDT_STRING,
+ SQLDT_ENUM,
+ // Note: An ENUM is a string with restricted values. When an invalid value
+ // is inserted, it is saved as an empty string (numerical value 0).
+ SQLDT_BLOB,
+ SQLDT_LASTID
};
struct Sql;// Sql handle (private access)
@@ -65,14 +64,14 @@ typedef struct SqlStmt SqlStmt;
/// Allocates and initializes a new Sql handle.
-struct Sql* Sql_Malloc(void);
+struct Sql *Sql_Malloc(void);
/// Establishes a connection.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db);
+int Sql_Connect(Sql *self, const char *user, const char *passwd, const char *host, uint16 port, const char *db);
@@ -80,7 +79,7 @@ int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* hos
/// Retrieves the timeout of the connection.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_GetTimeout(Sql* self, uint32* out_timeout);
+int Sql_GetTimeout(Sql *self, uint32 *out_timeout);
@@ -88,7 +87,7 @@ int Sql_GetTimeout(Sql* self, uint32* out_timeout);
/// Retrieves the name of the columns of a table into out_buf, with the separator after each name.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_len, char sep);
+int Sql_GetColumnNames(Sql *self, const char *table, char *out_buf, size_t buf_len, char sep);
@@ -96,14 +95,14 @@ int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_l
/// Changes the encoding of the connection.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_SetEncoding(Sql* self, const char* encoding);
+int Sql_SetEncoding(Sql *self, const char *encoding);
/// Pings the connection.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_Ping(Sql* self);
+int Sql_Ping(Sql *self);
@@ -111,7 +110,7 @@ int Sql_Ping(Sql* self);
/// The output buffer must be at least strlen(from)*2+1 in size.
///
/// @return The size of the escaped string
-size_t Sql_EscapeString(Sql* self, char* out_to, const char* from);
+size_t Sql_EscapeString(Sql *self, char *out_to, const char *from);
@@ -119,7 +118,7 @@ size_t Sql_EscapeString(Sql* self, char* out_to, const char* from);
/// The output buffer must be at least from_len*2+1 in size.
///
/// @return The size of the escaped string
-size_t Sql_EscapeStringLen(Sql* self, char* out_to, const char* from, size_t from_len);
+size_t Sql_EscapeStringLen(Sql *self, char *out_to, const char *from, size_t from_len);
@@ -128,7 +127,7 @@ size_t Sql_EscapeStringLen(Sql* self, char* out_to, const char* from, size_t fro
/// The query is constructed as if it was sprintf.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_Query(Sql* self, const char* query, ...);
+int Sql_Query(Sql *self, const char *query, ...);
@@ -137,7 +136,7 @@ int Sql_Query(Sql* self, const char* query, ...);
/// The query is constructed as if it was svprintf.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_QueryV(Sql* self, const char* query, va_list args);
+int Sql_QueryV(Sql *self, const char *query, va_list args);
@@ -146,28 +145,28 @@ int Sql_QueryV(Sql* self, const char* query, va_list args);
/// The query is used directly.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_QueryStr(Sql* self, const char* query);
+int Sql_QueryStr(Sql *self, const char *query);
/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query.
///
/// @return Value of the auto-increment column
-uint64 Sql_LastInsertId(Sql* self);
+uint64 Sql_LastInsertId(Sql *self);
/// Returns the number of columns in each row of the result.
///
/// @return Number of columns
-uint32 Sql_NumColumns(Sql* self);
+uint32 Sql_NumColumns(Sql *self);
/// Returns the number of rows in the result.
///
/// @return Number of rows
-uint64 Sql_NumRows(Sql* self);
+uint64 Sql_NumRows(Sql *self);
@@ -175,7 +174,7 @@ uint64 Sql_NumRows(Sql* self);
/// The data of the previous row is no longer valid.
///
/// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA
-int Sql_NextRow(Sql* self);
+int Sql_NextRow(Sql *self);
@@ -183,12 +182,12 @@ int Sql_NextRow(Sql* self);
/// The data remains valid until the next row is fetched or the result is freed.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len);
+int Sql_GetData(Sql *self, size_t col, char **out_buf, size_t *out_len);
/// Frees the result of the query.
-void Sql_FreeResult(Sql* self);
+void Sql_FreeResult(Sql *self);
@@ -198,22 +197,22 @@ void Sql_FreeResult(Sql* self);
#define Sql_ShowDebug(self) Sql_ShowDebug_(self, __FILE__, __LINE__)
#endif
/// Shows debug information (last query).
-void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug_line);
+void Sql_ShowDebug_(Sql *self, const char *debug_file, const unsigned long debug_line);
/// Frees a Sql handle returned by Sql_Malloc.
-void Sql_Free(Sql* self);
+void Sql_Free(Sql *self);
///////////////////////////////////////////////////////////////////////////////
// Prepared Statements
///////////////////////////////////////////////////////////////////////////////
-// Parameters are placed in the statement by embedding question mark ('?')
+// Parameters are placed in the statement by embedding question mark ('?')
// characters into the query at the appropriate positions.
// The markers are legal only in places where they represent data.
-// The markers cannot be inside quotes. Quotes will be added automatically
+// The markers cannot be inside quotes. Quotes will be added automatically
// when they are required.
//
// example queries with parameters:
@@ -227,7 +226,7 @@ void Sql_Free(Sql* self);
/// Queries in Sql and SqlStmt are independent and don't affect each other.
///
/// @return SqlStmt handle or NULL if an error occured
-struct SqlStmt* SqlStmt_Malloc(Sql* sql);
+struct SqlStmt *SqlStmt_Malloc(Sql *sql);
@@ -236,7 +235,7 @@ struct SqlStmt* SqlStmt_Malloc(Sql* sql);
/// The query is constructed as if it was sprintf.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_Prepare(SqlStmt* self, const char* query, ...);
+int SqlStmt_Prepare(SqlStmt *self, const char *query, ...);
@@ -245,7 +244,7 @@ int SqlStmt_Prepare(SqlStmt* self, const char* query, ...);
/// The query is constructed as if it was svprintf.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args);
+int SqlStmt_PrepareV(SqlStmt *self, const char *query, va_list args);
@@ -254,14 +253,14 @@ int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args);
/// The query is used directly.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_PrepareStr(SqlStmt* self, const char* query);
+int SqlStmt_PrepareStr(SqlStmt *self, const char *query);
/// Returns the number of parameters in the prepared statement.
///
/// @return Number or paramenters
-size_t SqlStmt_NumParams(SqlStmt* self);
+size_t SqlStmt_NumParams(SqlStmt *self);
@@ -270,7 +269,7 @@ size_t SqlStmt_NumParams(SqlStmt* self);
/// All parameters should have bindings.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_BindParam(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len);
+int SqlStmt_BindParam(SqlStmt *self, size_t idx, SqlDataType buffer_type, void *buffer, size_t buffer_len);
@@ -278,38 +277,38 @@ int SqlStmt_BindParam(SqlStmt* self, size_t idx, SqlDataType buffer_type, void*
/// Any previous result is freed and all column bindings are removed.
///
/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_Execute(SqlStmt* self);
+int SqlStmt_Execute(SqlStmt *self);
/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement.
///
/// @return Value of the auto-increment column
-uint64 SqlStmt_LastInsertId(SqlStmt* self);
+uint64 SqlStmt_LastInsertId(SqlStmt *self);
/// Returns the number of columns in each row of the result.
///
/// @return Number of columns
-size_t SqlStmt_NumColumns(SqlStmt* self);
+size_t SqlStmt_NumColumns(SqlStmt *self);
/// Binds the result of a column to a buffer.
/// The buffer will be filled with data when the next row is fetched.
-/// For string/enum buffer types there has to be enough space for the data
+/// For string/enum buffer types there has to be enough space for the data
/// and the nul-terminator (an extra byte).
///
/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_BindColumn(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null);
+int SqlStmt_BindColumn(SqlStmt *self, size_t idx, SqlDataType buffer_type, void *buffer, size_t buffer_len, uint32 *out_length, int8 *out_is_null);
/// Returns the number of rows in the result.
///
/// @return Number of rows
-uint64 SqlStmt_NumRows(SqlStmt* self);
+uint64 SqlStmt_NumRows(SqlStmt *self);
@@ -317,12 +316,12 @@ uint64 SqlStmt_NumRows(SqlStmt* self);
/// All column bindings will be filled with data.
///
/// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA
-int SqlStmt_NextRow(SqlStmt* self);
+int SqlStmt_NextRow(SqlStmt *self);
/// Frees the result of the statement execution.
-void SqlStmt_FreeResult(SqlStmt* self);
+void SqlStmt_FreeResult(SqlStmt *self);
@@ -332,12 +331,12 @@ void SqlStmt_FreeResult(SqlStmt* self);
#define SqlStmt_ShowDebug(self) SqlStmt_ShowDebug_(self, __FILE__, __LINE__)
#endif
/// Shows debug information (with statement).
-void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned long debug_line);
+void SqlStmt_ShowDebug_(SqlStmt *self, const char *debug_file, const unsigned long debug_line);
/// Frees a SqlStmt returned by SqlStmt_Malloc.
-void SqlStmt_Free(SqlStmt* self);
+void SqlStmt_Free(SqlStmt *self);
diff --git a/src/common/strlib.c b/src/common/strlib.c
index dfacbf136..89aac3b40 100644
--- a/src/common/strlib.c
+++ b/src/common/strlib.c
@@ -14,360 +14,348 @@
#define J_MAX_MALLOC_SIZE 65535
// escapes a string in-place (' -> \' , \ -> \\ , % -> _)
-char* jstrescape (char* pt)
+char *jstrescape(char *pt)
{
- //copy from here
- char *ptr;
- int i = 0, j = 0;
-
- //copy string to temporary
- CREATE(ptr, char, J_MAX_MALLOC_SIZE);
- strcpy(ptr,pt);
-
- while (ptr[i] != '\0') {
- switch (ptr[i]) {
- case '\'':
- pt[j++] = '\\';
- pt[j++] = ptr[i++];
- break;
- case '\\':
- pt[j++] = '\\';
- pt[j++] = ptr[i++];
- break;
- case '%':
- pt[j++] = '_'; i++;
- break;
- default:
- pt[j++] = ptr[i++];
- }
- }
- pt[j++] = '\0';
- aFree(ptr);
- return pt;
+ //copy from here
+ char *ptr;
+ int i = 0, j = 0;
+
+ //copy string to temporary
+ CREATE(ptr, char, J_MAX_MALLOC_SIZE);
+ strcpy(ptr,pt);
+
+ while (ptr[i] != '\0') {
+ switch (ptr[i]) {
+ case '\'':
+ pt[j++] = '\\';
+ pt[j++] = ptr[i++];
+ break;
+ case '\\':
+ pt[j++] = '\\';
+ pt[j++] = ptr[i++];
+ break;
+ case '%':
+ pt[j++] = '_';
+ i++;
+ break;
+ default:
+ pt[j++] = ptr[i++];
+ }
+ }
+ pt[j++] = '\0';
+ aFree(ptr);
+ return pt;
}
// escapes a string into a provided buffer
-char* jstrescapecpy (char* pt, const char* spt)
+char *jstrescapecpy(char *pt, const char *spt)
{
- //copy from here
- //WARNING: Target string pt should be able to hold strlen(spt)*2, as each time
- //a escape character is found, the target's final length increases! [Skotlex]
- int i =0, j=0;
-
- if (!spt) { //Return an empty string [Skotlex]
- pt[0] = '\0';
- return &pt[0];
- }
-
- while (spt[i] != '\0') {
- switch (spt[i]) {
- case '\'':
- pt[j++] = '\\';
- pt[j++] = spt[i++];
- break;
- case '\\':
- pt[j++] = '\\';
- pt[j++] = spt[i++];
- break;
- case '%':
- pt[j++] = '_'; i++;
- break;
- default:
- pt[j++] = spt[i++];
- }
- }
- pt[j++] = '\0';
- return &pt[0];
+ //copy from here
+ //WARNING: Target string pt should be able to hold strlen(spt)*2, as each time
+ //a escape character is found, the target's final length increases! [Skotlex]
+ int i =0, j=0;
+
+ if (!spt) { //Return an empty string [Skotlex]
+ pt[0] = '\0';
+ return &pt[0];
+ }
+
+ while (spt[i] != '\0') {
+ switch (spt[i]) {
+ case '\'':
+ pt[j++] = '\\';
+ pt[j++] = spt[i++];
+ break;
+ case '\\':
+ pt[j++] = '\\';
+ pt[j++] = spt[i++];
+ break;
+ case '%':
+ pt[j++] = '_';
+ i++;
+ break;
+ default:
+ pt[j++] = spt[i++];
+ }
+ }
+ pt[j++] = '\0';
+ return &pt[0];
}
// escapes exactly 'size' bytes of a string into a provided buffer
-int jmemescapecpy (char* pt, const char* spt, int size)
+int jmemescapecpy(char *pt, const char *spt, int size)
{
- //copy from here
- int i =0, j=0;
-
- while (i < size) {
- switch (spt[i]) {
- case '\'':
- pt[j++] = '\\';
- pt[j++] = spt[i++];
- break;
- case '\\':
- pt[j++] = '\\';
- pt[j++] = spt[i++];
- break;
- case '%':
- pt[j++] = '_'; i++;
- break;
- default:
- pt[j++] = spt[i++];
- }
- }
- // copy size is 0 ~ (j-1)
- return j;
+ //copy from here
+ int i =0, j=0;
+
+ while (i < size) {
+ switch (spt[i]) {
+ case '\'':
+ pt[j++] = '\\';
+ pt[j++] = spt[i++];
+ break;
+ case '\\':
+ pt[j++] = '\\';
+ pt[j++] = spt[i++];
+ break;
+ case '%':
+ pt[j++] = '_';
+ i++;
+ break;
+ default:
+ pt[j++] = spt[i++];
+ }
+ }
+ // copy size is 0 ~ (j-1)
+ return j;
}
// Function to suppress control characters in a string.
-int remove_control_chars(char* str)
+int remove_control_chars(char *str)
{
- int i;
- int change = 0;
+ int i;
+ int change = 0;
- for(i = 0; str[i]; i++) {
- if (ISCNTRL(str[i])) {
- str[i] = '_';
- change = 1;
- }
- }
+ for (i = 0; str[i]; i++) {
+ if (ISCNTRL(str[i])) {
+ str[i] = '_';
+ change = 1;
+ }
+ }
- return change;
+ return change;
}
// Removes characters identified by ISSPACE from the start and end of the string
// NOTE: make sure the string is not const!!
-char* trim(char* str)
+char *trim(char *str)
{
- size_t start;
- size_t end;
-
- if( str == NULL )
- return str;
-
- // get start position
- for( start = 0; str[start] && ISSPACE(str[start]); ++start )
- ;
- // get end position
- for( end = strlen(str); start < end && str[end-1] && ISSPACE(str[end-1]); --end )
- ;
- // trim
- if( start == end )
- *str = '\0';// empty string
- else
- {// move string with nul terminator
- str[end] = '\0';
- memmove(str,str+start,end-start+1);
- }
- return str;
+ size_t start;
+ size_t end;
+
+ if (str == NULL)
+ return str;
+
+ // get start position
+ for (start = 0; str[start] && ISSPACE(str[start]); ++start)
+ ;
+ // get end position
+ for (end = strlen(str); start < end && str[end-1] && ISSPACE(str[end-1]); --end)
+ ;
+ // trim
+ if (start == end)
+ *str = '\0';// empty string
+ else {
+ // move string with nul terminator
+ str[end] = '\0';
+ memmove(str,str+start,end-start+1);
+ }
+ return str;
}
// Converts one or more consecutive occurences of the delimiters into a single space
// and removes such occurences from the beginning and end of string
// NOTE: make sure the string is not const!!
-char* normalize_name(char* str,const char* delims)
+char *normalize_name(char *str,const char *delims)
{
- char* in = str;
- char* out = str;
- int put_space = 0;
-
- if( str == NULL || delims == NULL )
- return str;
-
- // trim start of string
- while( *in && strchr(delims,*in) )
- ++in;
- while( *in )
- {
- if( put_space )
- {// replace trim characters with a single space
- *out = ' ';
- ++out;
- }
- // copy non trim characters
- while( *in && !strchr(delims,*in) )
- {
- *out = *in;
- ++out;
- ++in;
- }
- // skip trim characters
- while( *in && strchr(delims,*in) )
- ++in;
- put_space = 1;
- }
- *out = '\0';
- return str;
+ char *in = str;
+ char *out = str;
+ int put_space = 0;
+
+ if (str == NULL || delims == NULL)
+ return str;
+
+ // trim start of string
+ while (*in && strchr(delims,*in))
+ ++in;
+ while (*in) {
+ if (put_space) {
+ // replace trim characters with a single space
+ *out = ' ';
+ ++out;
+ }
+ // copy non trim characters
+ while (*in && !strchr(delims,*in)) {
+ *out = *in;
+ ++out;
+ ++in;
+ }
+ // skip trim characters
+ while (*in && strchr(delims,*in))
+ ++in;
+ put_space = 1;
+ }
+ *out = '\0';
+ return str;
}
-//stristr: Case insensitive version of strstr, code taken from
+//stristr: Case insensitive version of strstr, code taken from
//http://www.daniweb.com/code/snippet313.html, Dave Sinkula
//
-const char* stristr(const char* haystack, const char* needle)
+const char *stristr(const char *haystack, const char *needle)
{
- if ( !*needle )
- {
- return haystack;
- }
- for ( ; *haystack; ++haystack )
- {
- if ( TOUPPER(*haystack) == TOUPPER(*needle) )
- {
- // matched starting char -- loop through remaining chars
- const char *h, *n;
- for ( h = haystack, n = needle; *h && *n; ++h, ++n )
- {
- if ( TOUPPER(*h) != TOUPPER(*n) )
- {
- break;
- }
- }
- if ( !*n ) // matched all of 'needle' to null termination
- {
- return haystack; // return the start of the match
- }
- }
- }
- return 0;
+ if (!*needle) {
+ return haystack;
+ }
+ for (; *haystack; ++haystack) {
+ if (TOUPPER(*haystack) == TOUPPER(*needle)) {
+ // matched starting char -- loop through remaining chars
+ const char *h, *n;
+ for (h = haystack, n = needle; *h && *n; ++h, ++n) {
+ if (TOUPPER(*h) != TOUPPER(*n)) {
+ break;
+ }
+ }
+ if (!*n) { // matched all of 'needle' to null termination
+ return haystack; // return the start of the match
+ }
+ }
+ }
+ return 0;
}
#ifdef __WIN32
-char* _strtok_r(char *s1, const char *s2, char **lasts)
+char *_strtok_r(char *s1, const char *s2, char **lasts)
{
- char *ret;
-
- if (s1 == NULL)
- s1 = *lasts;
- while(*s1 && strchr(s2, *s1))
- ++s1;
- if(*s1 == '\0')
- return NULL;
- ret = s1;
- while(*s1 && !strchr(s2, *s1))
- ++s1;
- if(*s1)
- *s1++ = '\0';
- *lasts = s1;
- return ret;
+ char *ret;
+
+ if (s1 == NULL)
+ s1 = *lasts;
+ while (*s1 && strchr(s2, *s1))
+ ++s1;
+ if (*s1 == '\0')
+ return NULL;
+ ret = s1;
+ while (*s1 && !strchr(s2, *s1))
+ ++s1;
+ if (*s1)
+ *s1++ = '\0';
+ *lasts = s1;
+ return ret;
}
#endif
#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN)
/* Find the length of STRING, but scan at most MAXLEN characters.
If no '\0' terminator is found in that many characters, return MAXLEN. */
-size_t strnlen (const char* string, size_t maxlen)
+size_t strnlen(const char *string, size_t maxlen)
{
- const char* end = (const char*)memchr(string, '\0', maxlen);
- return end ? (size_t) (end - string) : maxlen;
+ const char *end = (const char *)memchr(string, '\0', maxlen);
+ return end ? (size_t)(end - string) : maxlen;
}
#endif
#if defined(WIN32) && defined(_MSC_VER) && _MSC_VER <= 1200
-uint64 strtoull(const char* str, char** endptr, int base)
+uint64 strtoull(const char *str, char **endptr, int base)
{
- uint64 result;
- int count;
- int n;
-
- if( base == 0 )
- {
- if( str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
- base = 16;
- else
- if( str[0] == '0' )
- base = 8;
- else
- base = 10;
- }
-
- if( base == 8 )
- count = sscanf(str, "%I64o%n", &result, &n);
- else
- if( base == 10 )
- count = sscanf(str, "%I64u%n", &result, &n);
- else
- if( base == 16 )
- count = sscanf(str, "%I64x%n", &result, &n);
- else
- count = 0; // fail
-
- if( count < 1 )
- {
- errno = EINVAL;
- result = 0;
- n = 0;
- }
-
- if( endptr )
- *endptr = (char*)str + n;
-
- return result;
+ uint64 result;
+ int count;
+ int n;
+
+ if (base == 0) {
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ base = 16;
+ else if (str[0] == '0')
+ base = 8;
+ else
+ base = 10;
+ }
+
+ if (base == 8)
+ count = sscanf(str, "%I64o%n", &result, &n);
+ else if (base == 10)
+ count = sscanf(str, "%I64u%n", &result, &n);
+ else if (base == 16)
+ count = sscanf(str, "%I64x%n", &result, &n);
+ else
+ count = 0; // fail
+
+ if (count < 1) {
+ errno = EINVAL;
+ result = 0;
+ n = 0;
+ }
+
+ if (endptr)
+ *endptr = (char *)str + n;
+
+ return result;
}
#endif
//----------------------------------------------------
// E-mail check: return 0 (not correct) or 1 (valid).
//----------------------------------------------------
-int e_mail_check(char* email)
+int e_mail_check(char *email)
{
- char ch;
- char* last_arobas;
- size_t len = strlen(email);
+ char ch;
+ char *last_arobas;
+ size_t len = strlen(email);
- // athena limits
- if (len < 3 || len > 39)
- return 0;
+ // athena limits
+ if (len < 3 || len > 39)
+ return 0;
- // part of RFC limits (official reference of e-mail description)
- if (strchr(email, '@') == NULL || email[len-1] == '@')
- return 0;
+ // part of RFC limits (official reference of e-mail description)
+ if (strchr(email, '@') == NULL || email[len-1] == '@')
+ return 0;
- if (email[len-1] == '.')
- return 0;
+ if (email[len-1] == '.')
+ return 0;
- last_arobas = strrchr(email, '@');
+ last_arobas = strrchr(email, '@');
- if (strstr(last_arobas, "@.") != NULL || strstr(last_arobas, "..") != NULL)
- return 0;
+ if (strstr(last_arobas, "@.") != NULL || strstr(last_arobas, "..") != NULL)
+ return 0;
- for(ch = 1; ch < 32; ch++)
- if (strchr(last_arobas, ch) != NULL)
- return 0;
+ for (ch = 1; ch < 32; ch++)
+ if (strchr(last_arobas, ch) != NULL)
+ return 0;
- if (strchr(last_arobas, ' ') != NULL || strchr(last_arobas, ';') != NULL)
- return 0;
+ if (strchr(last_arobas, ' ') != NULL || strchr(last_arobas, ';') != NULL)
+ return 0;
- // all correct
- return 1;
+ // all correct
+ return 1;
}
//--------------------------------------------------
// Return numerical value of a switch configuration
// on/off, english, français, deutsch, español
//--------------------------------------------------
-int config_switch(const char* str)
+int config_switch(const char *str)
{
- if (strcmpi(str, "on") == 0 || strcmpi(str, "yes") == 0 || strcmpi(str, "oui") == 0 || strcmpi(str, "ja") == 0 || strcmpi(str, "si") == 0)
- return 1;
- if (strcmpi(str, "off") == 0 || strcmpi(str, "no") == 0 || strcmpi(str, "non") == 0 || strcmpi(str, "nein") == 0)
- return 0;
+ if (strcmpi(str, "on") == 0 || strcmpi(str, "yes") == 0 || strcmpi(str, "oui") == 0 || strcmpi(str, "ja") == 0 || strcmpi(str, "si") == 0)
+ return 1;
+ if (strcmpi(str, "off") == 0 || strcmpi(str, "no") == 0 || strcmpi(str, "non") == 0 || strcmpi(str, "nein") == 0)
+ return 0;
- return (int)strtol(str, NULL, 0);
+ return (int)strtol(str, NULL, 0);
}
/// strncpy that always nul-terminates the string
-char* safestrncpy(char* dst, const char* src, size_t n)
+char *safestrncpy(char *dst, const char *src, size_t n)
{
- if( n > 0 )
- {
- char* d = dst;
- const char* s = src;
- d[--n] = '\0';/* nul-terminate string */
- for( ; n > 0; --n )
- {
- if( (*d++ = *s++) == '\0' )
- {/* nul-pad remaining bytes */
- while( --n > 0 )
- *d++ = '\0';
- break;
- }
- }
- }
- return dst;
+ if (n > 0) {
+ char *d = dst;
+ const char *s = src;
+ d[--n] = '\0';/* nul-terminate string */
+ for (; n > 0; --n) {
+ if ((*d++ = *s++) == '\0') {
+ /* nul-pad remaining bytes */
+ while (--n > 0)
+ *d++ = '\0';
+ break;
+ }
+ }
+ }
+ return dst;
}
/// doesn't crash on null pointer
-size_t safestrnlen(const char* string, size_t maxlen)
+size_t safestrnlen(const char *string, size_t maxlen)
{
- return ( string != NULL ) ? strnlen(string, maxlen) : 0;
+ return (string != NULL) ? strnlen(string, maxlen) : 0;
}
/// Works like snprintf, but always nul-terminates the buffer.
@@ -379,41 +367,40 @@ size_t safestrnlen(const char* string, size_t maxlen)
/// @param fmt Format string
/// @param ... Format arguments
/// @return The size of the string or -1 if the buffer is too small
-int safesnprintf(char* buf, size_t sz, const char* fmt, ...)
+int safesnprintf(char *buf, size_t sz, const char *fmt, ...)
{
- va_list ap;
- int ret;
-
- va_start(ap,fmt);
- ret = vsnprintf(buf, sz, fmt, ap);
- va_end(ap);
- if( ret < 0 || (size_t)ret >= sz )
- {// overflow
- buf[sz-1] = '\0';// always nul-terminate
- return -1;
- }
- return ret;
+ va_list ap;
+ int ret;
+
+ va_start(ap,fmt);
+ ret = vsnprintf(buf, sz, fmt, ap);
+ va_end(ap);
+ if (ret < 0 || (size_t)ret >= sz) {
+ // overflow
+ buf[sz-1] = '\0';// always nul-terminate
+ return -1;
+ }
+ return ret;
}
/// Returns the line of the target position in the string.
/// Lines start at 1.
-int strline(const char* str, size_t pos)
+int strline(const char *str, size_t pos)
{
- const char* target;
- int line;
-
- if( str == NULL || pos == 0 )
- return 1;
-
- target = str+pos;
- for( line = 1; ; ++line )
- {
- str = strchr(str, '\n');
- if( str == NULL || target <= str )
- break;// found target line
- ++str;// skip newline
- }
- return line;
+ const char *target;
+ int line;
+
+ if (str == NULL || pos == 0)
+ return 1;
+
+ target = str+pos;
+ for (line = 1; ; ++line) {
+ str = strchr(str, '\n');
+ if (str == NULL || target <= str)
+ break;// found target line
+ ++str;// skip newline
+ }
+ return line;
}
/// Produces the hexadecimal representation of the given input.
@@ -423,19 +410,18 @@ int strline(const char* str, size_t pos)
/// @param output Output string
/// @param input Binary input buffer
/// @param count Number of bytes to convert
-bool bin2hex(char* output, unsigned char* input, size_t count)
+bool bin2hex(char *output, unsigned char *input, size_t count)
{
- char toHex[] = "0123456789abcdef";
- size_t i;
-
- for( i = 0; i < count; ++i )
- {
- *output++ = toHex[(*input & 0xF0) >> 4];
- *output++ = toHex[(*input & 0x0F) >> 0];
- ++input;
- }
- *output = '\0';
- return true;
+ char toHex[] = "0123456789abcdef";
+ size_t i;
+
+ for (i = 0; i < count; ++i) {
+ *output++ = toHex[(*input & 0xF0) >> 4];
+ *output++ = toHex[(*input & 0x0F) >> 0];
+ ++input;
+ }
+ *output = '\0';
+ return true;
}
@@ -446,146 +432,134 @@ bool bin2hex(char* output, unsigned char* input, size_t count)
///
/// @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 sv_parse_next(struct s_svstate *sv)
{
- enum {
- START_OF_FIELD,
- PARSING_FIELD,
- PARSING_C_ESCAPE,
- END_OF_FIELD,
- TERMINATE,
- END
- } state;
- const char* str;
- int len;
- enum e_svopt opt;
- char delim;
- int i;
-
- 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_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_next: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n");
- return -1;// error
- }
-
- if( sv->done || str == NULL )
- {
- sv->done = true;
- return 0;// nothing to parse
- }
+ enum {
+ START_OF_FIELD,
+ PARSING_FIELD,
+ PARSING_C_ESCAPE,
+ END_OF_FIELD,
+ TERMINATE,
+ END
+ } state;
+ const char *str;
+ int len;
+ enum e_svopt opt;
+ char delim;
+ int i;
+
+ 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_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_next: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n");
+ return -1;// error
+ }
+
+ if (sv->done || str == NULL) {
+ sv->done = true;
+ return 0;// nothing to parse
+ }
#define IS_END() ( i >= len )
#define IS_DELIM() ( str[i] == delim )
#define IS_TERMINATOR() ( \
- ((opt&SV_TERMINATE_LF) && str[i] == '\n') || \
- ((opt&SV_TERMINATE_CR) && str[i] == '\r') || \
- ((opt&SV_TERMINATE_CRLF) && i+1 < len && str[i] == '\r' && str[i+1] == '\n') )
+ ((opt&SV_TERMINATE_LF) && str[i] == '\n') || \
+ ((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() sv->start = i
#define SET_FIELD_END() sv->end = i
- i = sv->off;
- state = START_OF_FIELD;
- while( state != END )
- {
- switch( state )
- {
- case START_OF_FIELD:// record start of field and start parsing it
- SET_FIELD_START();
- state = PARSING_FIELD;
- break;
-
- case PARSING_FIELD:// skip field character
- if( IS_END() || IS_DELIM() || IS_TERMINATOR() )
- state = END_OF_FIELD;
- else if( IS_C_ESCAPE() )
- state = PARSING_C_ESCAPE;
- else
- ++i;// normal character
- break;
-
- case PARSING_C_ESCAPE:// skip escape sequence (validates it too)
- {
- ++i;// '\\'
- if( IS_END() )
- {
- ShowError("sv_parse_next: empty escape sequence\n");
- return -1;
- }
- if( str[i] == 'x' )
- {// hex escape
- ++i;// 'x'
- if( IS_END() || !ISXDIGIT(str[i]) )
- {
- ShowError("sv_parse_next: \\x with no following hex digits\n");
- return -1;
- }
- do{
- ++i;// hex digit
- }while( !IS_END() && ISXDIGIT(str[i]));
- }
- else if( str[i] == '0' || str[i] == '1' || str[i] == '2' )
- {// octal escape
- ++i;// octal digit
- if( !IS_END() && str[i] >= '0' && str[i] <= '7' )
- ++i;// octal digit
- if( !IS_END() && str[i] >= '0' && str[i] <= '7' )
- ++i;// octal digit
- }
- else if( strchr(SV_ESCAPE_C_SUPPORTED, str[i]) )
- {// supported escape character
- ++i;
- }
- else
- {
- 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 stop
- SET_FIELD_END();
- state = END;
- if( IS_END() )
- ;// nothing else
- else if( IS_DELIM() )
- ++i;// delim
- else if( IS_TERMINATOR() )
- state = TERMINATE;
- break;
-
- case TERMINATE:
+ i = sv->off;
+ state = START_OF_FIELD;
+ while (state != END) {
+ switch (state) {
+ case START_OF_FIELD:// record start of field and start parsing it
+ SET_FIELD_START();
+ state = PARSING_FIELD;
+ break;
+
+ case PARSING_FIELD:// skip field character
+ if (IS_END() || IS_DELIM() || IS_TERMINATOR())
+ state = END_OF_FIELD;
+ else if (IS_C_ESCAPE())
+ state = PARSING_C_ESCAPE;
+ else
+ ++i;// normal character
+ break;
+
+ case PARSING_C_ESCAPE: { // skip escape sequence (validates it too)
+ ++i;// '\\'
+ if (IS_END()) {
+ ShowError("sv_parse_next: empty escape sequence\n");
+ return -1;
+ }
+ if (str[i] == 'x') {
+ // hex escape
+ ++i;// 'x'
+ if (IS_END() || !ISXDIGIT(str[i])) {
+ ShowError("sv_parse_next: \\x with no following hex digits\n");
+ return -1;
+ }
+ do {
+ ++i;// hex digit
+ } while (!IS_END() && ISXDIGIT(str[i]));
+ } else if (str[i] == '0' || str[i] == '1' || str[i] == '2') {
+ // octal escape
+ ++i;// octal digit
+ if (!IS_END() && str[i] >= '0' && str[i] <= '7')
+ ++i;// octal digit
+ if (!IS_END() && str[i] >= '0' && str[i] <= '7')
+ ++i;// octal digit
+ } else if (strchr(SV_ESCAPE_C_SUPPORTED, str[i])) {
+ // supported escape character
+ ++i;
+ } else {
+ 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 stop
+ SET_FIELD_END();
+ state = END;
+ if (IS_END())
+ ;// nothing else
+ else if (IS_DELIM())
+ ++i;// delim
+ else if (IS_TERMINATOR())
+ state = TERMINATE;
+ break;
+
+ case TERMINATE:
#if 0
- // skip line terminator
- if( (opt&SV_TERMINATE_CRLF) && i+1 < len && str[i] == '\r' && str[i+1] == '\n' )
- i += 2;// CRLF
- else
- ++i;// CR or LF
+ // skip line terminator
+ if ((opt&SV_TERMINATE_CRLF) && i+1 < len && str[i] == '\r' && str[i+1] == '\n')
+ i += 2;// CRLF
+ else
+ ++i;// CR or LF
#endif
- sv->done = true;
- state = END;
- break;
- }
- }
- if( IS_END() )
- sv->done = true;
- sv->off = i;
+ sv->done = true;
+ state = END;
+ break;
+ }
+ }
+ if (IS_END())
+ sv->done = true;
+ sv->off = i;
#undef IS_END
#undef IS_DELIM
@@ -594,7 +568,7 @@ int sv_parse_next(struct s_svstate* sv)
#undef SET_FIELD_START
#undef SET_FIELD_END
- return 1;
+ return 1;
}
@@ -603,13 +577,13 @@ int sv_parse_next(struct s_svstate* sv)
/// 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]
+/// 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
@@ -618,35 +592,34 @@ int sv_parse_next(struct s_svstate* sv)
/// @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)
+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;
+ 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;
}
/// Splits a delim-separated string.
@@ -655,11 +628,11 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
/// out_fields[0] is the start of the next line.
/// Other entries are the start of fields (nul-teminated).
/// Returns the number of fields found or -1 if an error occurs.
-///
+///
/// out_fields can be NULL.
/// Fields that don't fit in out_fields are not nul-terminated.
/// Extra entries in out_fields are filled with the end of the last field (empty string).
-///
+///
/// @param str String to parse
/// @param len Length of the string
/// @param startoff Where to start parsing
@@ -668,75 +641,64 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
/// @param nfields Size of the field 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_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt)
+int sv_split(char *str, int len, int startoff, char delim, char **out_fields, int nfields, enum e_svopt opt)
{
- int pos[1024];
- int i;
- int done;
- char* end;
- int ret = sv_parse(str, len, startoff, delim, pos, ARRAYLENGTH(pos), opt);
-
- if( ret == -1 || out_fields == NULL || nfields <= 0 )
- return ret; // nothing to do
-
- // next line
- end = str + pos[1];
- if( end[0] == '\0' )
- {
- *out_fields = end;
- }
- else if( (opt&SV_TERMINATE_LF) && end[0] == '\n' )
- {
- if( !(opt&SV_KEEP_TERMINATOR) )
- end[0] = '\0';
- *out_fields = end + 1;
- }
- else if( (opt&SV_TERMINATE_CRLF) && end[0] == '\r' && end[1] == '\n' )
- {
- if( !(opt&SV_KEEP_TERMINATOR) )
- end[0] = end[1] = '\0';
- *out_fields = end + 2;
- }
- else if( (opt&SV_TERMINATE_CR) && end[0] == '\r' )
- {
- if( !(opt&SV_KEEP_TERMINATOR) )
- end[0] = '\0';
- *out_fields = end + 1;
- }
- else
- {
- ShowError("sv_split: unknown line delimiter 0x02%x.\n", (unsigned char)end[0]);
- return -1;// error
- }
- ++out_fields;
- --nfields;
-
- // fields
- i = 2;
- done = 0;
- while( done < ret && nfields > 0 )
- {
- if( i < ARRAYLENGTH(pos) )
- {// split field
- *out_fields = str + pos[i];
- end = str + pos[i+1];
- *end = '\0';
- // next field
- i += 2;
- ++done;
- ++out_fields;
- --nfields;
- }
- else
- {// get more fields
- sv_parse(str, len, pos[i-1] + 1, delim, pos, ARRAYLENGTH(pos), opt);
- i = 2;
- }
- }
- // remaining fields
- for( i = 0; i < nfields; ++i )
- out_fields[i] = end;
- return ret;
+ int pos[1024];
+ int i;
+ int done;
+ char *end;
+ int ret = sv_parse(str, len, startoff, delim, pos, ARRAYLENGTH(pos), opt);
+
+ if (ret == -1 || out_fields == NULL || nfields <= 0)
+ return ret; // nothing to do
+
+ // next line
+ end = str + pos[1];
+ if (end[0] == '\0') {
+ *out_fields = end;
+ } else if ((opt&SV_TERMINATE_LF) && end[0] == '\n') {
+ if (!(opt&SV_KEEP_TERMINATOR))
+ end[0] = '\0';
+ *out_fields = end + 1;
+ } else if ((opt&SV_TERMINATE_CRLF) && end[0] == '\r' && end[1] == '\n') {
+ if (!(opt&SV_KEEP_TERMINATOR))
+ end[0] = end[1] = '\0';
+ *out_fields = end + 2;
+ } else if ((opt&SV_TERMINATE_CR) && end[0] == '\r') {
+ if (!(opt&SV_KEEP_TERMINATOR))
+ end[0] = '\0';
+ *out_fields = end + 1;
+ } else {
+ ShowError("sv_split: unknown line delimiter 0x02%x.\n", (unsigned char)end[0]);
+ return -1;// error
+ }
+ ++out_fields;
+ --nfields;
+
+ // fields
+ i = 2;
+ done = 0;
+ while (done < ret && nfields > 0) {
+ if (i < ARRAYLENGTH(pos)) {
+ // split field
+ *out_fields = str + pos[i];
+ end = str + pos[i+1];
+ *end = '\0';
+ // next field
+ i += 2;
+ ++done;
+ ++out_fields;
+ --nfields;
+ } else {
+ // get more fields
+ sv_parse(str, len, pos[i-1] + 1, delim, pos, ARRAYLENGTH(pos), opt);
+ i = 2;
+ }
+ }
+ // remaining fields
+ for (i = 0; i < nfields; ++i)
+ out_fields[i] = end;
+ return ret;
}
/// Escapes src to out_dest according to the format of the C compiler.
@@ -748,69 +710,77 @@ int sv_split(char* str, int len, int startoff, char delim, char** out_fields, in
/// @param len Length of the source string
/// @param escapes Extra characters to be escaped
/// @return Length of the escaped string
-size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* escapes)
+size_t sv_escape_c(char *out_dest, const char *src, size_t len, const char *escapes)
{
- size_t i;
- size_t j;
-
- if( out_dest == NULL )
- return 0;// nothing to do
- if( src == NULL )
- {// nothing to escape
- *out_dest = 0;
- return 0;
- }
- if( escapes == NULL )
- escapes = "";
-
- for( i = 0, j = 0; i < len; ++i )
- {
- switch( src[i] )
- {
- case '\0':// octal 0
- out_dest[j++] = '\\';
- out_dest[j++] = '0';
- out_dest[j++] = '0';
- out_dest[j++] = '0';
- break;
- case '\r':// carriage return
- out_dest[j++] = '\\';
- out_dest[j++] = 'r';
- break;
- case '\n':// line feed
- out_dest[j++] = '\\';
- out_dest[j++] = 'n';
- break;
- case '\\':// escape character
- out_dest[j++] = '\\';
- out_dest[j++] = '\\';
- break;
- default:
- if( strchr(escapes,src[i]) )
- {// escape
- out_dest[j++] = '\\';
- switch( src[i] )
- {
- case '\a': out_dest[j++] = 'a'; break;
- case '\b': out_dest[j++] = 'b'; break;
- case '\t': out_dest[j++] = 't'; break;
- case '\v': out_dest[j++] = 'v'; break;
- case '\f': out_dest[j++] = 'f'; break;
- case '\?': out_dest[j++] = '?'; break;
- default:// to octal
- out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0700)>>6));
- out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0070)>>3));
- out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0007) ));
- break;
- }
- }
- else
- out_dest[j++] = src[i];
- break;
- }
- }
- out_dest[j] = 0;
- return j;
+ size_t i;
+ size_t j;
+
+ if (out_dest == NULL)
+ return 0;// nothing to do
+ if (src == NULL) {
+ // nothing to escape
+ *out_dest = 0;
+ return 0;
+ }
+ if (escapes == NULL)
+ escapes = "";
+
+ for (i = 0, j = 0; i < len; ++i) {
+ switch (src[i]) {
+ case '\0':// octal 0
+ out_dest[j++] = '\\';
+ out_dest[j++] = '0';
+ out_dest[j++] = '0';
+ out_dest[j++] = '0';
+ break;
+ case '\r':// carriage return
+ out_dest[j++] = '\\';
+ out_dest[j++] = 'r';
+ break;
+ case '\n':// line feed
+ out_dest[j++] = '\\';
+ out_dest[j++] = 'n';
+ break;
+ case '\\':// escape character
+ out_dest[j++] = '\\';
+ out_dest[j++] = '\\';
+ break;
+ default:
+ if (strchr(escapes,src[i])) {
+ // escape
+ out_dest[j++] = '\\';
+ switch (src[i]) {
+ case '\a':
+ out_dest[j++] = 'a';
+ break;
+ case '\b':
+ out_dest[j++] = 'b';
+ break;
+ case '\t':
+ out_dest[j++] = 't';
+ break;
+ case '\v':
+ out_dest[j++] = 'v';
+ break;
+ case '\f':
+ out_dest[j++] = 'f';
+ break;
+ case '\?':
+ out_dest[j++] = '?';
+ break;
+ default:// to octal
+ out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0700)>>6));
+ out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0070)>>3));
+ out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0007)));
+ break;
+ }
+ } else
+ out_dest[j++] = src[i];
+ break;
+ }
+ }
+ out_dest[j] = 0;
+ return j;
}
/// Unescapes src to out_dest according to the format of the C compiler.
@@ -821,129 +791,135 @@ size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* esca
/// @param src Source string
/// @param len Length of the source string
/// @return Length of the escaped string
-size_t sv_unescape_c(char* out_dest, const char* src, size_t len)
+size_t sv_unescape_c(char *out_dest, const char *src, size_t len)
{
- static unsigned char low2hex[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x0?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x1?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x2?
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,// 0x3?
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x4?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x5?
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x6?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x7?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x8?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x9?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xA?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xB?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xC?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xD?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xE?
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF?
- };
- size_t i;
- size_t j;
-
- for( i = 0, j = 0; i < len; )
- {
- if( src[i] == '\\' )
- {
- ++i;// '\\'
- if( i >= len )
- ShowWarning("sv_unescape_c: empty escape sequence\n");
- else if( src[i] == 'x' )
- {// hex escape sequence
- unsigned char c = 0;
- unsigned char inrange = 1;
-
- ++i;// 'x'
- if( i >= len || !ISXDIGIT(src[i]) )
- {
- ShowWarning("sv_unescape_c: \\x with no following hex digits\n");
- continue;
- }
- do{
- if( c > 0x0F && inrange )
- {
- ShowWarning("sv_unescape_c: hex escape sequence out of range\n");
- inrange = 0;
- }
- c = (c<<4)|low2hex[(unsigned char)src[i]];// hex digit
- ++i;
- }while( i < len && ISXDIGIT(src[i]) );
- out_dest[j++] = (char)c;
- }
- else if( src[i] == '0' || src[i] == '1' || src[i] == '2' || src[i] == '3' )
- {// octal escape sequence (255=0377)
- unsigned char c = src[i]-'0';
- ++i;// '0', '1', '2' or '3'
- if( i < len && src[i] >= '0' && src[i] <= '7' )
- {
- c = (c<<3)|(src[i]-'0');
- ++i;// octal digit
- }
- if( i < len && src[i] >= '0' && src[i] <= '7' )
- {
- c = (c<<3)|(src[i]-'0');
- ++i;// octal digit
- }
- out_dest[j++] = (char)c;
- }
- else
- {// other escape sequence
- if( strchr(SV_ESCAPE_C_SUPPORTED, src[i]) == NULL )
- ShowWarning("sv_unescape_c: unknown escape sequence \\%c\n", src[i]);
- switch( src[i] )
- {
- case 'a': out_dest[j++] = '\a'; break;
- case 'b': out_dest[j++] = '\b'; break;
- case 't': out_dest[j++] = '\t'; break;
- case 'n': out_dest[j++] = '\n'; break;
- case 'v': out_dest[j++] = '\v'; break;
- case 'f': out_dest[j++] = '\f'; break;
- case 'r': out_dest[j++] = '\r'; break;
- case '?': out_dest[j++] = '\?'; break;
- default: out_dest[j++] = src[i]; break;
- }
- ++i;// escaped character
- }
- }
- else
- out_dest[j++] = src[i++];// normal character
- }
- out_dest[j] = 0;
- return j;
+ static unsigned char low2hex[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x0?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x1?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x2?
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,// 0x3?
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x4?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x5?
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x6?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x7?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x8?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x9?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xA?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xB?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xC?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xD?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0xE?
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF?
+ };
+ size_t i;
+ size_t j;
+
+ for (i = 0, j = 0; i < len;) {
+ if (src[i] == '\\') {
+ ++i;// '\\'
+ if (i >= len)
+ ShowWarning("sv_unescape_c: empty escape sequence\n");
+ else if (src[i] == 'x') {
+ // hex escape sequence
+ unsigned char c = 0;
+ unsigned char inrange = 1;
+
+ ++i;// 'x'
+ if (i >= len || !ISXDIGIT(src[i])) {
+ ShowWarning("sv_unescape_c: \\x with no following hex digits\n");
+ continue;
+ }
+ do {
+ if (c > 0x0F && inrange) {
+ ShowWarning("sv_unescape_c: hex escape sequence out of range\n");
+ inrange = 0;
+ }
+ c = (c<<4)|low2hex[(unsigned char)src[i]];// hex digit
+ ++i;
+ } while (i < len && ISXDIGIT(src[i]));
+ out_dest[j++] = (char)c;
+ } else if (src[i] == '0' || src[i] == '1' || src[i] == '2' || src[i] == '3') {
+ // octal escape sequence (255=0377)
+ unsigned char c = src[i]-'0';
+ ++i;// '0', '1', '2' or '3'
+ if (i < len && src[i] >= '0' && src[i] <= '7') {
+ c = (c<<3)|(src[i]-'0');
+ ++i;// octal digit
+ }
+ if (i < len && src[i] >= '0' && src[i] <= '7') {
+ c = (c<<3)|(src[i]-'0');
+ ++i;// octal digit
+ }
+ out_dest[j++] = (char)c;
+ } else {
+ // other escape sequence
+ if (strchr(SV_ESCAPE_C_SUPPORTED, src[i]) == NULL)
+ ShowWarning("sv_unescape_c: unknown escape sequence \\%c\n", src[i]);
+ switch (src[i]) {
+ case 'a':
+ out_dest[j++] = '\a';
+ break;
+ case 'b':
+ out_dest[j++] = '\b';
+ break;
+ case 't':
+ out_dest[j++] = '\t';
+ break;
+ case 'n':
+ out_dest[j++] = '\n';
+ break;
+ case 'v':
+ out_dest[j++] = '\v';
+ break;
+ case 'f':
+ out_dest[j++] = '\f';
+ break;
+ case 'r':
+ out_dest[j++] = '\r';
+ break;
+ case '?':
+ out_dest[j++] = '\?';
+ break;
+ default:
+ out_dest[j++] = src[i];
+ break;
+ }
+ ++i;// escaped character
+ }
+ } else
+ out_dest[j++] = src[i++];// normal character
+ }
+ out_dest[j] = 0;
+ return j;
}
/// Skips a C escape sequence (starting with '\\').
-const char* skip_escaped_c(const char* p)
+const char *skip_escaped_c(const char *p)
{
- if( p && *p == '\\' )
- {
- ++p;
- switch( *p )
- {
- case 'x':// hexadecimal
- ++p;
- while( ISXDIGIT(*p) )
- ++p;
- break;
- case '0':
- case '1':
- case '2':
- case '3':// octal
- ++p;
- if( *p >= '0' && *p <= '7' )
- ++p;
- if( *p >= '0' && *p <= '7' )
- ++p;
- break;
- default:
- if( *p && strchr(SV_ESCAPE_C_SUPPORTED, *p) )
- ++p;
- }
- }
- return p;
+ if (p && *p == '\\') {
+ ++p;
+ switch (*p) {
+ case 'x':// hexadecimal
+ ++p;
+ while (ISXDIGIT(*p))
+ ++p;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':// octal
+ ++p;
+ if (*p >= '0' && *p <= '7')
+ ++p;
+ if (*p >= '0' && *p <= '7')
+ ++p;
+ break;
+ default:
+ if (*p && strchr(SV_ESCAPE_C_SUPPORTED, *p))
+ ++p;
+ }
+ }
+ return p;
}
@@ -958,78 +934,72 @@ const char* skip_escaped_c(const char* p)
/// @param maxcols Maximum number of columns of a valid row
/// @param parseproc User-supplied row processing function
/// @return true on success, false if file could not be opened
-bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current))
+bool sv_readdb(const char *directory, const char *filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char *fields[], int columns, int current))
{
- FILE* fp;
- int lines = 0;
- int entries = 0;
- char** fields; // buffer for fields ([0] is reserved)
- int columns, fields_length;
- char path[1024], line[1024];
- char* match;
-
- snprintf(path, sizeof(path), "%s/%s", directory, filename);
-
- // open file
- fp = fopen(path, "r");
- if( fp == NULL )
- {
- ShowError("sv_readdb: can't read %s\n", path);
- return false;
- }
-
- // allocate enough memory for the maximum requested amount of columns plus the reserved one
- fields_length = maxcols+1;
- fields = (char**)aMalloc(fields_length*sizeof(char*));
-
- // process rows one by one
- while( fgets(line, sizeof(line), fp) )
- {
- lines++;
-
- if( ( match = strstr(line, "//") ) != NULL )
- {// strip comments
- match[0] = 0;
- }
-
- //TODO: strip trailing whitespace
- if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
- continue;
-
- columns = sv_split(line, strlen(line), 0, delim, fields, fields_length, (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF));
-
- if( columns < mincols )
- {
- ShowError("sv_readdb: Insufficient columns in line %d of \"%s\" (found %d, need at least %d).\n", lines, path, columns, mincols);
- continue; // not enough columns
- }
- if( columns > maxcols )
- {
- ShowError("sv_readdb: Too many columns in line %d of \"%s\" (found %d, maximum is %d).\n", lines, path, columns, maxcols );
- continue; // too many columns
- }
- if( entries == maxrows )
- {
- ShowError("sv_readdb: Reached the maximum allowed number of entries (%d) when parsing file \"%s\".\n", maxrows, path);
- break;
- }
-
- // parse this row
- if( !parseproc(fields+1, columns, entries) )
- {
- ShowError("sv_readdb: Could not process contents of line %d of \"%s\".\n", lines, path);
- continue; // invalid row contents
- }
-
- // success!
- entries++;
- }
-
- aFree(fields);
- fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, path);
-
- return true;
+ FILE *fp;
+ int lines = 0;
+ int entries = 0;
+ char **fields; // buffer for fields ([0] is reserved)
+ int columns, fields_length;
+ char path[1024], line[1024];
+ char *match;
+
+ snprintf(path, sizeof(path), "%s/%s", directory, filename);
+
+ // open file
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ ShowError("sv_readdb: can't read %s\n", path);
+ return false;
+ }
+
+ // allocate enough memory for the maximum requested amount of columns plus the reserved one
+ fields_length = maxcols+1;
+ fields = (char **)aMalloc(fields_length*sizeof(char *));
+
+ // process rows one by one
+ while (fgets(line, sizeof(line), fp)) {
+ lines++;
+
+ if ((match = strstr(line, "//")) != NULL) {
+ // strip comments
+ match[0] = 0;
+ }
+
+ //TODO: strip trailing whitespace
+ if (line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
+ continue;
+
+ columns = sv_split(line, strlen(line), 0, delim, fields, fields_length, (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF));
+
+ if (columns < mincols) {
+ ShowError("sv_readdb: Insufficient columns in line %d of \"%s\" (found %d, need at least %d).\n", lines, path, columns, mincols);
+ continue; // not enough columns
+ }
+ if (columns > maxcols) {
+ ShowError("sv_readdb: Too many columns in line %d of \"%s\" (found %d, maximum is %d).\n", lines, path, columns, maxcols);
+ continue; // too many columns
+ }
+ if (entries == maxrows) {
+ ShowError("sv_readdb: Reached the maximum allowed number of entries (%d) when parsing file \"%s\".\n", maxrows, path);
+ break;
+ }
+
+ // parse this row
+ if (!parseproc(fields+1, columns, entries)) {
+ ShowError("sv_readdb: Could not process contents of line %d of \"%s\".\n", lines, path);
+ continue; // invalid row contents
+ }
+
+ // success!
+ entries++;
+ }
+
+ aFree(fields);
+ fclose(fp);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, path);
+
+ return true;
}
@@ -1039,129 +1009,126 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc
// @author MouseJstr (original)
/// Allocates a StringBuf
-StringBuf* StringBuf_Malloc()
+StringBuf *StringBuf_Malloc()
{
- StringBuf* self;
- CREATE(self, StringBuf, 1);
- StringBuf_Init(self);
- return self;
+ StringBuf *self;
+ CREATE(self, StringBuf, 1);
+ StringBuf_Init(self);
+ return self;
}
/// Initializes a previously allocated StringBuf
-void StringBuf_Init(StringBuf* self)
+void StringBuf_Init(StringBuf *self)
{
- self->max_ = 1024;
- self->ptr_ = self->buf_ = (char*)aMalloc(self->max_ + 1);
+ self->max_ = 1024;
+ self->ptr_ = self->buf_ = (char *)aMalloc(self->max_ + 1);
}
/// Appends the result of printf to the StringBuf
-int StringBuf_Printf(StringBuf* self, const char* fmt, ...)
+int StringBuf_Printf(StringBuf *self, const char *fmt, ...)
{
- int len;
- va_list ap;
+ int len;
+ va_list ap;
- va_start(ap, fmt);
- len = StringBuf_Vprintf(self, fmt, ap);
- va_end(ap);
+ va_start(ap, fmt);
+ len = StringBuf_Vprintf(self, fmt, ap);
+ va_end(ap);
- return len;
+ return len;
}
/// Appends the result of vprintf to the StringBuf
-int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list ap)
+int StringBuf_Vprintf(StringBuf *self, const char *fmt, va_list ap)
{
- int n, size, off;
-
- for(;;)
- {
- va_list apcopy;
- /* Try to print in the allocated space. */
- size = self->max_ - (self->ptr_ - self->buf_);
- va_copy(apcopy, ap);
- n = vsnprintf(self->ptr_, size, fmt, apcopy);
- va_end(apcopy);
- /* If that worked, return the length. */
- if( n > -1 && n < size )
- {
- self->ptr_ += n;
- return (int)(self->ptr_ - self->buf_);
- }
- /* Else try again with more space. */
- self->max_ *= 2; // twice the old size
- off = (int)(self->ptr_ - self->buf_);
- self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1);
- self->ptr_ = self->buf_ + off;
- }
+ int n, size, off;
+
+ for (;;) {
+ va_list apcopy;
+ /* Try to print in the allocated space. */
+ size = self->max_ - (self->ptr_ - self->buf_);
+ va_copy(apcopy, ap);
+ n = vsnprintf(self->ptr_, size, fmt, apcopy);
+ va_end(apcopy);
+ /* If that worked, return the length. */
+ if (n > -1 && n < size) {
+ self->ptr_ += n;
+ return (int)(self->ptr_ - self->buf_);
+ }
+ /* Else try again with more space. */
+ self->max_ *= 2; // twice the old size
+ off = (int)(self->ptr_ - self->buf_);
+ self->buf_ = (char *)aRealloc(self->buf_, self->max_ + 1);
+ self->ptr_ = self->buf_ + off;
+ }
}
/// Appends the contents of another StringBuf to the StringBuf
-int StringBuf_Append(StringBuf* self, const StringBuf* sbuf)
+int StringBuf_Append(StringBuf *self, const StringBuf *sbuf)
{
- int available = self->max_ - (self->ptr_ - self->buf_);
- int needed = (int)(sbuf->ptr_ - sbuf->buf_);
-
- if( needed >= available )
- {
- int off = (int)(self->ptr_ - self->buf_);
- self->max_ += needed;
- self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1);
- self->ptr_ = self->buf_ + off;
- }
-
- memcpy(self->ptr_, sbuf->buf_, needed);
- self->ptr_ += needed;
- return (int)(self->ptr_ - self->buf_);
+ int available = self->max_ - (self->ptr_ - self->buf_);
+ int needed = (int)(sbuf->ptr_ - sbuf->buf_);
+
+ if (needed >= available) {
+ int off = (int)(self->ptr_ - self->buf_);
+ self->max_ += needed;
+ self->buf_ = (char *)aRealloc(self->buf_, self->max_ + 1);
+ self->ptr_ = self->buf_ + off;
+ }
+
+ memcpy(self->ptr_, sbuf->buf_, needed);
+ self->ptr_ += needed;
+ return (int)(self->ptr_ - self->buf_);
}
// Appends str to the StringBuf
-int StringBuf_AppendStr(StringBuf* self, const char* str)
+int StringBuf_AppendStr(StringBuf *self, const char *str)
{
- int available = self->max_ - (self->ptr_ - self->buf_);
- int needed = (int)strlen(str);
-
- if( needed >= available )
- {// not enough space, expand the buffer (minimum expansion = 1024)
- int off = (int)(self->ptr_ - self->buf_);
- self->max_ += max(needed, 1024);
- self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1);
- self->ptr_ = self->buf_ + off;
- }
-
- memcpy(self->ptr_, str, needed);
- self->ptr_ += needed;
- return (int)(self->ptr_ - self->buf_);
+ int available = self->max_ - (self->ptr_ - self->buf_);
+ int needed = (int)strlen(str);
+
+ if (needed >= available) {
+ // not enough space, expand the buffer (minimum expansion = 1024)
+ int off = (int)(self->ptr_ - self->buf_);
+ self->max_ += max(needed, 1024);
+ self->buf_ = (char *)aRealloc(self->buf_, self->max_ + 1);
+ self->ptr_ = self->buf_ + off;
+ }
+
+ memcpy(self->ptr_, str, needed);
+ self->ptr_ += needed;
+ return (int)(self->ptr_ - self->buf_);
}
// Returns the length of the data in the Stringbuf
-int StringBuf_Length(StringBuf* self)
+int StringBuf_Length(StringBuf *self)
{
- return (int)(self->ptr_ - self->buf_);
+ return (int)(self->ptr_ - self->buf_);
}
/// Returns the data in the StringBuf
-char* StringBuf_Value(StringBuf* self)
+char *StringBuf_Value(StringBuf *self)
{
- *self->ptr_ = '\0';
- return self->buf_;
+ *self->ptr_ = '\0';
+ return self->buf_;
}
/// Clears the contents of the StringBuf
-void StringBuf_Clear(StringBuf* self)
+void StringBuf_Clear(StringBuf *self)
{
- self->ptr_ = self->buf_;
+ self->ptr_ = self->buf_;
}
/// Destroys the StringBuf
-void StringBuf_Destroy(StringBuf* self)
+void StringBuf_Destroy(StringBuf *self)
{
- aFree(self->buf_);
- self->ptr_ = self->buf_ = 0;
- self->max_ = 0;
+ aFree(self->buf_);
+ self->ptr_ = self->buf_ = 0;
+ self->max_ = 0;
}
// Frees a StringBuf returned by StringBuf_Malloc
-void StringBuf_Free(StringBuf* self)
+void StringBuf_Free(StringBuf *self)
{
- StringBuf_Destroy(self);
- aFree(self);
+ StringBuf_Destroy(self);
+ aFree(self);
}
diff --git a/src/common/strlib.h b/src/common/strlib.h
index bbc2c6105..ae4f688c2 100644
--- a/src/common/strlib.h
+++ b/src/common/strlib.h
@@ -11,66 +11,65 @@
#include <string.h>
#undef __USE_GNU
-char* jstrescape (char* pt);
-char* jstrescapecpy (char* pt, const char* spt);
-int jmemescapecpy (char* pt, const char* spt, int size);
+char *jstrescape(char *pt);
+char *jstrescapecpy(char *pt, const char *spt);
+int jmemescapecpy(char *pt, const char *spt, int size);
-int remove_control_chars(char* str);
-char* trim(char* str);
-char* normalize_name(char* str,const char* delims);
+int remove_control_chars(char *str);
+char *trim(char *str);
+char *normalize_name(char *str,const char *delims);
const char *stristr(const char *haystack, const char *needle);
#ifdef WIN32
#define HAVE_STRTOK_R
#define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr))
-char* _strtok_r(char* s1, const char* s2, char** lasts);
+char *_strtok_r(char *s1, const char *s2, char **lasts);
#endif
#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN)
-size_t strnlen (const char* string, size_t maxlen);
+size_t strnlen(const char *string, size_t maxlen);
#endif
#if defined(WIN32) && defined(_MSC_VER) && _MSC_VER <= 1200
-uint64 strtoull(const char* str, char** endptr, int base);
+uint64 strtoull(const char *str, char **endptr, int base);
#endif
-int e_mail_check(char* email);
-int config_switch(const char* str);
+int e_mail_check(char *email);
+int config_switch(const char *str);
/// strncpy that always nul-terminates the string
-char* safestrncpy(char* dst, const char* src, size_t n);
+char *safestrncpy(char *dst, const char *src, size_t n);
/// doesn't crash on null pointer
-size_t safestrnlen(const char* string, size_t maxlen);
+size_t safestrnlen(const char *string, size_t maxlen);
/// Works like snprintf, but always nul-terminates the buffer.
/// Returns the size of the string (without nul-terminator)
/// or -1 if the buffer is too small.
-int safesnprintf(char* buf, size_t sz, const char* fmt, ...);
+int safesnprintf(char *buf, size_t sz, const char *fmt, ...);
/// Returns the line of the target position in the string.
/// Lines start at 1.
-int strline(const char* str, size_t pos);
+int strline(const char *str, size_t pos);
/// Produces the hexadecimal representation of the given input.
/// The output buffer must be at least count*2+1 in size.
/// Returns true on success, false on failure.
-bool bin2hex(char* output, unsigned char* input, size_t count);
+bool bin2hex(char *output, unsigned char *input, size_t count);
/// Bitfield determining the behaviour of sv_parse and sv_split.
-typedef enum e_svopt
-{
- // default: no escapes and no line terminator
- SV_NOESCAPE_NOTERMINATE = 0,
- // Escapes according to the C compiler.
- SV_ESCAPE_C = 1,
- // Line terminators
- SV_TERMINATE_LF = 2,
- SV_TERMINATE_CRLF = 4,
- SV_TERMINATE_CR = 8,
- // If sv_split keeps the end of line terminator, instead of replacing with '\0'
- SV_KEEP_TERMINATOR = 16
+typedef enum e_svopt {
+ // default: no escapes and no line terminator
+ SV_NOESCAPE_NOTERMINATE = 0,
+ // Escapes according to the C compiler.
+ SV_ESCAPE_C = 1,
+ // Line terminators
+ SV_TERMINATE_LF = 2,
+ SV_TERMINATE_CRLF = 4,
+ SV_TERMINATE_CR = 8,
+ // If sv_split keeps the end of line terminator, instead of replacing with '\0'
+ SV_KEEP_TERMINATOR = 16
} e_svopt;
/// Other escape sequences supported by the C compiler.
@@ -78,16 +77,15 @@ typedef enum e_svopt
/// 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
+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.
@@ -95,14 +93,14 @@ struct s_svstate
///
/// @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);
+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.
/// Other position pairs are the start and end of fields.
/// Returns the number of fields found or -1 if an error occurs.
-int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt);
+int sv_parse(const char *str, int len, int startoff, char delim, int *out_pos, int npos, enum e_svopt opt);
/// Splits a delim-separated string.
/// WARNING: this function modifies the input string
@@ -110,46 +108,45 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
/// out_fields[0] is the start of the next line.
/// Other entries are the start of fields (nul-teminated).
/// Returns the number of fields found or -1 if an error occurs.
-int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt);
+int sv_split(char *str, int len, int startoff, char delim, char **out_fields, int nfields, enum e_svopt opt);
/// Escapes src to out_dest according to the format of the C compiler.
/// Returns the length of the escaped string.
/// out_dest should be len*4+1 in size.
-size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* escapes);
+size_t sv_escape_c(char *out_dest, const char *src, size_t len, const char *escapes);
/// Unescapes src to out_dest according to the format of the C compiler.
/// Returns the length of the unescaped string.
/// out_dest should be len+1 in size and can be the same buffer as src.
-size_t sv_unescape_c(char* out_dest, const char* src, size_t len);
+size_t sv_unescape_c(char *out_dest, const char *src, size_t len);
/// Skips a C escape sequence (starting with '\\').
-const char* skip_escaped_c(const char* p);
+const char *skip_escaped_c(const char *p);
/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
/// Tracks the progress of the operation (current line number, number of successfully processed rows).
/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
-bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current));
+bool sv_readdb(const char *directory, const char *filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char *fields[], int columns, int current));
/// StringBuf - dynamic string
-struct StringBuf
-{
- char *buf_;
- char *ptr_;
- unsigned int max_;
+struct StringBuf {
+ char *buf_;
+ char *ptr_;
+ unsigned int max_;
};
typedef struct StringBuf StringBuf;
-StringBuf* StringBuf_Malloc(void);
-void StringBuf_Init(StringBuf* self);
-int StringBuf_Printf(StringBuf* self, const char* fmt, ...);
-int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list args);
-int StringBuf_Append(StringBuf* self, const StringBuf *sbuf);
-int StringBuf_AppendStr(StringBuf* self, const char* str);
-int StringBuf_Length(StringBuf* self);
-char* StringBuf_Value(StringBuf* self);
-void StringBuf_Clear(StringBuf* self);
-void StringBuf_Destroy(StringBuf* self);
-void StringBuf_Free(StringBuf* self);
+StringBuf *StringBuf_Malloc(void);
+void StringBuf_Init(StringBuf *self);
+int StringBuf_Printf(StringBuf *self, const char *fmt, ...);
+int StringBuf_Vprintf(StringBuf *self, const char *fmt, va_list args);
+int StringBuf_Append(StringBuf *self, const StringBuf *sbuf);
+int StringBuf_AppendStr(StringBuf *self, const char *str);
+int StringBuf_Length(StringBuf *self);
+char *StringBuf_Value(StringBuf *self);
+void StringBuf_Clear(StringBuf *self);
+void StringBuf_Destroy(StringBuf *self);
+void StringBuf_Free(StringBuf *self);
#endif /* _STRLIB_H_ */
diff --git a/src/common/thread.c b/src/common/thread.c
index 315b310b2..610ee394c 100644
--- a/src/common/thread.c
+++ b/src/common/thread.c
@@ -9,7 +9,7 @@
#ifdef WIN32
#include "../common/winapi.h"
#define getpagesize() 4096 // @TODO: implement this properly (GetSystemInfo .. dwPageSize..). (Atm as on all supported win platforms its 4k its static.)
-#define __thread __declspec( thread )
+#define __thread __declspec( thread )
#else
#include <stdlib.h>
#include <unistd.h>
@@ -25,25 +25,25 @@
#include "thread.h"
// When Compiling using MSC (on win32..) we know we have support in any case!
-#ifdef _MSC_VER
-#define HAS_TLS
+#ifdef _MSC_VER
+#define HAS_TLS
#endif
#define RA_THREADS_MAX 64
struct rAthread {
- unsigned int myID;
-
- RATHREAD_PRIO prio;
- rAthreadProc proc;
- void *param;
-
- #ifdef WIN32
- HANDLE hThread;
- #else
- pthread_t hThread;
- #endif
+ unsigned int myID;
+
+ RATHREAD_PRIO prio;
+ rAthreadProc proc;
+ void *param;
+
+#ifdef WIN32
+ HANDLE hThread;
+#else
+ pthread_t hThread;
+#endif
};
@@ -57,95 +57,100 @@ __thread int g_rathread_ID = -1;
///
static struct rAthread l_threads[RA_THREADS_MAX];
-void rathread_init(){
- register unsigned int i;
- memset(&l_threads, 0x00, RA_THREADS_MAX * sizeof(struct rAthread) );
-
- for(i = 0; i < RA_THREADS_MAX; i++){
- l_threads[i].myID = i;
- }
+void rathread_init()
+{
+ register unsigned int i;
+ memset(&l_threads, 0x00, RA_THREADS_MAX * sizeof(struct rAthread));
+
+ for (i = 0; i < RA_THREADS_MAX; i++) {
+ l_threads[i].myID = i;
+ }
- // now lets init thread id 0, which represnts the main thread
+ // now lets init thread id 0, which represnts the main thread
#ifdef HAS_TLS
- g_rathread_ID = 0;
+ g_rathread_ID = 0;
#endif
- l_threads[0].prio = RAT_PRIO_NORMAL;
- l_threads[0].proc = (rAthreadProc)0xDEADCAFE;
+ l_threads[0].prio = RAT_PRIO_NORMAL;
+ l_threads[0].proc = (rAthreadProc)0xDEADCAFE;
}//end: rathread_init()
-void rathread_final(){
- register unsigned int i;
-
- // Unterminated Threads Left?
- // Should'nt happen ..
- // Kill 'em all!
- //
- for(i = 1; i < RA_THREADS_MAX; i++){
- if(l_threads[i].proc != NULL){
- ShowWarning("rAthread_final: unterminated Thread (tid %u entryPoint %p) - forcing to terminate (kill)\n", i, l_threads[i].proc);
- rathread_destroy(&l_threads[i]);
- }
- }
-
-
+void rathread_final()
+{
+ register unsigned int i;
+
+ // Unterminated Threads Left?
+ // Should'nt happen ..
+ // Kill 'em all!
+ //
+ for (i = 1; i < RA_THREADS_MAX; i++) {
+ if (l_threads[i].proc != NULL) {
+ ShowWarning("rAthread_final: unterminated Thread (tid %u entryPoint %p) - forcing to terminate (kill)\n", i, l_threads[i].proc);
+ rathread_destroy(&l_threads[i]);
+ }
+ }
+
+
}//end: rathread_final()
// gets called whenever a thread terminated ..
-static void rat_thread_terminated( rAthread handle ){
+static void rat_thread_terminated(rAthread handle)
+{
- int id_backup = handle->myID;
+ int id_backup = handle->myID;
- // Simply set all members to 0 (except the id)
- memset(handle, 0x00, sizeof(struct rAthread));
-
- handle->myID = id_backup; // done ;)
+ // Simply set all members to 0 (except the id)
+ memset(handle, 0x00, sizeof(struct rAthread));
+
+ handle->myID = id_backup; // done ;)
}//end: rat_thread_terminated()
#ifdef WIN32
-DWORD WINAPI _raThreadMainRedirector(LPVOID p){
+DWORD WINAPI _raThreadMainRedirector(LPVOID p)
+{
#else
-static void *_raThreadMainRedirector( void *p ){
- sigset_t set; // on Posix Thread platforms
+static void *_raThreadMainRedirector(void *p)
+{
+ sigset_t set; // on Posix Thread platforms
#endif
- void *ret;
-
- // Update myID @ TLS to right id.
+ void *ret;
+
+ // Update myID @ TLS to right id.
#ifdef HAS_TLS
- g_rathread_ID = ((rAthread)p)->myID;
+ g_rathread_ID = ((rAthread)p)->myID;
#endif
#ifndef WIN32
- // When using posix threads
- // the threads inherits the Signal mask from the thread which's spawned
- // this thread
- // so we've to block everything we dont care about.
- sigemptyset(&set);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGTERM);
- sigaddset(&set, SIGPIPE);
-
- pthread_sigmask(SIG_BLOCK, &set, NULL);
-
+ // When using posix threads
+ // the threads inherits the Signal mask from the thread which's spawned
+ // this thread
+ // so we've to block everything we dont care about.
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGTERM);
+ sigaddset(&set, SIGPIPE);
+
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
#endif
- ret = ((rAthread)p)->proc( ((rAthread)p)->param ) ;
+ ret = ((rAthread)p)->proc(((rAthread)p)->param) ;
-#ifdef WIN32
- CloseHandle( ((rAthread)p)->hThread );
+#ifdef WIN32
+ CloseHandle(((rAthread)p)->hThread);
#endif
- rat_thread_terminated( (rAthread)p );
+ rat_thread_terminated((rAthread)p);
#ifdef WIN32
- return (DWORD)ret;
+ return (DWORD)ret;
#else
- return ret;
+ return ret;
#endif
}//end: _raThreadMainRedirector()
@@ -155,163 +160,172 @@ static void *_raThreadMainRedirector( void *p ){
///
/// API Level
-///
-rAthread rathread_create( rAthreadProc entryPoint, void *param ){
- return rathread_createEx( entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL );
+///
+rAthread rathread_create(rAthreadProc entryPoint, void *param)
+{
+ return rathread_createEx(entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL);
}//end: rathread_create()
-rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio ){
+rAthread rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio)
+{
#ifndef WIN32
- pthread_attr_t attr;
+ pthread_attr_t attr;
#endif
- size_t tmp;
- unsigned int i;
- rAthread handle = NULL;
-
-
- // given stacksize aligned to systems pagesize?
- tmp = szStack % getpagesize();
- if(tmp != 0)
- szStack += tmp;
-
-
- // Get a free Thread Slot.
- for(i = 0; i < RA_THREADS_MAX; i++){
- if(l_threads[i].proc == NULL){
- handle = &l_threads[i];
- break;
- }
- }
-
- if(handle == NULL){
- ShowError("rAthread: cannot create new thread (entryPoint: %p) - no free thread slot found!", entryPoint);
- return NULL;
- }
-
-
-
- handle->proc = entryPoint;
- handle->param = param;
+ size_t tmp;
+ unsigned int i;
+ rAthread handle = NULL;
+
+
+ // given stacksize aligned to systems pagesize?
+ tmp = szStack % getpagesize();
+ if (tmp != 0)
+ szStack += tmp;
+
+
+ // Get a free Thread Slot.
+ for (i = 0; i < RA_THREADS_MAX; i++) {
+ if (l_threads[i].proc == NULL) {
+ handle = &l_threads[i];
+ break;
+ }
+ }
+
+ if (handle == NULL) {
+ ShowError("rAthread: cannot create new thread (entryPoint: %p) - no free thread slot found!", entryPoint);
+ return NULL;
+ }
+
+
+
+ handle->proc = entryPoint;
+ handle->param = param;
#ifdef WIN32
- handle->hThread = CreateThread(NULL, szStack, _raThreadMainRedirector, (void*)handle, 0, NULL);
+ handle->hThread = CreateThread(NULL, szStack, _raThreadMainRedirector, (void *)handle, 0, NULL);
#else
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, szStack);
-
- if(pthread_create(&handle->hThread, &attr, _raThreadMainRedirector, (void*)handle) != 0){
- handle->proc = NULL;
- handle->param = NULL;
- return NULL;
- }
- pthread_attr_destroy(&attr);
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, szStack);
+
+ if (pthread_create(&handle->hThread, &attr, _raThreadMainRedirector, (void *)handle) != 0) {
+ handle->proc = NULL;
+ handle->param = NULL;
+ return NULL;
+ }
+ pthread_attr_destroy(&attr);
#endif
- rathread_prio_set( handle, prio );
-
- return handle;
+ rathread_prio_set(handle, prio);
+
+ return handle;
}//end: rathread_createEx
-void rathread_destroy ( rAthread handle ){
+void rathread_destroy(rAthread handle)
+{
#ifdef WIN32
- if( TerminateThread(handle->hThread, 0) != FALSE){
- CloseHandle(handle->hThread);
- rat_thread_terminated(handle);
- }
+ if (TerminateThread(handle->hThread, 0) != FALSE) {
+ CloseHandle(handle->hThread);
+ rat_thread_terminated(handle);
+ }
#else
- if( pthread_cancel( handle->hThread ) == 0){
-
- // We have to join it, otherwise pthread wont re-cycle its internal ressources assoc. with this thread.
- //
- pthread_join( handle->hThread, NULL );
-
- // Tell our manager to release ressources ;)
- rat_thread_terminated(handle);
- }
+ if (pthread_cancel(handle->hThread) == 0) {
+
+ // We have to join it, otherwise pthread wont re-cycle its internal ressources assoc. with this thread.
+ //
+ pthread_join(handle->hThread, NULL);
+
+ // Tell our manager to release ressources ;)
+ rat_thread_terminated(handle);
+ }
#endif
}//end: rathread_destroy()
-rAthread rathread_self( ){
+rAthread rathread_self()
+{
#ifdef HAS_TLS
- rAthread handle = &l_threads[g_rathread_ID];
-
- if(handle->proc != NULL) // entry point set, so its used!
- return handle;
+ rAthread handle = &l_threads[g_rathread_ID];
+
+ if (handle->proc != NULL) // entry point set, so its used!
+ return handle;
#else
- // .. so no tls means we have to search the thread by its api-handle ..
- int i;
-
- #ifdef WIN32
- HANDLE hSelf;
- hSelf = GetCurrent = GetCurrentThread();
- #else
- pthread_t hSelf;
- hSelf = pthread_self();
- #endif
-
- for(i = 0; i < RA_THREADS_MAX; i++){
- if(l_threads[i].hThread == hSelf && l_threads[i].proc != NULL)
- return &l_threads[i];
- }
-
+ // .. so no tls means we have to search the thread by its api-handle ..
+ int i;
+
+#ifdef WIN32
+ HANDLE hSelf;
+ hSelf = GetCurrent = GetCurrentThread();
+#else
+ pthread_t hSelf;
+ hSelf = pthread_self();
+#endif
+
+ for (i = 0; i < RA_THREADS_MAX; i++) {
+ if (l_threads[i].hThread == hSelf && l_threads[i].proc != NULL)
+ return &l_threads[i];
+ }
+
#endif
-
- return NULL;
+
+ return NULL;
}//end: rathread_self()
-int rathread_get_tid(){
+int rathread_get_tid()
+{
-#ifdef HAS_TLS
- return g_rathread_ID;
+#ifdef HAS_TLS
+ return g_rathread_ID;
#else
- // todo
- #ifdef WIN32
- return (int)GetCurrentThreadId();
- #else
- return (intptr_t)pthread_self();
- #endif
-
+ // todo
+#ifdef WIN32
+ return (int)GetCurrentThreadId();
+#else
+ return (intptr_t)pthread_self();
+#endif
+
#endif
-
+
}//end: rathread_get_tid()
-bool rathread_wait( rAthread handle, void* *out_exitCode ){
-
- // Hint:
- // no thread data cleanup routine call here!
- // its managed by the callProxy itself..
- //
+bool rathread_wait(rAthread handle, void* *out_exitCode)
+{
+
+ // Hint:
+ // no thread data cleanup routine call here!
+ // its managed by the callProxy itself..
+ //
#ifdef WIN32
- WaitForSingleObject(handle->hThread, INFINITE);
- return true;
+ WaitForSingleObject(handle->hThread, INFINITE);
+ return true;
#else
- if(pthread_join(handle->hThread, out_exitCode) == 0)
- return true;
- return false;
+ if (pthread_join(handle->hThread, out_exitCode) == 0)
+ return true;
+ return false;
#endif
}//end: rathread_wait()
-void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio ){
- handle->prio = RAT_PRIO_NORMAL;
- //@TODO
+void rathread_prio_set(rAthread handle, RATHREAD_PRIO prio)
+{
+ handle->prio = RAT_PRIO_NORMAL;
+ //@TODO
}//end: rathread_prio_set()
-RATHREAD_PRIO rathread_prio_get( rAthread handle){
- return handle->prio;
+RATHREAD_PRIO rathread_prio_get(rAthread handle)
+{
+ return handle->prio;
}//end: rathread_prio_get()
-void rathread_yield(){
-#ifdef WIN32
- SwitchToThread();
+void rathread_yield()
+{
+#ifdef WIN32
+ SwitchToThread();
#else
- sched_yield();
-#endif
+ sched_yield();
+#endif
}//end: rathread_yield()
diff --git a/src/common/thread.h b/src/common/thread.h
index a5a66e954..cfbfe689f 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -1,19 +1,19 @@
// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#pragma once
+#pragma once
#ifndef _rA_THREAD_H_
#define _rA_THREAD_H_
#include "../common/cbasetypes.h"
typedef struct rAthread *rAthread;
-typedef void* (*rAthreadProc)(void*);
+typedef void *(*rAthreadProc)(void *);
typedef enum RATHREAD_PRIO {
- RAT_PRIO_LOW = 0,
- RAT_PRIO_NORMAL,
- RAT_PRIO_HIGH
+ RAT_PRIO_LOW = 0,
+ RAT_PRIO_NORMAL,
+ RAT_PRIO_HIGH
} RATHREAD_PRIO;
@@ -22,51 +22,51 @@ typedef enum RATHREAD_PRIO {
*
* @param entyPoint - entryProc,
* @param param - general purpose parameter, would be given as parameter to the thread's entrypoint.
- *
+ *
* @return not NULL if success
*/
-rAthread rathread_create( rAthreadProc entryPoint, void *param );
+rAthread rathread_create(rAthreadProc entryPoint, void *param);
-/**
+/**
* Creates a new Thread (with more creation options)
*
* @param entyPoint - entryProc,
* @param param - general purpose parameter, would be given as parameter to the thread's entrypoint
- * @param szStack - stack Size in bytes
+ * @param szStack - stack Size in bytes
* @param prio - Priority of the Thread @ OS Scheduler..
*
* @return not NULL if success
*/
-rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio );
+rAthread rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio);
/**
* Destroys the given Thread immediatly
*
- * @note The Handle gets invalid after call! dont use it afterwards.
+ * @note The Handle gets invalid after call! dont use it afterwards.
*
* @param handle - thread to destroy.
*/
-void rathread_destroy ( rAthread handle );
+void rathread_destroy(rAthread handle);
-/**
+/**
* Returns the thread handle of the thread calling this function
- *
+ *
* @note this wont work @ programms main thread
- * @note the underlying implementation might not perform very well, cache the value received!
- *
+ * @note the underlying implementation might not perform very well, cache the value received!
+ *
* @return not NULL if success
*/
-rAthread rathread_self( );
+rAthread rathread_self();
/**
- * Returns own thrad id (TID)
+ * Returns own thrad id (TID)
*
- * @note this is an unique identifier for the calling thread, and
- * depends on platfrom / compiler, and may not be the systems Thread ID!
+ * @note this is an unique identifier for the calling thread, and
+ * depends on platfrom / compiler, and may not be the systems Thread ID!
*
* @return -1 when fails, otherwise >= 0
*/
@@ -74,39 +74,39 @@ int rathread_get_tid();
/**
- * Waits for the given thread to terminate
+ * Waits for the given thread to terminate
*
* @param handle - thread to wait (join) for
* @param out_Exitcode - [OPTIONAL] - if given => Exitcode (value) of the given thread - if it's terminated
- *
+ *
* @return true - if the given thread has been terminated.
*/
-bool rathread_wait( rAthread handle, void* *out_exitCode );
+bool rathread_wait(rAthread handle, void* *out_exitCode);
-/**
+/**
* Sets the given PRIORITY @ OS Task Scheduler
- *
+ *
* @param handle - thread to set prio for
* @param rio - the priority (RAT_PRIO_LOW ... )
*/
-void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio );
+void rathread_prio_set(rAthread handle, RATHREAD_PRIO prio);
-/**
+/**
* Gets the current Prio of the given trhead
*
* @param handle - the thread to get the prio for.
*/
-RATHREAD_PRIO rathread_prio_get( rAthread handle);
+RATHREAD_PRIO rathread_prio_get(rAthread handle);
/**
* Tells the OS scheduler to yield the execution of the calling thread
- *
+ *
* @note: this will not "pause" the thread,
- * it just allows the OS to spent the remaining time
- * of the slice to another thread.
+ * it just allows the OS to spent the remaining time
+ * of the slice to another thread.
*/
void rathread_yield();
diff --git a/src/common/timer.c b/src/common/timer.c
index c239a9d70..bb2458233 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -26,12 +26,12 @@
#define TIMER_MAX_INTERVAL 1000
// timers (array)
-static struct TimerData* timer_data = NULL;
+static struct TimerData *timer_data = NULL;
static int timer_data_max = 0;
static int timer_data_num = 0;
// free timers (array)
-static int* free_timer_list = NULL;
+static int *free_timer_list = NULL;
static int free_timer_list_max = 0;
static int free_timer_list_pos = 0;
@@ -53,85 +53,87 @@ time_t start_time;
/*----------------------------
- * Timer debugging
+ * Timer debugging
*----------------------------*/
struct timer_func_list {
- struct timer_func_list* next;
- TimerFunc func;
- char* name;
+ struct timer_func_list *next;
+ TimerFunc func;
+ char *name;
} *tfl_root = NULL;
/// Sets the name of a timer function.
-int add_timer_func_list(TimerFunc func, char* name)
+int add_timer_func_list(TimerFunc func, char *name)
{
- struct timer_func_list* tfl;
-
- if (name) {
- for( tfl=tfl_root; tfl != NULL; tfl=tfl->next )
- {// check suspicious cases
- if( func == tfl->func )
- ShowWarning("add_timer_func_list: duplicating function %p(%s) as %s.\n",tfl->func,tfl->name,name);
- else if( strcmp(name,tfl->name) == 0 )
- ShowWarning("add_timer_func_list: function %p has the same name as %p(%s)\n",func,tfl->func,tfl->name);
- }
- CREATE(tfl,struct timer_func_list,1);
- tfl->next = tfl_root;
- tfl->func = func;
- tfl->name = aStrdup(name);
- tfl_root = tfl;
- }
- return 0;
+ struct timer_func_list *tfl;
+
+ if (name) {
+ for (tfl=tfl_root; tfl != NULL; tfl=tfl->next) {
+ // check suspicious cases
+ if (func == tfl->func)
+ ShowWarning("add_timer_func_list: duplicating function %p(%s) as %s.\n",tfl->func,tfl->name,name);
+ else if (strcmp(name,tfl->name) == 0)
+ ShowWarning("add_timer_func_list: function %p has the same name as %p(%s)\n",func,tfl->func,tfl->name);
+ }
+ CREATE(tfl,struct timer_func_list,1);
+ tfl->next = tfl_root;
+ tfl->func = func;
+ tfl->name = aStrdup(name);
+ tfl_root = tfl;
+ }
+ return 0;
}
/// Returns the name of the timer function.
-char* search_timer_func_list(TimerFunc func)
+char *search_timer_func_list(TimerFunc func)
{
- struct timer_func_list* tfl;
+ struct timer_func_list *tfl;
- for( tfl=tfl_root; tfl != NULL; tfl=tfl->next )
- if (func == tfl->func)
- return tfl->name;
+ for (tfl=tfl_root; tfl != NULL; tfl=tfl->next)
+ if (func == tfl->func)
+ return tfl->name;
- return "unknown timer function";
+ return "unknown timer function";
}
/*----------------------------
- * Get tick time
+ * Get tick time
*----------------------------*/
#if defined(ENABLE_RDTSC)
static uint64 RDTSC_BEGINTICK = 0, RDTSC_CLOCK = 0;
-static __inline uint64 _rdtsc(){
- register union{
- uint64 qw;
- uint32 dw[2];
- } t;
+static __inline uint64 _rdtsc()
+{
+ register union {
+ uint64 qw;
+ uint32 dw[2];
+ } t;
+
+ asm volatile("rdtsc":"=a"(t.dw[0]), "=d"(t.dw[1]));
- asm volatile("rdtsc":"=a"(t.dw[0]), "=d"(t.dw[1]) );
-
- return t.qw;
+ return t.qw;
}
-static void rdtsc_calibrate(){
- uint64 t1, t2;
- int32 i;
-
- ShowStatus("Calibrating Timer Source, please wait... ");
-
- RDTSC_CLOCK = 0;
-
- for(i = 0; i < 5; i++){
- t1 = _rdtsc();
- usleep(1000000); //1000 MS
- t2 = _rdtsc();
- RDTSC_CLOCK += (t2 - t1) / 1000;
- }
- RDTSC_CLOCK /= 5;
-
- RDTSC_BEGINTICK = _rdtsc();
-
- ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000) );
+static void rdtsc_calibrate()
+{
+ uint64 t1, t2;
+ int32 i;
+
+ ShowStatus("Calibrating Timer Source, please wait... ");
+
+ RDTSC_CLOCK = 0;
+
+ for (i = 0; i < 5; i++) {
+ t1 = _rdtsc();
+ usleep(1000000); //1000 MS
+ t2 = _rdtsc();
+ RDTSC_CLOCK += (t2 - t1) / 1000;
+ }
+ RDTSC_CLOCK /= 5;
+
+ RDTSC_BEGINTICK = _rdtsc();
+
+ ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000));
}
#endif
@@ -140,19 +142,19 @@ static void rdtsc_calibrate(){
static unsigned int tick(void)
{
#if defined(WIN32)
- return GetTickCount();
+ return GetTickCount();
#elif defined(ENABLE_RDTSC)
- //
- return (unsigned int)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK);
- //
+ //
+ return (unsigned int)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK);
+ //
#elif defined(HAVE_MONOTONIC_CLOCK)
- struct timespec tval;
- clock_gettime(CLOCK_MONOTONIC, &tval);
- return tval.tv_sec * 1000 + tval.tv_nsec / 1000000;
+ struct timespec tval;
+ clock_gettime(CLOCK_MONOTONIC, &tval);
+ return tval.tv_sec * 1000 + tval.tv_nsec / 1000000;
#else
- struct timeval tval;
- gettimeofday(&tval, NULL);
- return tval.tv_sec * 1000 + tval.tv_usec / 1000;
+ struct timeval tval;
+ gettimeofday(&tval, NULL);
+ return tval.tv_sec * 1000 + tval.tv_usec / 1000;
#endif
}
@@ -165,14 +167,14 @@ static int gettick_count = 1;
unsigned int gettick_nocache(void)
{
- gettick_count = TICK_CACHE;
- gettick_cache = tick();
- return gettick_cache;
+ gettick_count = TICK_CACHE;
+ gettick_cache = tick();
+ return gettick_cache;
}
unsigned int gettick(void)
{
- return ( --gettick_count == 0 ) ? gettick_nocache() : gettick_cache;
+ return (--gettick_count == 0) ? gettick_nocache() : gettick_cache;
}
//////////////////////////////
#else
@@ -180,110 +182,108 @@ unsigned int gettick(void)
// tick doesn't get cached
unsigned int gettick_nocache(void)
{
- return tick();
+ return tick();
}
unsigned int gettick(void)
{
- return tick();
+ return tick();
}
//////////////////////////////////////////////////////////////////////////
#endif
//////////////////////////////////////////////////////////////////////////
/*======================================
- * CORE : Timer Heap
+ * CORE : Timer Heap
*--------------------------------------*/
/// Adds a timer to the timer_heap
static void push_timer_heap(int tid)
{
- BHEAP_ENSURE(timer_heap, 1, 256);
- BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP);
+ BHEAP_ENSURE(timer_heap, 1, 256);
+ BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP);
}
/*==========================
- * Timer Management
+ * Timer Management
*--------------------------*/
/// Returns a free timer id.
static int acquire_timer(void)
{
- int tid;
-
- // select a free timer
- if (free_timer_list_pos) {
- do {
- tid = free_timer_list[--free_timer_list_pos];
- } while(tid >= timer_data_num && free_timer_list_pos > 0);
- } else
- tid = timer_data_num;
-
- // check available space
- if( tid >= timer_data_num )
- for (tid = timer_data_num; tid < timer_data_max && timer_data[tid].type; tid++);
- if (tid >= timer_data_num && tid >= timer_data_max)
- {// expand timer array
- timer_data_max += 256;
- if( timer_data )
- RECREATE(timer_data, struct TimerData, timer_data_max);
- else
- CREATE(timer_data, struct TimerData, timer_data_max);
- memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData)*256);
- }
-
- if( tid >= timer_data_num )
- timer_data_num = tid + 1;
-
- return tid;
+ int tid;
+
+ // select a free timer
+ if (free_timer_list_pos) {
+ do {
+ tid = free_timer_list[--free_timer_list_pos];
+ } while (tid >= timer_data_num && free_timer_list_pos > 0);
+ } else
+ tid = timer_data_num;
+
+ // check available space
+ if (tid >= timer_data_num)
+ for (tid = timer_data_num; tid < timer_data_max && timer_data[tid].type; tid++);
+ if (tid >= timer_data_num && tid >= timer_data_max) {
+ // expand timer array
+ timer_data_max += 256;
+ if (timer_data)
+ RECREATE(timer_data, struct TimerData, timer_data_max);
+ else
+ CREATE(timer_data, struct TimerData, timer_data_max);
+ memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData)*256);
+ }
+
+ if (tid >= timer_data_num)
+ timer_data_num = tid + 1;
+
+ return tid;
}
/// 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_t data)
{
- int tid;
-
- tid = acquire_timer();
- timer_data[tid].tick = tick;
- timer_data[tid].func = func;
- timer_data[tid].id = id;
- timer_data[tid].data = data;
- timer_data[tid].type = TIMER_ONCE_AUTODEL;
- timer_data[tid].interval = 1000;
- push_timer_heap(tid);
-
- return tid;
+ int tid;
+
+ tid = acquire_timer();
+ timer_data[tid].tick = tick;
+ timer_data[tid].func = func;
+ timer_data[tid].id = id;
+ timer_data[tid].data = data;
+ timer_data[tid].type = TIMER_ONCE_AUTODEL;
+ timer_data[tid].interval = 1000;
+ push_timer_heap(tid);
+
+ return tid;
}
/// 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_t data, int interval)
{
- int tid;
-
- if( interval < 1 )
- {
- ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick()));
- return INVALID_TIMER;
- }
-
- tid = acquire_timer();
- timer_data[tid].tick = tick;
- timer_data[tid].func = func;
- timer_data[tid].id = id;
- timer_data[tid].data = data;
- timer_data[tid].type = TIMER_INTERVAL;
- timer_data[tid].interval = interval;
- push_timer_heap(tid);
-
- return tid;
+ int tid;
+
+ if (interval < 1) {
+ ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick()));
+ return INVALID_TIMER;
+ }
+
+ tid = acquire_timer();
+ timer_data[tid].tick = tick;
+ timer_data[tid].func = func;
+ timer_data[tid].id = id;
+ timer_data[tid].data = data;
+ timer_data[tid].type = TIMER_INTERVAL;
+ timer_data[tid].interval = interval;
+ push_timer_heap(tid);
+
+ return tid;
}
/// Retrieves internal timer data
-const struct TimerData* get_timer(int tid)
-{
- return ( tid >= 0 && tid < timer_data_num ) ? &timer_data[tid] : NULL;
+const struct TimerData *get_timer(int tid) {
+ return (tid >= 0 && tid < timer_data_num) ? &timer_data[tid] : NULL;
}
/// Marks a timer specified by 'id' for immediate deletion once it expires.
@@ -291,142 +291,135 @@ const struct TimerData* get_timer(int tid)
/// Returns 0 on success, < 0 on failure.
int delete_timer(int tid, TimerFunc func)
{
- if( tid < 0 || tid >= timer_data_num )
- {
- ShowError("delete_timer error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func));
- return -1;
- }
- if( timer_data[tid].func != func )
- {
- ShowError("delete_timer error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func));
- return -2;
- }
-
- timer_data[tid].func = NULL;
- timer_data[tid].type = TIMER_ONCE_AUTODEL;
-
- return 0;
+ if (tid < 0 || tid >= timer_data_num) {
+ ShowError("delete_timer error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func));
+ return -1;
+ }
+ if (timer_data[tid].func != func) {
+ ShowError("delete_timer error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func));
+ return -2;
+ }
+
+ timer_data[tid].func = NULL;
+ timer_data[tid].type = TIMER_ONCE_AUTODEL;
+
+ return 0;
}
/// Adjusts a timer's expiration time.
/// Returns the new tick value, or -1 if it fails.
int addtick_timer(int tid, unsigned int tick)
{
- return settick_timer(tid, timer_data[tid].tick+tick);
+ return settick_timer(tid, timer_data[tid].tick+tick);
}
/// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one).
/// Returns the new tick value, or -1 if it fails.
int settick_timer(int tid, unsigned int tick)
{
- size_t i;
-
- // search timer position
- ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid);
- if( i == BHEAP_LENGTH(timer_heap) )
- {
- ShowError("settick_timer: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
- return -1;
- }
-
- if( (int)tick == -1 )
- tick = 0;// add 1ms to avoid the error value -1
-
- if( timer_data[tid].tick == tick )
- return (int)tick;// nothing to do, already in propper position
-
- // pop and push adjusted timer
- BHEAP_POPINDEX(timer_heap, i, DIFFTICK_MINTOPCMP);
- timer_data[tid].tick = tick;
- BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP);
- return (int)tick;
+ size_t i;
+
+ // search timer position
+ ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid);
+ if (i == BHEAP_LENGTH(timer_heap)) {
+ ShowError("settick_timer: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func));
+ return -1;
+ }
+
+ if ((int)tick == -1)
+ tick = 0;// add 1ms to avoid the error value -1
+
+ if (timer_data[tid].tick == tick)
+ return (int)tick;// nothing to do, already in propper position
+
+ // pop and push adjusted timer
+ BHEAP_POPINDEX(timer_heap, i, DIFFTICK_MINTOPCMP);
+ timer_data[tid].tick = tick;
+ BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP);
+ return (int)tick;
}
/// Executes all expired timers.
/// Returns the value of the smallest non-expired timer (or 1 second if there aren't any).
int do_timer(unsigned int tick)
{
- int diff = TIMER_MAX_INTERVAL; // return value
-
- // process all timers one by one
- while( BHEAP_LENGTH(timer_heap) )
- {
- int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick)
-
- diff = DIFF_TICK(timer_data[tid].tick, tick);
- if( diff > 0 )
- break; // no more expired timers to process
-
- // remove timer
- BHEAP_POP(timer_heap, DIFFTICK_MINTOPCMP);
- timer_data[tid].type |= TIMER_REMOVE_HEAP;
-
- if( timer_data[tid].func )
- {
- if( diff < -1000 )
- // timer was delayed for more than 1 second, use current tick instead
- timer_data[tid].func(tid, tick, timer_data[tid].id, timer_data[tid].data);
- else
- timer_data[tid].func(tid, timer_data[tid].tick, timer_data[tid].id, timer_data[tid].data);
- }
-
- // in the case the function didn't change anything...
- if( timer_data[tid].type & TIMER_REMOVE_HEAP )
- {
- timer_data[tid].type &= ~TIMER_REMOVE_HEAP;
-
- switch( timer_data[tid].type )
- {
- default:
- case TIMER_ONCE_AUTODEL:
- timer_data[tid].type = 0;
- if (free_timer_list_pos >= free_timer_list_max) {
- free_timer_list_max += 256;
- RECREATE(free_timer_list,int,free_timer_list_max);
- memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int));
- }
- free_timer_list[free_timer_list_pos++] = tid;
- break;
- case TIMER_INTERVAL:
- if( DIFF_TICK(timer_data[tid].tick, tick) < -1000 )
- timer_data[tid].tick = tick + timer_data[tid].interval;
- else
- timer_data[tid].tick += timer_data[tid].interval;
- push_timer_heap(tid);
- break;
- }
- }
- }
-
- return cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL);
+ int diff = TIMER_MAX_INTERVAL; // return value
+
+ // process all timers one by one
+ while (BHEAP_LENGTH(timer_heap)) {
+ int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick)
+
+ diff = DIFF_TICK(timer_data[tid].tick, tick);
+ if (diff > 0)
+ break; // no more expired timers to process
+
+ // remove timer
+ BHEAP_POP(timer_heap, DIFFTICK_MINTOPCMP);
+ timer_data[tid].type |= TIMER_REMOVE_HEAP;
+
+ if (timer_data[tid].func) {
+ if (diff < -1000)
+ // timer was delayed for more than 1 second, use current tick instead
+ timer_data[tid].func(tid, tick, timer_data[tid].id, timer_data[tid].data);
+ else
+ timer_data[tid].func(tid, timer_data[tid].tick, timer_data[tid].id, timer_data[tid].data);
+ }
+
+ // in the case the function didn't change anything...
+ if (timer_data[tid].type & TIMER_REMOVE_HEAP) {
+ timer_data[tid].type &= ~TIMER_REMOVE_HEAP;
+
+ switch (timer_data[tid].type) {
+ default:
+ case TIMER_ONCE_AUTODEL:
+ timer_data[tid].type = 0;
+ if (free_timer_list_pos >= free_timer_list_max) {
+ free_timer_list_max += 256;
+ RECREATE(free_timer_list,int,free_timer_list_max);
+ memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int));
+ }
+ free_timer_list[free_timer_list_pos++] = tid;
+ break;
+ case TIMER_INTERVAL:
+ if (DIFF_TICK(timer_data[tid].tick, tick) < -1000)
+ timer_data[tid].tick = tick + timer_data[tid].interval;
+ else
+ timer_data[tid].tick += timer_data[tid].interval;
+ push_timer_heap(tid);
+ break;
+ }
+ }
+ }
+
+ return cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL);
}
unsigned long get_uptime(void)
{
- return (unsigned long)difftime(time(NULL), start_time);
+ return (unsigned long)difftime(time(NULL), start_time);
}
void timer_init(void)
{
#if defined(ENABLE_RDTSC)
- rdtsc_calibrate();
+ rdtsc_calibrate();
#endif
- time(&start_time);
+ time(&start_time);
}
void timer_final(void)
{
- struct timer_func_list *tfl;
- struct timer_func_list *next;
-
- for( tfl=tfl_root; tfl != NULL; tfl = next ) {
- next = tfl->next; // copy next pointer
- aFree(tfl->name); // free structures
- aFree(tfl);
- }
-
- if (timer_data) aFree(timer_data);
- BHEAP_CLEAR(timer_heap);
- if (free_timer_list) aFree(free_timer_list);
+ struct timer_func_list *tfl;
+ struct timer_func_list *next;
+
+ for (tfl=tfl_root; tfl != NULL; tfl = next) {
+ next = tfl->next; // copy next pointer
+ aFree(tfl->name); // free structures
+ aFree(tfl);
+ }
+
+ if (timer_data) aFree(timer_data);
+ BHEAP_CLEAR(timer_heap);
+ if (free_timer_list) aFree(free_timer_list);
}
diff --git a/src/common/timer.h b/src/common/timer.h
index d45c73d12..9b46927d8 100644
--- a/src/common/timer.h
+++ b/src/common/timer.h
@@ -1,8 +1,8 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _TIMER_H_
-#define _TIMER_H_
+#ifndef _TIMER_H_
+#define _TIMER_H_
#include "../common/cbasetypes.h"
@@ -12,9 +12,9 @@
// timer flags
enum {
- TIMER_ONCE_AUTODEL = 0x01,
- TIMER_INTERVAL = 0x02,
- TIMER_REMOVE_HEAP = 0x10,
+ TIMER_ONCE_AUTODEL = 0x01,
+ TIMER_INTERVAL = 0x02,
+ TIMER_REMOVE_HEAP = 0x10,
};
// Struct declaration
@@ -22,15 +22,15 @@ enum {
typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data);
struct TimerData {
- unsigned int tick;
- TimerFunc func;
- int type;
- int interval;
- int heap_pos;
-
- // general-purpose storage
- int id;
- intptr_t data;
+ unsigned int tick;
+ TimerFunc func;
+ int type;
+ int interval;
+ int heap_pos;
+
+ // general-purpose storage
+ int id;
+ intptr_t data;
};
// Function prototype declaration
@@ -40,13 +40,13 @@ unsigned int gettick_nocache(void);
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);
+const struct TimerData *get_timer(int tid);
int delete_timer(int tid, TimerFunc func);
int addtick_timer(int tid, unsigned int tick);
int settick_timer(int tid, unsigned int tick);
-int add_timer_func_list(TimerFunc func, char* name);
+int add_timer_func_list(TimerFunc func, char *name);
unsigned long get_uptime(void);
diff --git a/src/common/utils.c b/src/common/utils.c
index 296df7e70..9d090f594 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -15,269 +15,262 @@
#include <math.h> // floor()
#ifdef WIN32
- #include "../common/winapi.h"
- #ifndef F_OK
- #define F_OK 0x0
- #endif /* F_OK */
+#include "../common/winapi.h"
+#ifndef F_OK
+#define F_OK 0x0
+#endif /* F_OK */
#else
- #include <unistd.h>
- #include <dirent.h>
- #include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
#endif
/// Dumps given buffer into file pointed to by a handle.
-void WriteDump(FILE* fp, const void* buffer, size_t length)
+void WriteDump(FILE *fp, const void *buffer, size_t length)
{
- size_t i;
- char hex[48+1], ascii[16+1];
-
- fprintf(fp, "--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
- ascii[16] = 0;
-
- for( i = 0; i < length; i++ )
- {
- char c = RBUFB(buffer,i);
-
- ascii[i%16] = ISCNTRL(c) ? '.' : c;
- sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
-
- if( (i%16) == 15 )
- {
- fprintf(fp, "%03X %s %s\n", (unsigned int)(i/16), hex, ascii);
- }
- }
-
- if( (i%16) != 0 )
- {
- ascii[i%16] = 0;
- fprintf(fp, "%03X %-48s %-16s\n", (unsigned int)(i/16), hex, ascii);
- }
+ size_t i;
+ char hex[48+1], ascii[16+1];
+
+ fprintf(fp, "--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
+ ascii[16] = 0;
+
+ for (i = 0; i < length; i++) {
+ char c = RBUFB(buffer,i);
+
+ ascii[i%16] = ISCNTRL(c) ? '.' : c;
+ sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
+
+ if ((i%16) == 15) {
+ fprintf(fp, "%03X %s %s\n", (unsigned int)(i/16), hex, ascii);
+ }
+ }
+
+ if ((i%16) != 0) {
+ ascii[i%16] = 0;
+ fprintf(fp, "%03X %-48s %-16s\n", (unsigned int)(i/16), hex, ascii);
+ }
}
/// Dumps given buffer on the console.
-void ShowDump(const void* buffer, size_t length)
+void ShowDump(const void *buffer, size_t length)
{
- size_t i;
- char hex[48+1], ascii[16+1];
-
- ShowDebug("--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
- ascii[16] = 0;
-
- for( i = 0; i < length; i++ )
- {
- char c = RBUFB(buffer,i);
-
- ascii[i%16] = ISCNTRL(c) ? '.' : c;
- sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
-
- if( (i%16) == 15 )
- {
- ShowDebug("%03X %s %s\n", i/16, hex, ascii);
- }
- }
-
- if( (i%16) != 0 )
- {
- ascii[i%16] = 0;
- ShowDebug("%03X %-48s %-16s\n", i/16, hex, ascii);
- }
+ size_t i;
+ char hex[48+1], ascii[16+1];
+
+ ShowDebug("--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
+ ascii[16] = 0;
+
+ for (i = 0; i < length; i++) {
+ char c = RBUFB(buffer,i);
+
+ ascii[i%16] = ISCNTRL(c) ? '.' : c;
+ sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
+
+ if ((i%16) == 15) {
+ ShowDebug("%03X %s %s\n", i/16, hex, ascii);
+ }
+ }
+
+ if ((i%16) != 0) {
+ ascii[i%16] = 0;
+ ShowDebug("%03X %-48s %-16s\n", i/16, hex, ascii);
+ }
}
#ifdef WIN32
-static char* checkpath(char *path, const char *srcpath)
-{ // just make sure the char*path is not const
- char *p=path;
- if(NULL!=path && NULL!=srcpath)
- while(*srcpath) {
- if (*srcpath=='/') {
- *p++ = '\\';
- srcpath++;
- }
- else
- *p++ = *srcpath++;
- }
- *p = *srcpath; //EOS
- return path;
+static char *checkpath(char *path, const char *srcpath)
+{
+ // just make sure the char*path is not const
+ char *p=path;
+ if (NULL!=path && NULL!=srcpath)
+ while (*srcpath) {
+ if (*srcpath=='/') {
+ *p++ = '\\';
+ srcpath++;
+ } else
+ *p++ = *srcpath++;
+ }
+ *p = *srcpath; //EOS
+ return path;
}
-void findfile(const char *p, const char *pat, void (func)(const char*))
+void findfile(const char *p, const char *pat, void (func)(const char *))
{
- WIN32_FIND_DATAA FindFileData;
- HANDLE hFind;
- char tmppath[MAX_PATH+1];
-
- const char *path = (p ==NULL)? "." : p;
- const char *pattern = (pat==NULL)? "" : pat;
-
- checkpath(tmppath,path);
- if( PATHSEP != tmppath[strlen(tmppath)-1])
- strcat(tmppath, "\\*");
- else
- strcat(tmppath, "*");
-
- hFind = FindFirstFileA(tmppath, &FindFileData);
- if (hFind != INVALID_HANDLE_VALUE)
- {
- do
- {
- if (strcmp(FindFileData.cFileName, ".") == 0)
- continue;
- if (strcmp(FindFileData.cFileName, "..") == 0)
- continue;
-
- sprintf(tmppath,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
-
- if (FindFileData.cFileName && strstr(FindFileData.cFileName, pattern)) {
- func( tmppath );
- }
-
-
- if( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
- {
- findfile(tmppath, pat, func);
- }
- }while (FindNextFileA(hFind, &FindFileData) != 0);
- FindClose(hFind);
- }
- return;
+ WIN32_FIND_DATAA FindFileData;
+ HANDLE hFind;
+ char tmppath[MAX_PATH+1];
+
+ const char *path = (p ==NULL)? "." : p;
+ const char *pattern = (pat==NULL)? "" : pat;
+
+ checkpath(tmppath,path);
+ if (PATHSEP != tmppath[strlen(tmppath)-1])
+ strcat(tmppath, "\\*");
+ else
+ strcat(tmppath, "*");
+
+ hFind = FindFirstFileA(tmppath, &FindFileData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ if (strcmp(FindFileData.cFileName, ".") == 0)
+ continue;
+ if (strcmp(FindFileData.cFileName, "..") == 0)
+ continue;
+
+ sprintf(tmppath,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
+
+ if (FindFileData.cFileName && strstr(FindFileData.cFileName, pattern)) {
+ func(tmppath);
+ }
+
+
+ if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ findfile(tmppath, pat, func);
+ }
+ } while (FindNextFileA(hFind, &FindFileData) != 0);
+ FindClose(hFind);
+ }
+ return;
}
#else
#define MAX_DIR_PATH 2048
-static char* checkpath(char *path, const char*srcpath)
-{ // just make sure the char*path is not const
- char *p=path;
- if(NULL!=path && NULL!=srcpath)
- while(*srcpath) {
- if (*srcpath=='\\') {
- *p++ = '/';
- srcpath++;
- }
- else
- *p++ = *srcpath++;
- }
- *p = *srcpath; //EOS
- return path;
+static char *checkpath(char *path, const char *srcpath)
+{
+ // just make sure the char*path is not const
+ char *p=path;
+ if (NULL!=path && NULL!=srcpath)
+ while (*srcpath) {
+ if (*srcpath=='\\') {
+ *p++ = '/';
+ srcpath++;
+ } else
+ *p++ = *srcpath++;
+ }
+ *p = *srcpath; //EOS
+ return path;
}
-void findfile(const char *p, const char *pat, void (func)(const char*))
+void findfile(const char *p, const char *pat, void (func)(const char *))
{
- DIR* dir; // pointer to the scanned directory.
- struct dirent* entry; // pointer to one directory entry.
- struct stat dir_stat; // used by stat().
- char tmppath[MAX_DIR_PATH+1];
- char path[MAX_DIR_PATH+1]= ".";
- const char *pattern = (pat==NULL)? "" : pat;
- if(p!=NULL) strcpy(path,p);
-
- // open the directory for reading
- dir = opendir( checkpath(path, path) );
- if (!dir) {
- ShowError("Cannot read directory '%s'\n", path);
- return;
- }
-
- // scan the directory, traversing each sub-directory
- // matching the pattern for each file name.
- while ((entry = readdir(dir))) {
- // skip the "." and ".." entries.
- if (strcmp(entry->d_name, ".") == 0)
- continue;
- if (strcmp(entry->d_name, "..") == 0)
- continue;
-
- sprintf(tmppath,"%s%c%s",path, PATHSEP, entry->d_name);
-
- // check if the pattern matchs.
- if (entry->d_name && strstr(entry->d_name, pattern)) {
- func( tmppath );
- }
- // check if it is a directory.
- if (stat(tmppath, &dir_stat) == -1) {
- ShowError("stat error %s\n': ", tmppath);
- continue;
- }
- // is this a directory?
- if (S_ISDIR(dir_stat.st_mode)) {
- // decent recursivly
- findfile(tmppath, pat, func);
- }
- }//end while
-
- closedir(dir);
+ DIR *dir; // pointer to the scanned directory.
+ struct dirent *entry; // pointer to one directory entry.
+ struct stat dir_stat; // used by stat().
+ char tmppath[MAX_DIR_PATH+1];
+ char path[MAX_DIR_PATH+1]= ".";
+ const char *pattern = (pat==NULL)? "" : pat;
+ if (p!=NULL) strcpy(path,p);
+
+ // open the directory for reading
+ dir = opendir(checkpath(path, path));
+ if (!dir) {
+ ShowError("Cannot read directory '%s'\n", path);
+ return;
+ }
+
+ // scan the directory, traversing each sub-directory
+ // matching the pattern for each file name.
+ while ((entry = readdir(dir))) {
+ // skip the "." and ".." entries.
+ if (strcmp(entry->d_name, ".") == 0)
+ continue;
+ if (strcmp(entry->d_name, "..") == 0)
+ continue;
+
+ sprintf(tmppath,"%s%c%s",path, PATHSEP, entry->d_name);
+
+ // check if the pattern matchs.
+ if (entry->d_name && strstr(entry->d_name, pattern)) {
+ func(tmppath);
+ }
+ // check if it is a directory.
+ if (stat(tmppath, &dir_stat) == -1) {
+ ShowError("stat error %s\n': ", tmppath);
+ continue;
+ }
+ // is this a directory?
+ if (S_ISDIR(dir_stat.st_mode)) {
+ // decent recursivly
+ findfile(tmppath, pat, func);
+ }
+ }//end while
+
+ closedir(dir);
}
#endif
-bool exists(const char* filename)
+bool exists(const char *filename)
{
- return !access(filename, F_OK);
+ return !access(filename, F_OK);
}
uint8 GetByte(uint32 val, int idx)
{
- switch( idx )
- {
- case 0: return (uint8)( (val & 0x000000FF) );
- case 1: return (uint8)( (val & 0x0000FF00) >> 0x08 );
- case 2: return (uint8)( (val & 0x00FF0000) >> 0x10 );
- case 3: return (uint8)( (val & 0xFF000000) >> 0x18 );
- default:
+ switch (idx) {
+ case 0:
+ return (uint8)((val & 0x000000FF));
+ case 1:
+ return (uint8)((val & 0x0000FF00) >> 0x08);
+ case 2:
+ return (uint8)((val & 0x00FF0000) >> 0x10);
+ case 3:
+ return (uint8)((val & 0xFF000000) >> 0x18);
+ default:
#if defined(DEBUG)
- ShowDebug("GetByte: invalid index (idx=%d)\n", idx);
+ ShowDebug("GetByte: invalid index (idx=%d)\n", idx);
#endif
- return 0;
- }
+ return 0;
+ }
}
uint16 GetWord(uint32 val, int idx)
{
- switch( idx )
- {
- case 0: return (uint16)( (val & 0x0000FFFF) );
- case 1: return (uint16)( (val & 0xFFFF0000) >> 0x10 );
- default:
+ switch (idx) {
+ case 0:
+ return (uint16)((val & 0x0000FFFF));
+ case 1:
+ return (uint16)((val & 0xFFFF0000) >> 0x10);
+ default:
#if defined(DEBUG)
- ShowDebug("GetWord: invalid index (idx=%d)\n", idx);
+ ShowDebug("GetWord: invalid index (idx=%d)\n", idx);
#endif
- return 0;
- }
+ return 0;
+ }
}
uint16 MakeWord(uint8 byte0, uint8 byte1)
{
- return byte0 | (byte1 << 0x08);
+ return byte0 | (byte1 << 0x08);
}
uint32 MakeDWord(uint16 word0, uint16 word1)
{
- return
- ( (uint32)(word0 ) )|
- ( (uint32)(word1 << 0x10) );
+ return
+ ((uint32)(word0))|
+ ((uint32)(word1 << 0x10));
}
/// calculates the value of A / B, in percent (rounded down)
unsigned int get_percentage(const unsigned int A, const unsigned int B)
{
- double result;
+ double result;
- if( B == 0 )
- {
- ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B);
- return ~0U;
- }
+ if (B == 0) {
+ ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B);
+ return ~0U;
+ }
- result = 100 * ((double)A / (double)B);
+ result = 100 * ((double)A / (double)B);
- if( result > UINT_MAX )
- {
- ShowError("get_percentage(): result percentage too high! (A=%u,B=%u,result=%g)\n", A, B, result);
- return UINT_MAX;
- }
+ if (result > UINT_MAX) {
+ ShowError("get_percentage(): result percentage too high! (A=%u,B=%u,result=%g)\n", A, B, result);
+ return UINT_MAX;
+ }
- return (unsigned int)floor(result);
+ return (unsigned int)floor(result);
}
diff --git a/src/common/utils.h b/src/common/utils.h
index 8e39f2655..7f68e484e 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -8,11 +8,11 @@
#include <stdio.h> // FILE*
// generate a hex dump of the first 'length' bytes of 'buffer'
-void WriteDump(FILE* fp, const void* buffer, size_t length);
-void ShowDump(const void* buffer, size_t length);
+void WriteDump(FILE *fp, const void *buffer, size_t length);
+void ShowDump(const void *buffer, size_t length);
-void findfile(const char *p, const char *pat, void (func)(const char*));
-bool exists(const char* filename);
+void findfile(const char *p, const char *pat, void (func)(const char *));
+bool exists(const char *filename);
//Caps values to min/max
#define cap_value(a, min, max) ((a >= max) ? max : (a <= min) ? min : a)
diff --git a/src/common/winapi.h b/src/common/winapi.h
index 7ce555049..dfb7d4588 100644
--- a/src/common/winapi.h
+++ b/src/common/winapi.h
@@ -2,12 +2,12 @@
#define STRICT
-#define NTDDI_VERSION NTDDI_WIN2K
+#define NTDDI_VERSION NTDDI_WIN2K
#define _WIN32_WINNT 0x0500
#define WINVER 0x0500
-#define _WIN32_IE 0x0600
+#define _WIN32_IE 0x0600
#define WIN32_LEAN_AND_MEAN
-#define NOCOMM
+#define NOCOMM
#define NOKANJI
#define NOHELP
#define NOMCX