libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmFile.c 20KB

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