libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmFile.c 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmFile.h"
  9. #include "cmFileSys.h"
  10. #include "cmMem.h"
  11. #include "cmMallocDebug.h"
  12. #include "cmLinkedHeap.h"
  13. #include "cmText.h"
  14. #include <sys/stat.h>
  15. cmFileH_t cmFileNullHandle = cmSTATIC_NULL_HANDLE;
  16. typedef struct
  17. {
  18. FILE* fp;
  19. cmErr_t err;
  20. cmChar_t* fnStr;
  21. } cmFile_t;
  22. cmFile_t* _cmFileHandleToPtr( cmFileH_t h )
  23. {
  24. cmFile_t* p = (cmFile_t*)h.h;
  25. assert(p != NULL);
  26. return p;
  27. }
  28. cmFileRC_t _cmFileError( cmFile_t* p, cmFileRC_t rc, int errNumb, const cmChar_t* msg )
  29. {
  30. if(errNumb == 0)
  31. rc = cmErrMsg(&p->err,rc,"%s on file '%s'",msg,p->fnStr);
  32. else
  33. rc = cmErrMsg(&p->err,rc,"%s on file '%s'\nSystem Msg:%s",msg,p->fnStr,strerror(errNumb));
  34. return rc;
  35. }
  36. cmFileRC_t cmFileOpen( cmFileH_t* hp, const cmChar_t* fn, enum cmFileOpenFlags_t flags, cmRpt_t* rpt )
  37. {
  38. char mode[] = "/0/0/0";
  39. cmFile_t* p = NULL;
  40. cmErr_t err;
  41. cmFileRC_t rc;
  42. if((rc = cmFileClose(hp)) != kOkFileRC )
  43. return rc;
  44. cmErrSetup(&err,rpt,"File");
  45. hp->h = NULL;
  46. if( cmIsFlag(flags,kReadFileFl) )
  47. mode[0] = 'r';
  48. else
  49. if( cmIsFlag(flags,kWriteFileFl) )
  50. mode[0] = 'w';
  51. else
  52. if( cmIsFlag(flags,kAppendFileFl) )
  53. mode[0] = 'a';
  54. else
  55. cmErrMsg(&err,kInvalidFlagFileRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'.");
  56. if( cmIsFlag(flags,kUpdateFileFl) )
  57. mode[1] = '+';
  58. // handle requests to use stdin,stdout,stderr
  59. FILE* sfp = NULL;
  60. if( cmIsFlag(flags,kStdoutFileFl) )
  61. {
  62. sfp = stdout;
  63. fn = "stdout";
  64. }
  65. else
  66. if( cmIsFlag(flags,kStderrFileFl) )
  67. {
  68. sfp = stderr;
  69. fn = "stderr";
  70. }
  71. else
  72. if( cmIsFlag(flags,kStdinFileFl) )
  73. {
  74. sfp = stdin;
  75. fn = "stdin";
  76. }
  77. if( fn == NULL )
  78. return cmErrMsg(&err,kObjAllocFailFileRC,"File object allocation failed due to empty file name.");
  79. unsigned byteCnt = sizeof(cmFile_t) + strlen(fn) + 1;
  80. if((p = (cmFile_t*)cmMemMallocZ(byteCnt)) == NULL )
  81. return cmErrMsg(&err,kObjAllocFailFileRC,"File object allocation failed for file '%s'.",cmStringNullGuard(fn));
  82. cmErrClone(&p->err,&err);
  83. p->fnStr = (cmChar_t*)(p+1);
  84. strcpy(p->fnStr,fn);
  85. if( sfp != NULL )
  86. p->fp = sfp;
  87. else
  88. {
  89. errno = 0;
  90. if((p->fp = fopen(fn,mode)) == NULL )
  91. {
  92. cmFileRC_t rc = _cmFileError(p,kOpenFailFileRC,errno,"File open failed");
  93. cmMemFree(p);
  94. return rc;
  95. }
  96. }
  97. hp->h = p;
  98. return kOkFileRC;
  99. }
  100. cmFileRC_t cmFileClose( cmFileH_t* hp )
  101. {
  102. if( cmFileIsValid(*hp) == false )
  103. return kOkFileRC;
  104. cmFile_t* p = _cmFileHandleToPtr(*hp);
  105. errno = 0;
  106. if( p->fp != NULL )
  107. if( fclose(p->fp) != 0 )
  108. return _cmFileError(p,kCloseFailFileRC,errno,"File close failed");
  109. cmMemFree(p);
  110. hp->h = NULL;
  111. return kOkFileRC;
  112. }
  113. bool cmFileIsValid( cmFileH_t h )
  114. { return h.h != NULL; }
  115. cmFileRC_t cmFileRead( cmFileH_t h, void* buf, unsigned bufByteCnt )
  116. {
  117. cmFile_t* p = _cmFileHandleToPtr(h);
  118. errno = 0;
  119. if( fread(buf,bufByteCnt,1,p->fp) != 1 )
  120. return _cmFileError(p,kReadFailFileRC,errno,"File read failed");
  121. return kOkFileRC;
  122. }
  123. cmFileRC_t cmFileWrite( cmFileH_t h, const void* buf, unsigned bufByteCnt )
  124. {
  125. cmFile_t* p = _cmFileHandleToPtr(h);
  126. errno = 0;
  127. if( fwrite(buf,bufByteCnt,1,p->fp) != 1 )
  128. return _cmFileError(p,kWriteFailFileRC,errno,"File write failed");
  129. return kOkFileRC;
  130. }
  131. cmFileRC_t cmFileSeek( cmFileH_t h, enum cmFileSeekFlags_t flags, int offsByteCnt )
  132. {
  133. cmFile_t* p = _cmFileHandleToPtr(h);
  134. unsigned fileflags = 0;
  135. if( cmIsFlag(flags,kBeginFileFl) )
  136. fileflags = SEEK_SET;
  137. else
  138. if( cmIsFlag(flags,kCurFileFl) )
  139. fileflags = SEEK_CUR;
  140. else
  141. if( cmIsFlag(flags,kEndFileFl) )
  142. fileflags = SEEK_END;
  143. else
  144. return cmErrMsg(&p->err,kInvalidFlagFileRC,"Invalid file seek flag on '%s'.",p->fnStr);
  145. errno = 0;
  146. if( fseek(p->fp,offsByteCnt,fileflags) != 0 )
  147. return _cmFileError(p,kSeekFailFileRC,errno,"File seek failed");
  148. return kOkFileRC;
  149. }
  150. cmFileRC_t cmFileTell( cmFileH_t h, long* offsPtr )
  151. {
  152. assert( offsPtr != NULL );
  153. *offsPtr = -1;
  154. cmFile_t* p = _cmFileHandleToPtr(h);
  155. errno = 0;
  156. if((*offsPtr = ftell(p->fp)) == -1)
  157. return _cmFileError(p,kTellFailFileRC,errno,"File tell failed");
  158. return kOkFileRC;
  159. }
  160. bool cmFileEof( cmFileH_t h )
  161. { return feof( _cmFileHandleToPtr(h)->fp ) != 0; }
  162. unsigned cmFileByteCount( cmFileH_t h )
  163. {
  164. struct stat sr;
  165. int f;
  166. cmFile_t* p = _cmFileHandleToPtr(h);
  167. const cmChar_t errMsg[] = "File byte count request failed.";
  168. errno = 0;
  169. if((f = fileno(p->fp)) == -1)
  170. {
  171. _cmFileError(p,kHandleInvalidFileRC,errno,errMsg);
  172. return 0;
  173. }
  174. if(fstat(f,&sr) == -1)
  175. {
  176. _cmFileError(p,kStatFailFileRC,errno,errMsg);
  177. return 0;
  178. }
  179. return sr.st_size;
  180. }
  181. cmFileRC_t cmFileByteCountFn( const cmChar_t* fn, cmRpt_t* rpt, unsigned* fileByteCntPtr )
  182. {
  183. assert( fileByteCntPtr != NULL );
  184. cmFileRC_t rc;
  185. cmFileH_t h = cmFileNullHandle;
  186. if((rc = cmFileOpen(&h,fn,kReadFileFl,rpt)) != kOkFileRC )
  187. return rc;
  188. if( fileByteCntPtr != NULL)
  189. *fileByteCntPtr = cmFileByteCount(h);
  190. cmFileClose(&h);
  191. return rc;
  192. }
  193. cmFileRC_t cmFileCompare( const cmChar_t* fn0, const cmChar_t* fn1, cmRpt_t* rpt, bool* isEqualPtr )
  194. {
  195. cmFileRC_t rc = kOkFileRC;
  196. unsigned bufByteCnt = 2048;
  197. cmFileH_t h0 = cmFileNullHandle;
  198. cmFileH_t h1 = cmFileNullHandle;
  199. char b0[ bufByteCnt ];
  200. char b1[ bufByteCnt ];
  201. assert(isEqualPtr != NULL );
  202. *isEqualPtr = true;
  203. if((rc = cmFileOpen(&h0,fn0,kReadFileFl,rpt)) != kOkFileRC )
  204. goto errLabel;
  205. if((rc = cmFileOpen(&h1,fn1,kReadFileFl,rpt)) != kOkFileRC )
  206. goto errLabel;
  207. cmFile_t* p0 = _cmFileHandleToPtr(h0);
  208. cmFile_t* p1 = _cmFileHandleToPtr(h1);
  209. while(1)
  210. {
  211. size_t n0 = fread(b0,1,bufByteCnt,p0->fp);
  212. size_t n1 = fread(b1,1,bufByteCnt,p1->fp);
  213. if( n0 != n1 || memcmp(b0,b1,n0) != 0 )
  214. {
  215. *isEqualPtr = false;
  216. break;
  217. }
  218. if( n0 != bufByteCnt || n1 != bufByteCnt )
  219. break;
  220. }
  221. errLabel:
  222. cmFileClose(&h0);
  223. cmFileClose(&h1);
  224. return rc;
  225. }
  226. const cmChar_t* cmFileName( cmFileH_t h )
  227. {
  228. cmFile_t* p = _cmFileHandleToPtr(h);
  229. return p->fnStr;
  230. }
  231. cmFileRC_t cmFileFnWrite( const cmChar_t* fn, cmRpt_t* rpt, const void* buf, unsigned bufByteCnt )
  232. {
  233. cmFileH_t h = cmFileNullHandle;
  234. cmFileRC_t rc;
  235. if((rc = cmFileOpen(&h,fn,kWriteFileFl,rpt)) != kOkFileRC )
  236. goto errLabel;
  237. rc = cmFileWrite(h,buf,bufByteCnt);
  238. errLabel:
  239. cmFileClose(&h);
  240. return rc;
  241. }
  242. cmChar_t* _cmFileToBuf( cmFileH_t h, unsigned nn, unsigned* bufByteCntPtr )
  243. {
  244. errno = 0;
  245. unsigned n = cmFileByteCount(h);
  246. cmChar_t* buf = NULL;
  247. cmFile_t* p = _cmFileHandleToPtr(h);
  248. // if the file size calculation is ok
  249. if( errno != 0 )
  250. {
  251. _cmFileError(p,kBufAllocFailFileRC,errno,"Invalid file buffer length.");
  252. goto errLabel;
  253. }
  254. // allocate the read target buffer
  255. if((buf = cmMemAlloc(cmChar_t,n+nn)) == NULL)
  256. {
  257. _cmFileError(p,kBufAllocFailFileRC,0,"Read buffer allocation failed.");
  258. goto errLabel;
  259. }
  260. // read the file
  261. if( cmFileRead(h,buf,n) != kOkFileRC )
  262. goto errLabel;
  263. // zero memory after the file data
  264. memset(buf+n,0,nn);
  265. if( bufByteCntPtr != NULL )
  266. *bufByteCntPtr = n;
  267. return buf;
  268. errLabel:
  269. if( bufByteCntPtr != NULL )
  270. *bufByteCntPtr = 0;
  271. cmMemFree(buf);
  272. return NULL;
  273. }
  274. cmChar_t* _cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned nn, unsigned* bufByteCntPtr )
  275. {
  276. cmFileH_t h = cmFileNullHandle;
  277. cmChar_t* buf = NULL;
  278. if( cmFileOpen(&h,fn,kReadFileFl | kBinaryFileFl,rpt) != kOkFileRC )
  279. goto errLabel;
  280. buf = _cmFileToBuf(h,nn,bufByteCntPtr);
  281. errLabel:
  282. cmFileClose(&h);
  283. return buf;
  284. }
  285. cmFileRC_t cmFileCopy(
  286. const cmChar_t* srcDir,
  287. const cmChar_t* srcFn,
  288. const cmChar_t* srcExt,
  289. const cmChar_t* dstDir,
  290. const cmChar_t* dstFn,
  291. const cmChar_t* dstExt,
  292. cmErr_t* err)
  293. {
  294. cmFileRC_t rc = kOkFileRC;
  295. unsigned byteCnt = 0;
  296. cmChar_t* buf = NULL;
  297. const cmChar_t* srcPathFn = NULL;
  298. const cmChar_t* dstPathFn = NULL;
  299. // form the source path fn
  300. if((srcPathFn = cmFsMakeFn(srcDir,srcFn,srcExt,NULL)) == NULL )
  301. {
  302. rc = cmErrMsg(err,kFileSysFailFileRC,"The soure file name for dir:%s name:%s ext:%s could not be formed.",cmStringNullGuard(srcDir),cmStringNullGuard(srcFn),cmStringNullGuard(srcExt));
  303. goto errLabel;
  304. }
  305. // form the dest path fn
  306. if((dstPathFn = cmFsMakeFn(dstDir,dstFn,dstExt,NULL)) == NULL )
  307. {
  308. rc = cmErrMsg(err,kFileSysFailFileRC,"The destination file name for dir:%s name:%s ext:%s could not be formed.",cmStringNullGuard(dstDir),cmStringNullGuard(dstFn),cmStringNullGuard(dstExt));
  309. goto errLabel;
  310. }
  311. // verify that the source exists
  312. if( cmFsIsFile(srcPathFn) == false )
  313. {
  314. rc = cmErrMsg(err,kOpenFailFileRC,"The source file '%s' does not exist.",cmStringNullGuard(srcPathFn));
  315. goto errLabel;
  316. }
  317. // read the source file into a buffer
  318. if((buf = cmFileFnToBuf(srcPathFn,err->rpt,&byteCnt)) == NULL )
  319. rc = cmErrMsg(err,kReadFailFileRC,"Attempt to fill a buffer from '%s' failed.",cmStringNullGuard(srcPathFn));
  320. else
  321. {
  322. // write the file to the output file
  323. if( cmFileFnWrite(dstPathFn,err->rpt,buf,byteCnt) != kOkFileRC )
  324. rc = cmErrMsg(err,kWriteFailFileRC,"An attempt to write a buffer to '%s' failed.",cmStringNullGuard(dstPathFn));
  325. }
  326. errLabel:
  327. // free the buffer
  328. cmMemFree(buf);
  329. cmFsFreeFn(srcPathFn);
  330. cmFsFreeFn(dstPathFn);
  331. return rc;
  332. }
  333. cmFileRC_t cmFileBackup( const cmChar_t* dir, const cmChar_t* name, const cmChar_t* ext, cmErr_t* err )
  334. {
  335. cmFileRC_t rc = kOkFileRC;
  336. cmChar_t* newName = NULL;
  337. const cmChar_t* newFn = NULL;
  338. unsigned n = 0;
  339. const cmChar_t* srcFn = NULL;
  340. cmFileSysPathPart_t* pp = NULL;
  341. // form the name of the backup file
  342. if((srcFn = cmFsMakeFn(dir,name,ext,NULL)) == NULL )
  343. {
  344. rc = cmErrMsg(err,kFileSysFailFileRC,"Backup source file name formation failed.");
  345. goto errLabel;
  346. }
  347. // if the src file does not exist then there is nothing to do
  348. if( cmFsIsFile(srcFn) == false )
  349. return rc;
  350. // break the source file name up into dir/fn/ext.
  351. if((pp = cmFsPathParts(srcFn)) == NULL || pp->fnStr==NULL)
  352. {
  353. rc = cmErrMsg(err,kFileSysFailFileRC,"The file name '%s' could not be parsed into its parts.",cmStringNullGuard(srcFn));
  354. goto errLabel;
  355. }
  356. // iterate until a unique file name is found
  357. for(n=0; 1; ++n)
  358. {
  359. cmFsFreeFn(newFn);
  360. // generate a new file name
  361. newName = cmTsPrintfP(newName,"%s_%i",pp->fnStr,n);
  362. // form the new file name into a complete path
  363. if((newFn = cmFsMakeFn(pp->dirStr,newName,pp->extStr,NULL)) == NULL )
  364. {
  365. rc = cmErrMsg(err,kFileSysFailFileRC,"A backup file name could not be formed for the file '%s'.",cmStringNullGuard(newName));
  366. goto errLabel;
  367. }
  368. // if the new file name is not already in use ...
  369. if( cmFsIsFile(newFn) == false )
  370. {
  371. // .. then duplicate the file
  372. if((rc = cmFileCopy(srcFn,NULL,NULL,newFn,NULL,NULL,err)) != kOkFileRC )
  373. rc = cmErrMsg(err,rc,"The file '%s' could not be duplicated as '%s'.",cmStringNullGuard(srcFn),cmStringNullGuard(newFn));
  374. break;
  375. }
  376. }
  377. errLabel:
  378. cmFsFreeFn(srcFn);
  379. cmFsFreeFn(newFn);
  380. cmMemFree(newName);
  381. cmFsFreePathParts(pp);
  382. return rc;
  383. }
  384. cmChar_t* cmFileToBuf( cmFileH_t h, unsigned* bufByteCntPtr )
  385. { return _cmFileToBuf(h,0,bufByteCntPtr); }
  386. cmChar_t* cmFileFnToBuf( const cmChar_t* fn, cmRpt_t* rpt, unsigned* bufByteCntPtr )
  387. { return _cmFileFnToBuf(fn,rpt,0,bufByteCntPtr); }
  388. cmChar_t* cmFileToStr( cmFileH_t h, unsigned* bufByteCntPtr )
  389. { return _cmFileToBuf(h,1,bufByteCntPtr); }
  390. cmChar_t* cmFileFnToStr( const cmChar_t* fn, cmRpt_t* rpt, unsigned* bufByteCntPtr )
  391. { return _cmFileFnToBuf(fn,rpt,1,bufByteCntPtr); }
  392. cmFileRC_t cmFileLineCount( cmFileH_t h, unsigned* lineCntPtr )
  393. {
  394. cmFileRC_t rc = kOkFileRC;
  395. cmFile_t* p = _cmFileHandleToPtr(h);
  396. unsigned lineCnt = 0;
  397. long offs;
  398. int c;
  399. assert( lineCntPtr != NULL );
  400. *lineCntPtr = 0;
  401. if((rc = cmFileTell(h,&offs)) != kOkFileRC )
  402. return rc;
  403. errno = 0;
  404. while(1)
  405. {
  406. c = fgetc(p->fp);
  407. if( c == EOF )
  408. {
  409. if( errno )
  410. rc =_cmFileError(p,kReadFailFileRC,errno,"File read char failed");
  411. else
  412. ++lineCnt; // add one in case the last line isn't terminated with a '\n'.
  413. break;
  414. }
  415. // if an end-of-line was encountered
  416. if( c == '\n' )
  417. ++lineCnt;
  418. }
  419. if((rc = cmFileSeek(h,kBeginFileFl,offs)) != kOkFileRC )
  420. return rc;
  421. *lineCntPtr = lineCnt;
  422. return rc;
  423. }
  424. cmFileRC_t _cmFileGetLine( cmFile_t* p, cmChar_t* buf, unsigned* bufByteCntPtr )
  425. {
  426. // fgets() reads up to n-1 bytes into buf[]
  427. if( fgets(buf,*bufByteCntPtr,p->fp) == NULL )
  428. {
  429. // an read error or EOF condition occurred
  430. *bufByteCntPtr = 0;
  431. if( !feof(p->fp ) )
  432. return _cmFileError(p,kReadFailFileRC,errno,"File read line failed");
  433. return kReadFailFileRC;
  434. }
  435. return kOkFileRC;
  436. }
  437. cmFileRC_t cmFileGetLine( cmFileH_t h, cmChar_t* buf, unsigned* bufByteCntPtr )
  438. {
  439. assert( bufByteCntPtr != NULL );
  440. cmFile_t* p = _cmFileHandleToPtr(h);
  441. unsigned tn = 128;
  442. cmChar_t t[ tn ];
  443. unsigned on = *bufByteCntPtr;
  444. long offs;
  445. cmFileRC_t rc;
  446. // store the current file offset
  447. if((rc = cmFileTell(h,&offs)) != kOkFileRC )
  448. return rc;
  449. // if no buffer was given then use t[]
  450. if( buf == NULL || *bufByteCntPtr == 0 )
  451. {
  452. *bufByteCntPtr = tn;
  453. buf = t;
  454. }
  455. // fill the buffer from the current line
  456. if((rc = _cmFileGetLine(p,buf,bufByteCntPtr)) != kOkFileRC )
  457. return rc;
  458. // get length of the string in the buffer
  459. // (this is one less than the count of bytes written to the buffer)
  460. unsigned n = strlen(buf);
  461. // if the provided buffer was large enough to read the entire string
  462. if( on > n+1 )
  463. {
  464. //*bufByteCntPtr = n+1;
  465. return kOkFileRC;
  466. }
  467. //
  468. // the provided buffer was not large enough
  469. //
  470. // m tracks the length of the string
  471. unsigned m = n;
  472. while( n+1 == *bufByteCntPtr )
  473. {
  474. // fill the buffer from the current line
  475. if((rc = _cmFileGetLine(p,buf,bufByteCntPtr)) != kOkFileRC )
  476. return rc;
  477. n = strlen(buf);
  478. m += n;
  479. }
  480. // restore the original file offset
  481. if((rc = cmFileSeek(h,kBeginFileFl,offs)) != kOkFileRC )
  482. return rc;
  483. // add 1 for /0, 1 for /n and 1 to detect buf-too-short
  484. *bufByteCntPtr = m+3;
  485. return kBufTooSmallFileRC;
  486. }
  487. cmFileRC_t cmFileGetLineAuto( cmFileH_t h, cmChar_t** bufPtrPtr, unsigned* bufByteCntPtr )
  488. {
  489. cmFileRC_t rc = kOkFileRC;
  490. bool fl = true;
  491. cmChar_t* buf = *bufPtrPtr;
  492. *bufPtrPtr = NULL;
  493. while(fl)
  494. {
  495. fl = false;
  496. switch( rc = cmFileGetLine(h,buf,bufByteCntPtr) )
  497. {
  498. case kOkFileRC:
  499. {
  500. *bufPtrPtr = buf;
  501. }
  502. break;
  503. case kBufTooSmallFileRC:
  504. buf = cmMemResizeZ(cmChar_t,buf,*bufByteCntPtr);
  505. fl = true;
  506. break;
  507. default:
  508. cmMemFree(buf);
  509. break;
  510. }
  511. }
  512. return rc;
  513. }
  514. cmFileRC_t cmFileReadChar( cmFileH_t h, char* buf, unsigned cnt )
  515. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  516. cmFileRC_t cmFileReadUChar( cmFileH_t h, unsigned char* buf, unsigned cnt )
  517. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  518. cmFileRC_t cmFileReadShort( cmFileH_t h, short* buf, unsigned cnt )
  519. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  520. cmFileRC_t cmFileReadUShort( cmFileH_t h, unsigned short* buf, unsigned cnt )
  521. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  522. cmFileRC_t cmFileReadLong( cmFileH_t h, long* buf, unsigned cnt )
  523. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  524. cmFileRC_t cmFileReadULong( cmFileH_t h, unsigned long* buf, unsigned cnt )
  525. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  526. cmFileRC_t cmFileReadInt( cmFileH_t h, int* buf, unsigned cnt )
  527. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  528. cmFileRC_t cmFileReadUInt( cmFileH_t h, unsigned int* buf, unsigned cnt )
  529. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  530. cmFileRC_t cmFileReadFloat( cmFileH_t h, float* buf, unsigned cnt )
  531. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  532. cmFileRC_t cmFileReadDouble( cmFileH_t h, double* buf, unsigned cnt )
  533. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  534. cmFileRC_t cmFileReadBool( cmFileH_t h, bool* buf, unsigned cnt )
  535. { return cmFileRead(h,buf,sizeof(buf[0])*cnt); }
  536. cmFileRC_t cmFileWriteChar( cmFileH_t h, const char* buf, unsigned cnt )
  537. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  538. cmFileRC_t cmFileWriteUChar( cmFileH_t h, const unsigned char* buf, unsigned cnt )
  539. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  540. cmFileRC_t cmFileWriteShort( cmFileH_t h, const short* buf, unsigned cnt )
  541. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  542. cmFileRC_t cmFileWriteUShort( cmFileH_t h, const unsigned short* buf, unsigned cnt )
  543. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  544. cmFileRC_t cmFileWriteLong( cmFileH_t h, const long* buf, unsigned cnt )
  545. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  546. cmFileRC_t cmFileWriteULong( cmFileH_t h, const unsigned long* buf, unsigned cnt )
  547. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  548. cmFileRC_t cmFileWriteInt( cmFileH_t h, const int* buf, unsigned cnt )
  549. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  550. cmFileRC_t cmFileWriteUInt( cmFileH_t h, const unsigned int* buf, unsigned cnt )
  551. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  552. cmFileRC_t cmFileWriteFloat( cmFileH_t h, const float* buf, unsigned cnt )
  553. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  554. cmFileRC_t cmFileWriteDouble( cmFileH_t h, const double* buf, unsigned cnt )
  555. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  556. cmFileRC_t cmFileWriteBool( cmFileH_t h, const bool* buf, unsigned cnt )
  557. { return cmFileWrite(h,buf,sizeof(buf[0])*cnt); }
  558. cmFileRC_t cmFileWriteStr( cmFileH_t h, const cmChar_t* s )
  559. {
  560. cmFileRC_t rc;
  561. unsigned n = cmTextLength(s);
  562. if((rc = cmFileWriteUInt(h,&n,1)) != kOkFileRC )
  563. return rc;
  564. if( n > 0 )
  565. rc = cmFileWriteChar(h,s,n);
  566. return rc;
  567. }
  568. cmFileRC_t cmFileReadStr( cmFileH_t h, cmChar_t** sRef, unsigned maxCharN )
  569. {
  570. unsigned n;
  571. cmFileRC_t rc;
  572. assert(sRef != NULL );
  573. *sRef = NULL;
  574. if( maxCharN == 0 )
  575. maxCharN = 16384;
  576. // read the string length
  577. if((rc = cmFileReadUInt(h,&n,1)) != kOkFileRC )
  578. return rc;
  579. // verify that string isn't too long
  580. if( n > maxCharN )
  581. {
  582. cmFile_t* p = _cmFileHandleToPtr(h);
  583. return cmErrMsg(&p->err,kBufAllocFailFileRC,"The stored string is larger than the maximum allowable size.");
  584. }
  585. // allocate a read buffer
  586. cmChar_t* s = cmMemAllocZ(cmChar_t,n+1);
  587. // fill the buffer from the file
  588. if((rc = cmFileReadChar(h,s,n)) != kOkFileRC )
  589. return rc;
  590. s[n] = 0; // terminate the string
  591. *sRef = s;
  592. return rc;
  593. }
  594. cmFileRC_t cmFilePrint( cmFileH_t h, const cmChar_t* text )
  595. {
  596. cmFile_t* p = _cmFileHandleToPtr(h);
  597. errno = 0;
  598. if( fputs(text,p->fp) < 0 )
  599. return _cmFileError(p,kPrintFailFileRC,errno,"File print failed");
  600. return kOkFileRC;
  601. }
  602. cmFileRC_t cmFileVPrintf( cmFileH_t h, const cmChar_t* fmt, va_list vl )
  603. {
  604. cmFile_t* p = _cmFileHandleToPtr(h);
  605. if( vfprintf(p->fp,fmt,vl) < 0 )
  606. return _cmFileError(p,kPrintFailFileRC,errno,"File print failed");
  607. return kOkFileRC;
  608. }
  609. cmFileRC_t cmFilePrintf( cmFileH_t h, const cmChar_t* fmt, ... )
  610. {
  611. va_list vl;
  612. va_start(vl,fmt);
  613. cmFileRC_t rc = cmFileVPrintf(h,fmt,vl);
  614. va_end(vl);
  615. return rc;
  616. }
  617. cmFileRC_t cmFileLastRC( cmFileH_t h )
  618. {
  619. cmFile_t* p = _cmFileHandleToPtr(h);
  620. return cmErrLastRC(&p->err);
  621. }
  622. cmFileRC_t cmFileSetRC( cmFileH_t h, cmFileRC_t rc )
  623. {
  624. cmFile_t* p = _cmFileHandleToPtr(h);
  625. return cmErrSetRC(&p->err,rc);
  626. }