libcm is a C development framework with an emphasis on audio signal processing applications.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

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 = { NULL };
  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. }