file_base.h 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  1. #pragma once
  2. #include <file_system.h>
  3. #include <macros_def.h>
  4. #include <stdarg.h>
  5. #if defined(_PLATFORM_WINDOWS_)
  6. #include <windows.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. // file path splitter
  11. #define PATH_SEPARATOR_CHAR '\\'
  12. // file search
  13. struct file_search_t
  14. {
  15. HANDLE handle;
  16. WIN32_FIND_DATA data;
  17. };
  18. // module handle
  19. typedef HMODULE dll_handle_t;
  20. // dll后缀
  21. #define DLL_POSTFIX "dll"
  22. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  23. #include <unistd.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <dirent.h>
  28. #include <dlfcn.h>
  29. #include <time.h>
  30. #include <ctype.h>
  31. #include <sys/stat.h>
  32. #include <sys/types.h>
  33. #include <utime.h>
  34. // file path splitter
  35. #define PATH_SEPARATOR_CHAR '/'
  36. // file search
  37. struct file_search_t
  38. {
  39. DIR* pdir;
  40. dirent* pent;
  41. char strpath[256];
  42. char strext[16];
  43. };
  44. // module handle
  45. typedef void* dll_handle_t;
  46. // dll后缀
  47. #define DLL_POSTFIX "so"
  48. #ifndef defmax
  49. #define defmax(a,b) (((a) > (b)) ? (a) : (b))
  50. #endif
  51. #ifndef defmin
  52. #define defmin(a,b) (((a) < (b)) ? (a) : (b))
  53. #endif
  54. #elif defined(_PLATFORM_APPLE_) // end of _PLATFORM_LINUX_
  55. #include <unistd.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <stdio.h>
  59. #include <dirent.h>
  60. #include <dlfcn.h>
  61. #include <time.h>
  62. #include <ctype.h>
  63. #include <sys/stat.h>
  64. #include <sys/types.h>
  65. #include <utime.h>
  66. // file path splitter
  67. #define PATH_SEPARATOR_CHAR '/'
  68. // file search
  69. struct file_search_t
  70. {
  71. DIR* pdir;
  72. dirent* pent;
  73. char strpath[256];
  74. char strext[16];
  75. };
  76. // module handle
  77. typedef void* dll_handle_t;
  78. // dll后缀
  79. #define DLL_POSTFIX "dylib"
  80. #ifndef defmax
  81. #define defmax(a,b) (((a) > (b)) ? (a) : (b))
  82. #endif
  83. #ifndef defmin
  84. #define defmin(a,b) (((a) < (b)) ? (a) : (b))
  85. #endif
  86. #endif // end of _PLATFORM_APPLE_
  87. namespace disk_file
  88. {
  89. FORCE_INLINE const char* get_standard_path(const char* path, char* buffer,
  90. size_t size)
  91. {
  92. #if defined(_PLATFORM_WINDOWS_)
  93. bool slash = false;
  94. const char* src = path;
  95. char* dst = buffer;
  96. char* dst_end = buffer + size - 1;
  97. while (*src) {
  98. if (dst >= dst_end) {
  99. break;
  100. }
  101. if ((*src == '/') || (*src == '\\')) {
  102. if (slash) {
  103. ++src;
  104. continue;
  105. }
  106. else {
  107. slash = true;
  108. }
  109. *dst = '\\';
  110. }
  111. else {
  112. *dst = *src;
  113. slash = false;
  114. }
  115. ++dst;
  116. ++src;
  117. }
  118. *dst = 0;
  119. return buffer;
  120. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  121. bool slash = false;
  122. const char* src = path;
  123. char* dst = buffer;
  124. char* dst_end = buffer + size - 1;
  125. while (*src) {
  126. if (dst >= dst_end) {
  127. break;
  128. }
  129. if ((*src == '/') || (*src == '\\')) {
  130. if (slash) {
  131. ++src;
  132. continue;
  133. }
  134. else {
  135. slash = true;
  136. }
  137. *dst = '/';
  138. }
  139. else {
  140. // 本来为了linux下大小写路径不混乱,全用小写,但是宝将规定了特定的环境路径,所以去掉吧
  141. //*dst = tolower(*src);
  142. *dst = *src;
  143. slash = false;
  144. }
  145. ++dst;
  146. ++src;
  147. }
  148. *dst = 0;
  149. return buffer;
  150. #endif // end of _PLATFORM_LINUX_
  151. }
  152. FORCE_INLINE int get_full_pathname(const char* file_name, char* buffer,
  153. size_t size, char** file_part)
  154. {
  155. #if defined(_PLATFORM_WINDOWS_)
  156. DWORD res = GetFullPathName(file_name, (DWORD)size, buffer, file_part);
  157. if (0 == res) {
  158. buffer[0] = 0;
  159. return 0;
  160. }
  161. if (size_t(res) >= size) {
  162. buffer[0] = 0;
  163. return res;
  164. }
  165. return (int)res;
  166. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  167. memset(buffer, 0, size);
  168. // 消除前面的空格
  169. const char* first = file_name;
  170. while ((*first == ' ') || (*first == '\t')) {
  171. ++first;
  172. }
  173. // 是否已经包含完整的路径
  174. if (*first == '/') {
  175. size_t file_name_len = strlen(first);
  176. if (file_name_len >= size) {
  177. // 缓冲区不够
  178. return 0;
  179. }
  180. memcpy(buffer, first, file_name_len + 1);
  181. }
  182. else {
  183. // 获取当前目录
  184. char cur_dir[512] = { 0 };
  185. if (getcwd(cur_dir, sizeof(cur_dir) - 1) == NULL) {
  186. return 0;
  187. }
  188. // 解析相对路径
  189. const char* p = first;
  190. while (*p) {
  191. if (*p == '.') {
  192. // (.\)当前目录
  193. if ((p[1] == '\\') || (p[1] == '/')) {
  194. p += 2;
  195. continue;
  196. }
  197. if (p[1] != '.') {
  198. break;
  199. }
  200. if ((p[2] != '\\') && (p[2] != '/')) {
  201. break;
  202. }
  203. // (..\)取上一级目录
  204. char* prev = strrchr(cur_dir, '/');
  205. if (prev) {
  206. *prev = 0;
  207. }
  208. p += 3;
  209. }
  210. else {
  211. break;
  212. }
  213. }
  214. if (strlen(cur_dir) + strlen(p) >= size) {
  215. return 0;
  216. }
  217. strcat(cur_dir, "/");
  218. strcpy(buffer, cur_dir);
  219. strcat(buffer, p);
  220. }
  221. if (file_part) {
  222. // 分割路径和文件名
  223. char* separator = strrchr(buffer, '/');
  224. if (separator) {
  225. *file_part = separator + 1;
  226. }
  227. else {
  228. // 文件名中没有包含路径
  229. *file_part = buffer;
  230. }
  231. }
  232. return strlen(buffer);
  233. #endif // end of _PLATFORM_LINUX_
  234. }
  235. FORCE_INLINE bool get_current_dir(char* buffer, size_t size)
  236. {
  237. #if defined(_PLATFORM_WINDOWS_)
  238. DWORD res = GetCurrentDirectory((DWORD)size, buffer);
  239. if (0 == res) {
  240. buffer[0] = 0;
  241. return false;
  242. }
  243. if (size_t(res) >= size) {
  244. buffer[0] = 0;
  245. return false;
  246. }
  247. return true;
  248. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  249. char* res = getcwd(buffer, size);
  250. if (NULL == res) {
  251. buffer[0] = 0;
  252. return false;
  253. }
  254. return true;
  255. #endif // end of _PLATFORM_LINUX_
  256. }
  257. FORCE_INLINE bool set_current_dir(const char* dir_name)
  258. {
  259. #if defined(_PLATFORM_WINDOWS_)
  260. return SetCurrentDirectory(dir_name) == TRUE;
  261. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  262. return chdir(dir_name) == 0;
  263. #endif // end of _PLATFORM_LINUX_
  264. }
  265. // directory exist?
  266. FORCE_INLINE bool dir_exists(const char* dir_name)
  267. {
  268. #if defined(_PLATFORM_WINDOWS_)
  269. DWORD res = GetFileAttributes(dir_name);
  270. if (res == DWORD(-1)) {
  271. return false;
  272. }
  273. return (res & FILE_ATTRIBUTE_DIRECTORY) != 0;
  274. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  275. char sname[512];
  276. get_standard_path(dir_name, sname, sizeof(sname));
  277. struct stat st;
  278. if (stat(sname, &st) == -1) {
  279. return false;
  280. }
  281. return (st.st_mode & S_IFMT) == S_IFDIR;
  282. #endif // end of _PLATFORM_LINUX_
  283. }
  284. FORCE_INLINE bool dir_create(const char* dir_name)
  285. {
  286. #if defined(_PLATFORM_WINDOWS_)
  287. return CreateDirectory(dir_name, NULL) == TRUE;
  288. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  289. char sname[512];
  290. get_standard_path(dir_name, sname, sizeof(sname));
  291. return mkdir(sname, 0700) == 0;
  292. #endif // end of _PLATFORM_LINUX_
  293. }
  294. FORCE_INLINE bool dir_delete(const char* dir_name)
  295. {
  296. #if defined(_PLATFORM_WINDOWS_)
  297. return RemoveDirectory(dir_name) == TRUE;
  298. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  299. char sname[512];
  300. get_standard_path(dir_name, sname, sizeof(sname));
  301. return rmdir(sname) == 0;
  302. #endif // end of _PLATFORM_LINUX_
  303. }
  304. FORCE_INLINE bool file_exists(const char* file_name)
  305. {
  306. #if defined(_PLATFORM_WINDOWS_)
  307. DWORD res = GetFileAttributes(file_name);
  308. if (res == DWORD(-1)) {
  309. return false;
  310. }
  311. return (res & FILE_ATTRIBUTE_DIRECTORY) == 0;
  312. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  313. char sname[512];
  314. get_standard_path(file_name, sname, sizeof(sname));
  315. struct stat st;
  316. if (stat(sname, &st) == -1) {
  317. return false;
  318. }
  319. return (st.st_mode & S_IFMT) == S_IFREG;
  320. #endif // end of _PLATFORM_LINUX_
  321. }
  322. FORCE_INLINE FILE* file_open(const char* file_name, const char* mode)
  323. {
  324. #if defined(_PLATFORM_WINDOWS_)
  325. return fopen(file_name, mode);
  326. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  327. char sname[512];
  328. get_standard_path(file_name, sname, sizeof(sname));
  329. return fopen(sname, mode);
  330. #endif // end of _PLATFORM_LINUX_
  331. }
  332. FORCE_INLINE bool file_delete(const char* file_name)
  333. {
  334. #if defined(_PLATFORM_WINDOWS_)
  335. return DeleteFile(file_name) == TRUE;
  336. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  337. char sname[512];
  338. get_standard_path(file_name, sname, sizeof(sname));
  339. return unlink(sname) == 0;
  340. #endif // end of _PLATFORM_LINUX_
  341. }
  342. FORCE_INLINE bool file_close(FILE* fp)
  343. {
  344. return fclose(fp) == 0;
  345. }
  346. FORCE_INLINE int file_seek(FILE* fp, int offset, int where)
  347. {
  348. return fseek(fp, offset, where);
  349. }
  350. FORCE_INLINE int file_tell(FILE* fp)
  351. {
  352. return ftell(fp);
  353. }
  354. FORCE_INLINE size_t get_file_size(const char* file_name)
  355. {
  356. #if defined(_PLATFORM_WINDOWS_)
  357. HANDLE fp = CreateFile(file_name, GENERIC_READ,
  358. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  359. if (INVALID_HANDLE_VALUE == fp) {
  360. return 0;
  361. }
  362. DWORD size_high;
  363. DWORD size_low = GetFileSize(fp, &size_high);
  364. CloseHandle(fp);
  365. size_t file_size = 0;
  366. #if defined(_PLATFORM_X64_)
  367. file_size = (size_t)size_high << 32;
  368. #endif
  369. file_size |= size_low;
  370. return file_size;
  371. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  372. char sname[512];
  373. get_standard_path(file_name, sname, sizeof(sname));
  374. struct stat st;
  375. if (stat(sname, &st) == -1) {
  376. return false;
  377. }
  378. return st.st_size;
  379. #endif // end of _PLATFORM_LINUX_
  380. }
  381. FORCE_INLINE bool get_file_time(const char* file_name,
  382. file_time_t* file_time)
  383. {
  384. #if defined(_PLATFORM_WINDOWS_)
  385. HANDLE fp = CreateFile(file_name, GENERIC_READ,
  386. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  387. if (INVALID_HANDLE_VALUE == fp) {
  388. return false;
  389. }
  390. FILETIME ft;
  391. if (!GetFileTime(fp, NULL, NULL, &ft)) {
  392. CloseHandle(fp);
  393. return false;
  394. }
  395. CloseHandle(fp);
  396. SYSTEMTIME st;
  397. FileTimeToSystemTime(&ft, &st);
  398. file_time->nyear = st.wYear;
  399. file_time->nmonth = st.wMonth;
  400. file_time->nday = st.wDay;
  401. file_time->nhour = st.wHour;
  402. file_time->nminute = st.wMinute;
  403. file_time->nsecond = st.wSecond;
  404. return true;
  405. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  406. char sname[512];
  407. get_standard_path(file_name, sname, sizeof(sname));
  408. struct stat st;
  409. if (stat(sname, &st) == -1) {
  410. return false;
  411. }
  412. tm* pt = gmtime(&st.st_mtime);
  413. file_time->nyear = pt->tm_year + 1900;
  414. file_time->nmonth = pt->tm_mon + 1;
  415. file_time->nday = pt->tm_mday;
  416. file_time->nhour = pt->tm_hour;
  417. file_time->nminute = pt->tm_min;
  418. file_time->nsecond = pt->tm_sec;
  419. return true;
  420. #endif // end of _PLATFORM_LINUX_
  421. }
  422. FORCE_INLINE bool set_file_time(const char* file_name,
  423. const file_time_t* file_time)
  424. {
  425. #if defined(_PLATFORM_WINDOWS_)
  426. HANDLE handle = CreateFile(file_name, GENERIC_WRITE,
  427. FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  428. if (INVALID_HANDLE_VALUE == handle) {
  429. return false;
  430. }
  431. SYSTEMTIME st;
  432. FILETIME ft;
  433. memset(&st, 0, sizeof(st));
  434. st.wYear = (WORD)file_time->nyear;
  435. st.wMonth = (WORD)file_time->nmonth;
  436. st.wDay = (WORD)file_time->nday;
  437. st.wHour = (WORD)file_time->nhour;
  438. st.wMinute = (WORD)file_time->nminute;
  439. st.wSecond = (WORD)file_time->nsecond;
  440. SystemTimeToFileTime(&st, &ft);
  441. if (!SetFileTime(handle, &ft, &ft, &ft)) {
  442. CloseHandle(handle);
  443. return false;
  444. }
  445. CloseHandle(handle);
  446. return true;
  447. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  448. char sname[512];
  449. get_standard_path(file_name, sname, sizeof(sname));
  450. struct utimbuf ut;
  451. struct tm tm1;
  452. memset(&tm1, 0, sizeof(tm1));
  453. tm1.tm_year = file_time->nyear;
  454. tm1.tm_mon = file_time->nmonth;
  455. tm1.tm_mday = file_time->nday;
  456. tm1.tm_hour = file_time->nhour;
  457. tm1.tm_min = file_time->nminute;
  458. tm1.tm_sec = file_time->nsecond;
  459. ut.actime = mktime(&tm1);
  460. ut.modtime = ut.actime;
  461. return utime(sname, &ut) == 0;
  462. #endif // end of _PLATFORM_LINUX_
  463. }
  464. FORCE_INLINE bool enable_file_modify(const char* file_name)
  465. {
  466. #if defined(_PLATFORM_WINDOWS_)
  467. return SetFileAttributes(file_name, FILE_ATTRIBUTE_ARCHIVE) == TRUE;
  468. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  469. char sname[512];
  470. get_standard_path(sname, sname, sizeof(sname));
  471. return chmod(sname, 0777) == 0;
  472. #endif // end of _PLATFORM_LINUX_
  473. }
  474. FORCE_INLINE const char* dll_name(const char* name, char* buf, size_t size)
  475. {
  476. #if defined(_PLATFORM_WINDOWS_)
  477. size_t name_size = strlen(name) + 1;
  478. if (name_size > size) {
  479. memcpy(buf, name, size - 1);
  480. buf[size - 1] = 0;
  481. }
  482. else {
  483. memcpy(buf, name, name_size);
  484. }
  485. return buf;
  486. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  487. char* p = buf;
  488. bool has_path = (strchr(name, '/') != NULL)
  489. || (strchr(name, '\\') != NULL);
  490. if (!has_path) {
  491. // current dir flag
  492. *p++ = '.';
  493. *p++ = '/';
  494. size -= 2;
  495. }
  496. size_t ext_len = strlen(DLL_POSTFIX);
  497. size -= ext_len;
  498. size_t name_size = strlen(name) + 1;
  499. if (name_size > size) {
  500. memcpy(p, name, size - 1);
  501. p[size - 1] = 0;
  502. }
  503. else {
  504. memcpy(p, name, name_size);
  505. }
  506. if (ext_len > 0) {
  507. char* dot = strrchr(p, '.');
  508. if (dot) {
  509. // change file ext
  510. memcpy(dot + 1, DLL_POSTFIX, ext_len + 1);
  511. }
  512. }
  513. return buf;
  514. #endif // end of _PLATFORM_LINUX_
  515. }
  516. // @brief 读取文件
  517. FORCE_INLINE size_t file_read(void* buf, size_t buf_len, FILE* fp)
  518. {
  519. return fread(buf, 1, buf_len, fp);
  520. }
  521. // @brief 写入文件
  522. FORCE_INLINE size_t file_write(const void* buf, size_t buf_len, FILE* fp)
  523. {
  524. return fwrite(buf, 1, buf_len, fp);
  525. }
  526. // @brief 写入文件
  527. FORCE_INLINE int file_printf(FILE* fp, const char* format, ...)
  528. {
  529. va_list args;
  530. va_start(args, format);
  531. int res = vfprintf(fp, format, args);
  532. va_end(args);
  533. return res;
  534. }
  535. // @brief 刷新文件
  536. FORCE_INLINE int file_flush(FILE* fp)
  537. {
  538. return fflush(fp);
  539. }
  540. // @brief 刷新文件
  541. FORCE_INLINE bool file_eof(FILE* fp)
  542. {
  543. return feof(fp) != 0;
  544. }
  545. // @brief 读取文件到缓冲区中
  546. FORCE_INLINE size_t file_readstring(const char* name, char* buffer, size_t buf_len)
  547. {
  548. FILE* fp = file_open(name, "rb");
  549. if (nullptr == fp)
  550. return 0;
  551. size_t read_len = file_read(buffer, buf_len, fp);
  552. file_close(fp);
  553. return read_len;
  554. }
  555. FORCE_INLINE dll_handle_t dll_open(const char* file_name)
  556. {
  557. #if defined(_PLATFORM_WINDOWS_)
  558. return LoadLibraryA(file_name);
  559. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  560. char sname[512];
  561. get_standard_path(file_name, sname, sizeof(sname));
  562. return dlopen(sname, RTLD_NOW);
  563. #endif // end of _PLATFORM_LINUX_
  564. }
  565. FORCE_INLINE const char* dll_error(char* buffer, size_t size)
  566. {
  567. #if defined(_PLATFORM_WINDOWS_)
  568. if (NULL == buffer) {
  569. return NULL;
  570. }
  571. DWORD err = GetLastError();
  572. if (0 == err) {
  573. return NULL;
  574. }
  575. wchar_t _temp[128];
  576. if (FormatMessageW(
  577. FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  578. 0, err, 0, _temp, (DWORD)128, NULL) == 0)
  579. {
  580. return NULL;
  581. }
  582. //widestr_to_utf8(_temp, buffer, size);
  583. return buffer;
  584. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  585. char* err = dlerror();
  586. if (NULL == buffer) {
  587. return NULL;
  588. }
  589. if (NULL == err) {
  590. return NULL;
  591. }
  592. size_t err_len = strlen(err);
  593. if (err_len >= size) {
  594. memcpy(buffer, err, size - 1);
  595. buffer[size - 1] = 0;
  596. }
  597. else {
  598. memcpy(buffer, err, err_len + 1);
  599. }
  600. return buffer;
  601. #endif // end of _PLATFORM_LINUX_
  602. }
  603. FORCE_INLINE void* dll_symbol(dll_handle_t handle, const char* name)
  604. {
  605. #if defined(_PLATFORM_WINDOWS_)
  606. return GetProcAddress(handle, name);
  607. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  608. dlerror();
  609. void* addr = dlsym(handle, name);
  610. char* err = dlerror();
  611. if (err) {
  612. return NULL;
  613. }
  614. return addr;
  615. #endif // end of _PLATFORM_LINUX_
  616. }
  617. FORCE_INLINE bool dll_close(dll_handle_t handle)
  618. {
  619. #if defined(_PLATFORM_WINDOWS_)
  620. return FreeLibrary(handle) == TRUE;
  621. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  622. return dlclose(handle) == 0;
  623. #endif // end of _PLATFORM_LINUX_
  624. }
  625. FORCE_INLINE file_search_t* find_open()
  626. {
  627. file_search_t* find_ = new file_search_t;
  628. memset(find_, 0, sizeof(file_search_t));
  629. return find_;
  630. }
  631. FORCE_INLINE bool find_first(file_search_t* file_search, const char* path,
  632. const char* name)
  633. {
  634. #if defined(_PLATFORM_WINDOWS_)
  635. file_search->handle = INVALID_HANDLE_VALUE;
  636. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  637. file_search->pdir = NULL;
  638. file_search->pent = NULL;
  639. file_search->strpath[0] = 0;
  640. file_search->strext[0] = 0;
  641. #endif // end of _PLATFORM_LINUX_
  642. #if defined(_PLATFORM_WINDOWS_)
  643. char fname[512];
  644. if (name[0] == 0) {
  645. // search all file
  646. _snprintf(fname, sizeof(fname) - 1, "%s*.*", path);
  647. fname[sizeof(fname) - 1] = 0;
  648. }
  649. else {
  650. if (strchr(name, '.') != NULL) {
  651. // match symbol
  652. _snprintf(fname, sizeof(fname) - 1, "%s%s", path, name);
  653. fname[sizeof(fname) - 1] = 0;
  654. }
  655. else {
  656. // extend file name
  657. _snprintf(fname, sizeof(fname) - 1, "%s*.%s", path, name);
  658. fname[sizeof(fname) - 1] = 0;
  659. }
  660. }
  661. file_search->handle = FindFirstFile(fname, &file_search->data);
  662. if (INVALID_HANDLE_VALUE == file_search->handle) {
  663. return false;
  664. }
  665. while (true) {
  666. const char* _file_name = file_search->data.cFileName;
  667. if ((strcmp(_file_name, ".") == 0) || (strcmp(_file_name, "..") == 0)) {
  668. // 剔除父目录和当前目录(win下隐藏文件和普通文件一样遍历)
  669. if (FindNextFile(file_search->handle, &file_search->data) != TRUE) {
  670. return false;
  671. }
  672. continue;
  673. }
  674. break;
  675. }
  676. return true;
  677. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  678. char sname[512];
  679. get_standard_path(path, sname, sizeof(sname));
  680. size_t path_len = strlen(sname);
  681. if (path_len >= sizeof(file_search->strpath)) {
  682. return false;
  683. }
  684. const char* nameDummy = name;
  685. {
  686. char buf[512];
  687. const char* tok1 = strrchr(name, '/');
  688. const char* tok2 = strrchr(name, '\\');
  689. const char* tok = defmax(tok1, tok2);
  690. if (tok > name) {
  691. memcpy(buf, name, tok - name);
  692. buf[tok - name] = 0;
  693. strcat(sname, "/");
  694. strcat(sname, buf);
  695. get_standard_path(sname, buf, sizeof(buf));
  696. strcpy(sname, buf);
  697. nameDummy = tok + 1;
  698. }
  699. }
  700. // 文件扩展名,只支持(*.*)或(*.xxx)的格式
  701. const char* ext = nameDummy;
  702. const char* name_dot = strchr(nameDummy, '.');
  703. if (name_dot) {
  704. if (*(name_dot + 1) == '*') {
  705. // 认为是(*.*)
  706. ext = "";
  707. }
  708. else {
  709. // (*.xxx)
  710. ext = name_dot + 1;
  711. }
  712. }
  713. size_t ext_len = strlen(ext);
  714. if (ext_len >= sizeof(file_search->strext)) {
  715. return false;
  716. }
  717. DIR* pDir = opendir(sname);
  718. if (NULL == pDir) {
  719. return false;
  720. }
  721. dirent* pEnt = readdir(pDir);
  722. if (ext[0] != 0) {
  723. while (pEnt) {
  724. if (strcasecmp(pEnt->d_name, ".") == 0 || strcasecmp(pEnt->d_name, "..") == 0) {
  725. // 剔除父目录和当前目录(注意并没有剔除隐藏文件,需要自己剔除)
  726. // 读取下一个
  727. pEnt = readdir(pDir);
  728. continue;
  729. }
  730. const char* dot = strchr(pEnt->d_name, '.');
  731. if (dot) {
  732. if (strcasecmp(ext, dot + 1) == 0) {
  733. // 文件扩展名匹配
  734. break;
  735. }
  736. }
  737. // 读取下一个
  738. pEnt = readdir(pDir);
  739. }
  740. }
  741. else {
  742. while (pEnt) {
  743. if (strcasecmp(pEnt->d_name, ".") == 0 || strcasecmp(pEnt->d_name, "..") == 0) {
  744. // 剔除父目录和当前目录(注意并没有剔除隐藏文件,需要自己剔除)
  745. // 读取下一个
  746. pEnt = readdir(pDir);
  747. }
  748. else {
  749. break;
  750. }
  751. }
  752. }
  753. if (NULL == pEnt) {
  754. closedir(pDir);
  755. return false;
  756. }
  757. file_search->pdir = pDir;
  758. file_search->pent = pEnt;
  759. memcpy(file_search->strpath, path, path_len + 1);
  760. memcpy(file_search->strext, ext, ext_len + 1);
  761. return true;
  762. #endif // end of _PLATFORM_LINUX_
  763. }
  764. FORCE_INLINE const char* get_find_name(file_search_t* file_search)
  765. {
  766. #if defined(_PLATFORM_WINDOWS_)
  767. return file_search->data.cFileName;
  768. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  769. return file_search->pent->d_name;
  770. #endif // end of _PLATFORM_LINUX_
  771. }
  772. FORCE_INLINE bool find_is_file(file_search_t* file_search)
  773. {
  774. #if defined(_PLATFORM_WINDOWS_)
  775. return (file_search->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
  776. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  777. std::string fname(file_search->strpath);
  778. fname += "/";
  779. fname += file_search->pent->d_name;
  780. struct stat st;
  781. if (stat(fname.c_str(), &st) == -1) {
  782. return false;
  783. }
  784. return (st.st_mode & S_IFMT) == S_IFREG;
  785. #endif // end of _PLATFORM_LINUX_
  786. }
  787. FORCE_INLINE bool find_is_dir(file_search_t* file_search)
  788. {
  789. #if defined(_PLATFORM_WINDOWS_)
  790. return (file_search->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  791. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  792. std::string fname(file_search->strpath);
  793. fname += "/";
  794. fname += file_search->pent->d_name;
  795. struct stat st;
  796. if (stat(fname.c_str(), &st) == -1) {
  797. return false;
  798. }
  799. return (st.st_mode & S_IFMT) == S_IFDIR;
  800. #endif // end of _PLATFORM_LINUX_
  801. }
  802. FORCE_INLINE bool find_next(file_search_t* file_search)
  803. {
  804. #if defined(_PLATFORM_WINDOWS_)
  805. if (FindNextFile(file_search->handle, &file_search->data) != TRUE) {
  806. return false;
  807. }
  808. while (true) {
  809. const char* _file_name = file_search->data.cFileName;
  810. if ((strcmp(_file_name, ".") == 0) || (strcmp(_file_name, "..") == 0)) {
  811. // 剔除父目录和当前目录(win下隐藏文件和普通文件一样遍历)
  812. if (FindNextFile(file_search->handle, &file_search->data) != TRUE) {
  813. return false;
  814. }
  815. continue;
  816. }
  817. break;
  818. }
  819. return true;
  820. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  821. dirent* pEnt = readdir(file_search->pdir);
  822. const char* ext = file_search->strext;
  823. if (ext[0] != 0) {
  824. while (pEnt) {
  825. if (strcasecmp(pEnt->d_name, ".") == 0 || strcasecmp(pEnt->d_name, "..") == 0) {
  826. // 剔除父目录和当前目录(注意并没有剔除隐藏文件,需要自己剔除)
  827. // 读取下一个
  828. pEnt = readdir(file_search->pdir);
  829. continue;
  830. }
  831. const char* dot = strchr(pEnt->d_name, '.');
  832. if (dot) {
  833. if (strcasecmp(ext, dot + 1) == 0) {
  834. // match file ext
  835. break;
  836. }
  837. }
  838. // next
  839. pEnt = readdir(file_search->pdir);
  840. }
  841. }
  842. else {
  843. while (pEnt) {
  844. if (strcasecmp(pEnt->d_name, ".") == 0 || strcasecmp(pEnt->d_name, "..") == 0) {
  845. // 剔除父目录和当前目录(注意并没有剔除隐藏文件,需要自己剔除)
  846. // 读取下一个
  847. pEnt = readdir(file_search->pdir);
  848. }
  849. else {
  850. break;
  851. }
  852. }
  853. }
  854. if (NULL == pEnt) {
  855. return false;
  856. }
  857. file_search->pent = pEnt;
  858. return true;
  859. #endif // end of _PLATFORM_LINUX_
  860. }
  861. FORCE_INLINE bool find_close(file_search_t* file_search)
  862. {
  863. #if defined(_PLATFORM_WINDOWS_)
  864. if (file_search->handle != INVALID_HANDLE_VALUE) {
  865. if (FindClose(file_search->handle) != TRUE) {
  866. delete file_search;
  867. return false;
  868. }
  869. }
  870. #elif defined(_PLATFORM_LINUX_) // end of _PLATFORM_WINDOWS_
  871. if (file_search->pdir != NULL) {
  872. if (closedir(file_search->pdir) != 0) {
  873. delete file_search;
  874. return false;
  875. }
  876. }
  877. #endif // end of _PLATFORM_LINUX_
  878. delete file_search;
  879. return true;
  880. }
  881. }