utils.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "../common/cbasetypes.h"
  4. #include "../common/mmo.h"
  5. #include "../common/malloc.h"
  6. #include "../common/showmsg.h"
  7. #include "socket.h"
  8. #include "utils.h"
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <math.h> // floor()
  14. #ifdef WIN32
  15. #include "../common/winapi.h"
  16. #ifndef F_OK
  17. #define F_OK 0x0
  18. #endif /* F_OK */
  19. #else
  20. #include <unistd.h>
  21. #include <dirent.h>
  22. #include <sys/stat.h>
  23. #endif
  24. /// Dumps given buffer into file pointed to by a handle.
  25. void WriteDump(FILE* fp, const void* buffer, size_t length)
  26. {
  27. size_t i;
  28. char hex[48+1], ascii[16+1];
  29. fprintf(fp, "--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
  30. ascii[16] = 0;
  31. for( i = 0; i < length; i++ )
  32. {
  33. char c = RBUFB(buffer,i);
  34. ascii[i%16] = ISCNTRL(c) ? '.' : c;
  35. sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
  36. if( (i%16) == 15 )
  37. {
  38. fprintf(fp, "%03X %s %s\n", (unsigned int)(i/16), hex, ascii);
  39. }
  40. }
  41. if( (i%16) != 0 )
  42. {
  43. ascii[i%16] = 0;
  44. fprintf(fp, "%03X %-48s %-16s\n", (unsigned int)(i/16), hex, ascii);
  45. }
  46. }
  47. /// Dumps given buffer on the console.
  48. void ShowDump(const void* buffer, size_t length)
  49. {
  50. size_t i;
  51. char hex[48+1], ascii[16+1];
  52. ShowDebug("--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
  53. ascii[16] = 0;
  54. for( i = 0; i < length; i++ )
  55. {
  56. char c = RBUFB(buffer,i);
  57. ascii[i%16] = ISCNTRL(c) ? '.' : c;
  58. sprintf(hex+(i%16)*3, "%02X ", RBUFB(buffer,i));
  59. if( (i%16) == 15 )
  60. {
  61. ShowDebug("%03X %s %s\n", i/16, hex, ascii);
  62. }
  63. }
  64. if( (i%16) != 0 )
  65. {
  66. ascii[i%16] = 0;
  67. ShowDebug("%03X %-48s %-16s\n", i/16, hex, ascii);
  68. }
  69. }
  70. #ifdef WIN32
  71. static char* checkpath(char *path, const char *srcpath)
  72. { // just make sure the char*path is not const
  73. char *p=path;
  74. if(NULL!=path && NULL!=srcpath)
  75. while(*srcpath) {
  76. if (*srcpath=='/') {
  77. *p++ = '\\';
  78. srcpath++;
  79. }
  80. else
  81. *p++ = *srcpath++;
  82. }
  83. *p = *srcpath; //EOS
  84. return path;
  85. }
  86. void findfile(const char *p, const char *pat, void (func)(const char*))
  87. {
  88. WIN32_FIND_DATAA FindFileData;
  89. HANDLE hFind;
  90. char tmppath[MAX_PATH+1];
  91. const char *path = (p ==NULL)? "." : p;
  92. const char *pattern = (pat==NULL)? "" : pat;
  93. checkpath(tmppath,path);
  94. if( PATHSEP != tmppath[strlen(tmppath)-1])
  95. strcat(tmppath, "\\*");
  96. else
  97. strcat(tmppath, "*");
  98. hFind = FindFirstFileA(tmppath, &FindFileData);
  99. if (hFind != INVALID_HANDLE_VALUE)
  100. {
  101. do
  102. {
  103. if (strcmp(FindFileData.cFileName, ".") == 0)
  104. continue;
  105. if (strcmp(FindFileData.cFileName, "..") == 0)
  106. continue;
  107. sprintf(tmppath,"%s%c%s",path,PATHSEP,FindFileData.cFileName);
  108. if (FindFileData.cFileName && strstr(FindFileData.cFileName, pattern)) {
  109. func( tmppath );
  110. }
  111. if( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  112. {
  113. findfile(tmppath, pat, func);
  114. }
  115. }while (FindNextFileA(hFind, &FindFileData) != 0);
  116. FindClose(hFind);
  117. }
  118. return;
  119. }
  120. int check_filepath(const char* filepath){
  121. DWORD Attribute;
  122. if( Attribute = GetFileAttributes(filepath) ){
  123. if( (Attribute & INVALID_FILE_ATTRIBUTES) && GetLastError() == ERROR_FILE_NOT_FOUND ) return 3;
  124. else if( Attribute & FILE_ATTRIBUTE_DIRECTORY ) return 1;
  125. else return 2;
  126. }
  127. return 0;
  128. }
  129. #else
  130. #define MAX_DIR_PATH 2048
  131. /**
  132. * Check if the path is a directory or file
  133. * @param filepath
  134. * @return 1=dir, 2=file, 3=else, 0=error
  135. */
  136. int check_filepath(const char* filepath){
  137. struct stat s;
  138. if( stat(filepath,&s) == 0 ){
  139. if( s.st_mode & S_IFDIR ) return 1;
  140. else if( s.st_mode & S_IFREG )return 2;
  141. else return 3;
  142. }
  143. else {
  144. return 0;
  145. }
  146. }
  147. static char* checkpath(char *path, const char*srcpath)
  148. { // just make sure the char*path is not const
  149. char *p=path;
  150. if(NULL!=path && NULL!=srcpath)
  151. while(*srcpath) {
  152. if (*srcpath=='\\') {
  153. *p++ = '/';
  154. srcpath++;
  155. }
  156. else
  157. *p++ = *srcpath++;
  158. }
  159. *p = *srcpath; //EOS
  160. return path;
  161. }
  162. void findfile(const char *p, const char *pat, void (func)(const char*))
  163. {
  164. DIR* dir; // pointer to the scanned directory.
  165. struct dirent* entry; // pointer to one directory entry.
  166. struct stat dir_stat; // used by stat().
  167. char tmppath[MAX_DIR_PATH+1];
  168. char path[MAX_DIR_PATH+1]= ".";
  169. const char *pattern = (pat==NULL)? "" : pat;
  170. if(p!=NULL) strcpy(path,p);
  171. // open the directory for reading
  172. dir = opendir( checkpath(path, path) );
  173. if (!dir) {
  174. ShowError("Cannot read directory '%s'\n", path);
  175. return;
  176. }
  177. // scan the directory, traversing each sub-directory
  178. // matching the pattern for each file name.
  179. while ((entry = readdir(dir))) {
  180. // skip the "." and ".." entries.
  181. if (strcmp(entry->d_name, ".") == 0)
  182. continue;
  183. if (strcmp(entry->d_name, "..") == 0)
  184. continue;
  185. sprintf(tmppath,"%s%c%s",path, PATHSEP, entry->d_name);
  186. // check if the pattern matchs.
  187. if (entry->d_name && strstr(entry->d_name, pattern)) {
  188. func( tmppath );
  189. }
  190. // check if it is a directory.
  191. if (stat(tmppath, &dir_stat) == -1) {
  192. ShowError("stat error %s\n': ", tmppath);
  193. continue;
  194. }
  195. // is this a directory?
  196. if (S_ISDIR(dir_stat.st_mode)) {
  197. // decent recursivly
  198. findfile(tmppath, pat, func);
  199. }
  200. }//end while
  201. closedir(dir);
  202. }
  203. #endif
  204. bool exists(const char* filename)
  205. {
  206. return !access(filename, F_OK);
  207. }
  208. uint8 GetByte(uint32 val, int idx)
  209. {
  210. switch( idx )
  211. {
  212. case 0: return (uint8)( (val & 0x000000FF) );
  213. case 1: return (uint8)( (val & 0x0000FF00) >> 0x08 );
  214. case 2: return (uint8)( (val & 0x00FF0000) >> 0x10 );
  215. case 3: return (uint8)( (val & 0xFF000000) >> 0x18 );
  216. default:
  217. #if defined(DEBUG)
  218. ShowDebug("GetByte: invalid index (idx=%d)\n", idx);
  219. #endif
  220. return 0;
  221. }
  222. }
  223. uint16 GetWord(uint32 val, int idx)
  224. {
  225. switch( idx )
  226. {
  227. case 0: return (uint16)( (val & 0x0000FFFF) );
  228. case 1: return (uint16)( (val & 0xFFFF0000) >> 0x10 );
  229. default:
  230. #if defined(DEBUG)
  231. ShowDebug("GetWord: invalid index (idx=%d)\n", idx);
  232. #endif
  233. return 0;
  234. }
  235. }
  236. uint16 MakeWord(uint8 byte0, uint8 byte1)
  237. {
  238. return byte0 | (byte1 << 0x08);
  239. }
  240. uint32 MakeDWord(uint16 word0, uint16 word1)
  241. {
  242. return
  243. ( (uint32)(word0 ) )|
  244. ( (uint32)(word1 << 0x10) );
  245. }
  246. /*************************************
  247. * Big-endian compatibility functions *
  248. *************************************/
  249. // Converts an int16 from current machine order to little-endian
  250. int16 MakeShortLE(int16 val)
  251. {
  252. unsigned char buf[2];
  253. buf[0] = (unsigned char)( (val & 0x00FF) );
  254. buf[1] = (unsigned char)( (val & 0xFF00) >> 0x08 );
  255. return *((int16*)buf);
  256. }
  257. // Converts an int32 from current machine order to little-endian
  258. int32 MakeLongLE(int32 val)
  259. {
  260. unsigned char buf[4];
  261. buf[0] = (unsigned char)( (val & 0x000000FF) );
  262. buf[1] = (unsigned char)( (val & 0x0000FF00) >> 0x08 );
  263. buf[2] = (unsigned char)( (val & 0x00FF0000) >> 0x10 );
  264. buf[3] = (unsigned char)( (val & 0xFF000000) >> 0x18 );
  265. return *((int32*)buf);
  266. }
  267. // Reads an uint16 in little-endian from the buffer
  268. uint16 GetUShort(const unsigned char* buf)
  269. {
  270. return ( ((uint16)(buf[0])) )
  271. |( ((uint16)(buf[1])) << 0x08 );
  272. }
  273. // Reads an uint32 in little-endian from the buffer
  274. uint32 GetULong(const unsigned char* buf)
  275. {
  276. return ( ((uint32)(buf[0])) )
  277. |( ((uint32)(buf[1])) << 0x08 )
  278. |( ((uint32)(buf[2])) << 0x10 )
  279. |( ((uint32)(buf[3])) << 0x18 );
  280. }
  281. // Reads an int32 in little-endian from the buffer
  282. int32 GetLong(const unsigned char* buf)
  283. {
  284. return (int32)GetULong(buf);
  285. }
  286. // Reads a float (32 bits) from the buffer
  287. float GetFloat(const unsigned char* buf)
  288. {
  289. uint32 val = GetULong(buf);
  290. return *((float*)(void*)&val);
  291. }
  292. uint32 date2version(int date) {
  293. if(date < 20040906) return 5;
  294. else if(date < 20040920) return 10;
  295. else if(date < 20041005) return 11;
  296. else if(date < 20041025) return 12;
  297. else if(date < 20041129) return 13;
  298. else if(date < 20050110) return 14;
  299. else if(date < 20050509) return 15;
  300. else if(date < 20050628) return 16;
  301. else if(date < 20050718) return 17;
  302. else if(date < 20050719) return 18;
  303. else if(date < 20060327) return 19;
  304. else if(date < 20070108) return 20;
  305. else if(date < 20070212) return 21;
  306. //wtf @FIXME
  307. //else if(date < 20080910) return 22;
  308. else if(date < 20080827) return 23;
  309. else if(date < 20080910) return 24;
  310. //unable to solve from date
  311. else if(date < 20101124) return 25;
  312. else if(date < 20111005) return 26;
  313. else if(date < 20111102) return 27;
  314. else if(date < 20120307) return 28;
  315. else if(date < 20120410) return 29;
  316. else if(date < 20120418) return 30;
  317. else if(date < 20120618) return 31;
  318. else if(date < 20120702) return 32;
  319. else if(date < 20130320) return 33;
  320. else if(date < 20130515) return 34;
  321. else if(date < 20130522) return 35;
  322. else if(date < 20130529) return 36;
  323. else if(date < 20130605) return 37;
  324. else if(date < 20130612) return 38;
  325. else if(date < 20130618) return 39;
  326. else if(date < 20130626) return 40;
  327. else if(date < 20130703) return 41;
  328. else if(date < 20130710) return 42;
  329. else if(date < 20130717) return 43;
  330. else if(date < 20130807) return 44;
  331. else if(date < 20131223) return 45;
  332. else if(date >= 20131223) return 46;
  333. else return 30; //default
  334. }
  335. /// calculates the value of A / B, in percent (rounded down)
  336. unsigned int get_percentage(const unsigned int A, const unsigned int B)
  337. {
  338. double result;
  339. if( B == 0 )
  340. {
  341. ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B);
  342. return ~0U;
  343. }
  344. result = 100 * ((double)A / (double)B);
  345. if( result > UINT_MAX )
  346. {
  347. ShowError("get_percentage(): result percentage too high! (A=%u,B=%u,result=%g)\n", A, B, result);
  348. return UINT_MAX;
  349. }
  350. return (unsigned int)floor(result);
  351. }
  352. /**
  353. * Calculates the Levenshtein distance of two strings.
  354. * @author http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C
  355. */
  356. int levenshtein(const char *s1, const char *s2) {
  357. unsigned int s1len, s2len, x, y, lastdiag, olddiag, i;
  358. unsigned int *column;
  359. s1len = strlen(s1);
  360. s2len = strlen(s2);
  361. column = malloc((s1len+1) * sizeof(unsigned int));
  362. for (y = 1; y <= s1len; y++)
  363. column[y] = y;
  364. for (x = 1; x <= s2len; x++) {
  365. column[0] = x;
  366. for (y = 1, lastdiag = x-1; y <= s1len; y++) {
  367. olddiag = column[y];
  368. column[y] = min(min(column[y] + 1, column[y-1] + 1), lastdiag + (s1[y-1] == s2[x-1] ? 0 : 1));
  369. lastdiag = olddiag;
  370. }
  371. }
  372. i = column[s1len];
  373. free(column);
  374. return i;
  375. }