summaryrefslogtreecommitdiff
path: root/src/common/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/utils.c')
-rw-r--r--src/common/utils.c224
1 files changed, 195 insertions, 29 deletions
diff --git a/src/common/utils.c b/src/common/utils.c
index 296df7e70..79232b25c 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -1,30 +1,37 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
+
+#define HERCULES_CORE
-#include "../common/cbasetypes.h"
-#include "../common/mmo.h"
-#include "../common/malloc.h"
-#include "../common/showmsg.h"
-#include "socket.h"
#include "utils.h"
-#include <stdio.h>
+#include <math.h> // floor()
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h> // floor()
+#include <sys/stat.h> // cache purposes [Ind/Hercules]
+
+#include "../common/cbasetypes.h"
+#include "../common/core.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
#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 <dirent.h>
+# include <sys/stat.h>
+# include <unistd.h>
#endif
+struct HCache_interface HCache_s;
/// Dumps given buffer into file pointed to by a handle.
void WriteDump(FILE* fp, const void* buffer, size_t length)
@@ -57,31 +64,27 @@ void WriteDump(FILE* fp, const void* buffer, size_t length)
/// 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++ )
- {
+ 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) == 15) {
+ ShowDebug("%03"PRIXS" %s %s\n", i/16, hex, ascii);
}
}
- if( (i%16) != 0 )
- {
+ if ((i%16) != 0) {
ascii[i%16] = 0;
- ShowDebug("%03X %-48s %-16s\n", i/16, hex, ascii);
+ ShowDebug("%03"PRIXS" %-48s %-16s\n", i/16, hex, ascii);
}
}
@@ -193,7 +196,7 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
sprintf(tmppath,"%s%c%s",path, PATHSEP, entry->d_name);
- // check if the pattern matchs.
+ // check if the pattern matches.
if (entry->d_name && strstr(entry->d_name, pattern)) {
func( tmppath );
}
@@ -204,7 +207,7 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
}
// is this a directory?
if (S_ISDIR(dir_stat.st_mode)) {
- // decent recursivly
+ // decent recursively
findfile(tmppath, pat, func);
}
}//end while
@@ -259,6 +262,58 @@ uint32 MakeDWord(uint16 word0, uint16 word1)
( (uint32)(word1 << 0x10) );
}
+/*************************************
+* Big-endian compatibility functions *
+*************************************/
+
+// Converts an int16 from current machine order to little-endian
+int16 MakeShortLE(int16 val)
+{
+ unsigned char buf[2];
+ buf[0] = (unsigned char)( (val & 0x00FF) );
+ buf[1] = (unsigned char)( (val & 0xFF00) >> 0x08 );
+ return *((int16*)buf);
+}
+
+// Converts an int32 from current machine order to little-endian
+int32 MakeLongLE(int32 val)
+{
+ unsigned char buf[4];
+ buf[0] = (unsigned char)( (val & 0x000000FF) );
+ buf[1] = (unsigned char)( (val & 0x0000FF00) >> 0x08 );
+ buf[2] = (unsigned char)( (val & 0x00FF0000) >> 0x10 );
+ buf[3] = (unsigned char)( (val & 0xFF000000) >> 0x18 );
+ return *((int32*)buf);
+}
+
+// Reads an uint16 in little-endian from the buffer
+uint16 GetUShort(const unsigned char* buf)
+{
+ return ( ((uint16)(buf[0])) )
+ |( ((uint16)(buf[1])) << 0x08 );
+}
+
+// Reads an uint32 in little-endian from the buffer
+uint32 GetULong(const unsigned char* buf)
+{
+ return ( ((uint32)(buf[0])) )
+ |( ((uint32)(buf[1])) << 0x08 )
+ |( ((uint32)(buf[2])) << 0x10 )
+ |( ((uint32)(buf[3])) << 0x18 );
+}
+
+// Reads an int32 in little-endian from the buffer
+int32 GetLong(const unsigned char* buf)
+{
+ return (int32)GetULong(buf);
+}
+
+// Reads a float (32 bits) from the buffer
+float GetFloat(const unsigned char* buf)
+{
+ uint32 val = GetULong(buf);
+ return *((float*)(void*)&val);
+}
/// calculates the value of A / B, in percent (rounded down)
unsigned int get_percentage(const unsigned int A, const unsigned int B)
@@ -267,7 +322,7 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B)
if( B == 0 )
{
- ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B);
+ ShowError("get_percentage(): division by zero! (A=%u,B=%u)\n", A, B);
return ~0U;
}
@@ -281,3 +336,114 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B)
return (unsigned int)floor(result);
}
+
+//-----------------------------------------------------
+// custom timestamp formatting (from eApp)
+//-----------------------------------------------------
+const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format)
+{
+ size_t len = strftime(str, size, format, localtime(&timestamp));
+ memset(str + len, '\0', size - len);
+ return str;
+}
+
+
+/* [Ind/Hercules] Caching */
+bool HCache_check(const char *file) {
+ struct stat bufa, bufb;
+ FILE *first, *second;
+ char s_path[255], dT[1];
+ time_t rtime;
+
+ if( !(first = fopen(file,"rb")) )
+ return false;
+
+ if( file[0] == '.' && file[1] == '/' )
+ file += 2;
+ else if( file[0] == '.' )
+ file++;
+
+ snprintf(s_path, 255, "./cache/%s", file);
+
+ if( !(second = fopen(s_path,"rb")) ) {
+ fclose(first);
+ return false;
+ }
+
+ if( fread(dT,sizeof(dT),1,second) != 1 || fread(&rtime,sizeof(rtime),1,second) != 1 || dT[0] != HCACHE_KEY || HCache->recompile_time > rtime ) {
+ fclose(first);
+ fclose(second);
+ return false;
+ }
+
+ fstat(fileno(first), &bufa);
+ fstat(fileno(second), &bufb);
+
+ fclose(first);
+ fclose(second);
+
+ if( bufa.st_mtime > bufb.st_mtime )
+ return false;
+
+ return true;
+}
+
+FILE *HCache_open(const char *file, const char *opt) {
+ FILE *first;
+ char s_path[255];
+
+ if( file[0] == '.' && file[1] == '/' )
+ file += 2;
+ else if( file[0] == '.' )
+ file++;
+
+ snprintf(s_path, 255, "./cache/%s", file);
+
+ if( !(first = fopen(s_path,opt)) ) {
+ return NULL;
+ }
+
+ if( opt[0] != 'r' ) {
+ char dT[1];/* 1-byte key to ensure our method is the latest, we can modify to ensure the method matches */
+ dT[0] = HCACHE_KEY;
+ hwrite(dT,sizeof(dT),1,first);
+ hwrite(&HCache->recompile_time,sizeof(HCache->recompile_time),1,first);
+ }
+ fseek(first, 20, SEEK_SET);/* skip first 20, might wanna store something else later */
+
+ return first;
+}
+void HCache_init(void) {
+ FILE *server;
+
+ if( (server = fopen(SERVER_NAME,"rb")) ) {
+ struct stat buf;
+
+ fstat(fileno(server), &buf);
+ HCache->recompile_time = buf.st_mtime;
+ fclose(server);
+
+ HCache->enabled = true;
+ } else
+ ShowWarning("Unable to open '%s', caching capabilities have been disabled!\n",SERVER_NAME);
+}
+/* transit to fread, shields vs warn_unused_result */
+size_t hread(void * ptr, size_t size, size_t count, FILE * stream) {
+ return fread(ptr, size, count, stream);
+}
+/* transit to fwrite, shields vs warn_unused_result */
+size_t hwrite(const void * ptr, size_t size, size_t count, FILE * stream) {
+ return fwrite(ptr, size, count, stream);
+}
+
+void HCache_defaults(void) {
+
+ HCache = &HCache_s;
+
+ HCache->init = HCache_init;
+
+ HCache->check = HCache_check;
+ HCache->open = HCache_open;
+ HCache->recompile_time = 0;
+ HCache->enabled = false;
+}