libcw/cwFile.cpp

884 lines
21 KiB
C++
Raw Normal View History

2019-12-19 03:24:12 +00:00
#include "cwCommon.h"
#include "cwLog.h"
#include "cwCommonImpl.h"
#include "cwTest.h"
#include "cwObject.h"
2019-12-19 03:24:12 +00:00
#include "cwMem.h"
#include "cwFileSys.h"
#include "cwText.h"
#include "cwFile.h"
#ifdef OS_LINUX
2019-12-19 03:24:12 +00:00
#include <sys/stat.h>
#endif
namespace cw
{
namespace file
2019-12-19 03:24:12 +00:00
{
typedef struct file_str
{
FILE* fp;
char* fnStr;
2020-12-29 15:09:43 +00:00
rc_t lastRC;
} this_t;
2019-12-19 03:24:12 +00:00
this_t* _handleToPtr(handle_t h)
{
return handleToPtr<handle_t,this_t>(h);
}
2019-12-19 03:24:12 +00:00
char* _fileToBuf( handle_t h, unsigned nn, unsigned* bufByteCntPtr )
{
errno = 0;
2019-12-19 03:24:12 +00:00
unsigned n = byteCount(h);
char* buf = nullptr;
2019-12-19 03:24:12 +00:00
// if the file size calculation is ok
if( errno != 0 )
{
cwLogSysError(kOpFailRC,errno,"Invalid file buffer length on '%s'.", cwStringNullGuard(name(h)));
goto errLabel;
}
2019-12-19 03:24:12 +00:00
// allocate the read target buffer
if((buf = mem::alloc<char>(n+nn)) == nullptr)
{
cwLogError(kMemAllocFailRC,"Read buffer allocation failed.");
goto errLabel;
}
2019-12-19 03:24:12 +00:00
// read the file
if( read(h,buf,n) != kOkRC )
goto errLabel;
2019-12-19 03:24:12 +00:00
// zero memory after the file data
memset(buf+n,0,nn);
2019-12-19 03:24:12 +00:00
if( bufByteCntPtr != nullptr )
*bufByteCntPtr = n;
2019-12-19 03:24:12 +00:00
return buf;
2019-12-19 03:24:12 +00:00
errLabel:
if( bufByteCntPtr != nullptr )
*bufByteCntPtr = 0;
2019-12-19 03:24:12 +00:00
mem::release(buf);
2019-12-19 03:24:12 +00:00
return nullptr;
2019-12-19 03:24:12 +00:00
}
2019-12-19 03:24:12 +00:00
char* _fileFnToBuf( const char* fn, unsigned nn, unsigned* bufByteCntPtr )
{
handle_t h;
char* buf = nullptr;
2019-12-19 03:24:12 +00:00
if( open(h,fn,kReadFl | kBinaryFl) != kOkRC )
goto errLabel;
2019-12-19 03:24:12 +00:00
buf = _fileToBuf(h,nn,bufByteCntPtr);
2019-12-19 03:24:12 +00:00
errLabel:
close(h);
2019-12-19 03:24:12 +00:00
return buf;
}
2019-12-19 03:24:12 +00:00
rc_t _fileGetLine( this_t* p, char* buf, unsigned* bufByteCntPtr )
{
// fgets() reads up to n-1 bytes into buf[]
if( fgets(buf,*bufByteCntPtr,p->fp) == nullptr )
{
// an read error or EOF condition occurred
*bufByteCntPtr = 0;
2019-12-19 03:24:12 +00:00
if( !feof(p->fp ) )
2020-12-29 15:09:43 +00:00
return p->lastRC = cwLogSysError(kReadFailRC,errno,"File read line failed");
p->lastRC = kEofRC;
return kEofRC;
}
2019-12-19 03:24:12 +00:00
return kOkRC;
}
2019-12-19 03:24:12 +00:00
}
2019-12-19 03:24:12 +00:00
}
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::open( handle_t& hRef, const char* fn, unsigned flags )
2019-12-19 03:24:12 +00:00
{
this_t* p = nullptr;
char* exp_fn = nullptr;
rc_t rc = kOkRC;
char mode[] = "/0/0/0";
if((rc = close(hRef)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
if( cwIsFlag(flags,kReadFl) )
2019-12-19 03:24:12 +00:00
mode[0] = 'r';
else
if( cwIsFlag(flags,kWriteFl) )
2019-12-19 03:24:12 +00:00
mode[0] = 'w';
else
if( cwIsFlag(flags,kAppendFl) )
2019-12-19 03:24:12 +00:00
mode[0] = 'a';
else
cwLogError(kInvalidArgRC,"File open flags must contain 'kReadFl','kWriteFl', or 'kAppendFl'.");
2019-12-19 03:24:12 +00:00
if( cwIsFlag(flags,kUpdateFl) )
2019-12-19 03:24:12 +00:00
mode[1] = '+';
// handle requests to use stdin,stdout,stderr
FILE* sfp = nullptr;
if( cwIsFlag(flags,kStdoutFl) )
2019-12-19 03:24:12 +00:00
{
sfp = stdout;
fn = "stdout";
}
else
if( cwIsFlag(flags,kStderrFl) )
2019-12-19 03:24:12 +00:00
{
sfp = stderr;
fn = "stderr";
}
else
if( cwIsFlag(flags,kStdinFl) )
2019-12-19 03:24:12 +00:00
{
sfp = stdin;
fn = "stdin";
}
// verify the filename is not empty
if( fn == nullptr || strlen(fn)==0 )
2019-12-19 03:24:12 +00:00
return cwLogError(kInvalidArgRC,"File object allocation failed due to empty file name.");
unsigned byteCnt = sizeof(this_t) + strlen(fn) + 1;
2019-12-19 03:24:12 +00:00
// create the file object
if((p = mem::allocZ<this_t>(byteCnt)) == nullptr )
2019-12-19 03:24:12 +00:00
return cwLogError(kOpFailRC,"File object allocation failed for file '%s'.",cwStringNullGuard(fn));
// copy in the file name
2019-12-19 03:24:12 +00:00
p->fnStr = (char*)(p+1);
strcpy(p->fnStr,fn);
// if a special file was requestd
2019-12-19 03:24:12 +00:00
if( sfp != nullptr )
p->fp = sfp;
else
2019-12-19 03:24:12 +00:00
{
exp_fn = filesys::expandPath(fn);
errno = 0;
if((p->fp = fopen(exp_fn,mode)) == nullptr )
rc = p->lastRC = cwLogSysError(kOpenFailRC,errno,"File open failed on file:'%s'.",cwStringNullGuard(fn));
mem::release(exp_fn);
2019-12-19 03:24:12 +00:00
}
if( rc != kOkRC )
mem::release(p);
else
hRef.set(p);
return rc;
2019-12-19 03:24:12 +00:00
}
2020-12-29 15:09:43 +00:00
cw::rc_t cw::file::close( handle_t& hRef )
2019-12-19 03:24:12 +00:00
{
if( isValid(hRef) == false )
2019-12-19 03:24:12 +00:00
return kOkRC;
this_t* p = _handleToPtr(hRef);
2019-12-19 03:24:12 +00:00
errno = 0;
if( p->fp != nullptr )
if( fclose(p->fp) != 0 )
2020-12-29 15:09:43 +00:00
return p->lastRC = cwLogSysError(kCloseFailRC,errno,"File close failed on '%s'.", cwStringNullGuard(p->fnStr));
2019-12-19 03:24:12 +00:00
mem::release(p);
hRef.clear();
2019-12-19 03:24:12 +00:00
return kOkRC;
}
bool cw::file::isValid( handle_t h )
2019-12-19 03:24:12 +00:00
{ return h.isValid(); }
2020-12-29 15:09:43 +00:00
cw::rc_t cw::file::lastRC( handle_t h )
2019-12-19 03:24:12 +00:00
{
2020-12-29 15:09:43 +00:00
this_t* p = _handleToPtr(h);
return p->lastRC;
}
cw::rc_t cw::file::read( handle_t h, void* buf, unsigned bufByteCnt, unsigned* actualByteCntRef )
{
rc_t rc = kOkRC;
this_t* p = _handleToPtr(h);
unsigned actualByteCnt = 0;
if( p->lastRC != kOkRC )
return p->lastRC;
2019-12-19 03:24:12 +00:00
errno = 0;
2020-12-29 15:09:43 +00:00
if(( actualByteCnt = fread(buf,1,bufByteCnt,p->fp)) != bufByteCnt )
{
if( feof( p->fp ) != 0 )
2020-12-29 15:09:43 +00:00
rc = p->lastRC = kEofRC;
else
rc= p->lastRC = cwLogSysError(kReadFailRC,errno,"File read failed on '%s'.", cwStringNullGuard(p->fnStr));
}
2019-12-19 03:24:12 +00:00
2020-12-29 15:09:43 +00:00
if( actualByteCntRef != nullptr )
*actualByteCntRef = actualByteCnt;
return rc;
2019-12-19 03:24:12 +00:00
}
cw::rc_t cw::file::write( handle_t h, const void* buf, unsigned bufByteCnt )
2019-12-19 03:24:12 +00:00
{
this_t* p = _handleToPtr(h);
if( p->lastRC != kOkRC )
return p->lastRC;
2019-12-19 03:24:12 +00:00
if( bufByteCnt )
{
errno = 0;
if( fwrite(buf,bufByteCnt,1,p->fp) != 1 )
return p->lastRC = cwLogSysError(kWriteFailRC,errno,"File write failed on '%s'.", cwStringNullGuard(p->fnStr));
}
2019-12-19 03:24:12 +00:00
return kOkRC;
}
cw::rc_t cw::file::seek( handle_t h, enum seekFlags_t flags, int offsByteCnt )
2019-12-19 03:24:12 +00:00
{
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
unsigned fileflags = 0;
if( cwIsFlag(flags,kBeginFl) )
2019-12-19 03:24:12 +00:00
fileflags = SEEK_SET;
else
if( cwIsFlag(flags,kCurFl) )
2019-12-19 03:24:12 +00:00
fileflags = SEEK_CUR;
else
if( cwIsFlag(flags,kEndFl) )
2019-12-19 03:24:12 +00:00
fileflags = SEEK_END;
else
return cwLogError(kInvalidArgRC,"Invalid file seek flag on '%s'.",cwStringNullGuard(p->fnStr));
errno = 0;
if( fseek(p->fp,offsByteCnt,fileflags) != 0 )
return cwLogSysError(kSeekFailRC,errno,"File seek failed on '%s'",cwStringNullGuard(p->fnStr));
2020-12-29 15:09:43 +00:00
// if the seek succeeded then override any previous error state
p->lastRC = kOkRC;
2019-12-19 03:24:12 +00:00
return kOkRC;
}
cw::rc_t cw::file::tell( handle_t h, long* offsPtr )
2019-12-19 03:24:12 +00:00
{
cwAssert( offsPtr != nullptr );
*offsPtr = -1;
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
errno = 0;
if((*offsPtr = ftell(p->fp)) == -1)
2020-12-29 15:09:43 +00:00
return p->lastRC = cwLogSysError(kOpFailRC,errno,"File tell failed on '%s'.", cwStringNullGuard(p->fnStr));
2019-12-19 03:24:12 +00:00
return kOkRC;
}
bool cw::file::eof( handle_t h )
{ return feof( _handleToPtr(h)->fp ) != 0; }
2019-12-19 03:24:12 +00:00
unsigned cw::file::byteCount( handle_t h )
2019-12-19 03:24:12 +00:00
{
struct stat sr;
int f;
2020-12-29 15:09:43 +00:00
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
const char errMsg[] = "File byte count request failed.";
errno = 0;
if((f = fileno(p->fp)) == -1)
{
2020-12-29 15:09:43 +00:00
p->lastRC = cwLogSysError(kInvalidOpRC,errno,"%s because fileno() failed on '%s'.",errMsg,cwStringNullGuard(p->fnStr));
2019-12-19 03:24:12 +00:00
return 0;
}
if(fstat(f,&sr) == -1)
{
2020-12-29 15:09:43 +00:00
p->lastRC = cwLogSysError(kInvalidOpRC,errno,"%s because fstat() failed on '%s'.",errMsg,cwStringNullGuard(p->fnStr));
2019-12-19 03:24:12 +00:00
return 0;
}
return sr.st_size;
}
cw::rc_t cw::file::byteCountFn( const char* fn, unsigned* fileByteCntPtr )
2019-12-19 03:24:12 +00:00
{
cwAssert( fileByteCntPtr != nullptr );
rc_t rc;
handle_t h;
2019-12-19 03:24:12 +00:00
if((rc = open(h,fn,kReadFl)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
if( fileByteCntPtr != nullptr)
*fileByteCntPtr = byteCount(h);
2019-12-19 03:24:12 +00:00
close(h);
2019-12-19 03:24:12 +00:00
return rc;
}
cw::rc_t cw::file::compare( const char* fn0, const char* fn1, bool& isEqualRef )
2019-12-19 03:24:12 +00:00
{
rc_t rc = kOkRC;
unsigned bufByteCnt = 2048;
handle_t h0;
handle_t h1;
this_t* p0 = nullptr;
this_t* p1 = nullptr;
2019-12-19 03:24:12 +00:00
char b0[ bufByteCnt ];
char b1[ bufByteCnt ];
isEqualRef = true;
if((rc = open(h0,fn0,kReadFl)) != kOkRC )
2019-12-19 03:24:12 +00:00
goto errLabel;
if((rc = open(h1,fn1,kReadFl)) != kOkRC )
2019-12-19 03:24:12 +00:00
goto errLabel;
p0 = _handleToPtr(h0);
p1 = _handleToPtr(h1);
2019-12-19 03:24:12 +00:00
while(1)
{
size_t n0 = fread(b0,1,bufByteCnt,p0->fp);
size_t n1 = fread(b1,1,bufByteCnt,p1->fp);
if( n0 != n1 || memcmp(b0,b1,n0) != 0 )
{
isEqualRef = false;
break;
}
if( n0 != bufByteCnt || n1 != bufByteCnt )
break;
}
errLabel:
close(h0);
close(h1);
2019-12-19 03:24:12 +00:00
return rc;
}
const char* cw::file::name( handle_t h )
2019-12-19 03:24:12 +00:00
{
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
return p->fnStr;
}
cw::rc_t cw::file::fnWrite( const char* fn, const void* buf, unsigned bufByteCnt )
2019-12-19 03:24:12 +00:00
{
handle_t h;
2019-12-19 03:24:12 +00:00
rc_t rc;
if((rc = open(h,fn,kWriteFl)) != kOkRC )
2019-12-19 03:24:12 +00:00
goto errLabel;
rc = write(h,buf,bufByteCnt);
2019-12-19 03:24:12 +00:00
errLabel:
close(h);
2019-12-19 03:24:12 +00:00
return rc;
}
cw::rc_t cw::file::copy(
2019-12-19 03:24:12 +00:00
const char* srcDir,
const char* srcFn,
const char* srcExt,
const char* dstDir,
const char* dstFn,
const char* dstExt)
{
rc_t rc = kOkRC;
unsigned byteCnt = 0;
char* buf = nullptr;
char* srcPathFn = nullptr;
char* dstPathFn = nullptr;
// form the source path fn
if((srcPathFn = filesys::makeFn(srcDir,srcFn,srcExt,nullptr)) == nullptr )
2019-12-19 03:24:12 +00:00
{
rc = cwLogError(kOpFailRC,"The soure file name for dir:%s name:%s ext:%s could not be formed.",cwStringNullGuard(srcDir),cwStringNullGuard(srcFn),cwStringNullGuard(srcExt));
goto errLabel;
}
// form the dest path fn
if((dstPathFn = filesys::makeFn(dstDir,dstFn,dstExt,nullptr)) == nullptr )
2019-12-19 03:24:12 +00:00
{
rc = cwLogError(kOpFailRC,"The destination file name for dir:%s name:%s ext:%s could not be formed.",cwStringNullGuard(dstDir),cwStringNullGuard(dstFn),cwStringNullGuard(dstExt));
goto errLabel;
}
// verify that the source exists
if( filesys::isFile(srcPathFn) == false )
2019-12-19 03:24:12 +00:00
{
rc = cwLogError(kOpenFailRC,"The source file '%s' does not exist.",cwStringNullGuard(srcPathFn));
goto errLabel;
}
// read the source file into a buffer
if((buf = fnToBuf(srcPathFn,&byteCnt)) == nullptr )
2019-12-19 03:24:12 +00:00
rc = cwLogError(kReadFailRC,"Attempt to fill a buffer from '%s' failed.",cwStringNullGuard(srcPathFn));
else
{
// write the file to the output file
if( fnWrite(dstPathFn,buf,byteCnt) != kOkRC )
2019-12-19 03:24:12 +00:00
rc = cwLogError(kWriteFailRC,"An attempt to write a buffer to '%s' failed.",cwStringNullGuard(dstPathFn));
}
errLabel:
// free the buffer
mem::release(buf);
mem::release(srcPathFn);
mem::release(dstPathFn);
2019-12-19 03:24:12 +00:00
return rc;
}
cw::rc_t cw::file::backup( const char* dir, const char* name, const char* ext, const char* dst0_dir )
2019-12-19 03:24:12 +00:00
{
rc_t rc = kOkRC;
char* newName = nullptr;
char* newFn = nullptr;
unsigned n = 0;
char* srcFn = nullptr;
filesys::pathPart_t* pp = nullptr;
const char* dst_dir = nullptr;
char* dst_base_dir = nullptr;
2019-12-19 03:24:12 +00:00
// expand the destination path
if( dst0_dir != nullptr )
{
if((dst_base_dir = filesys::expandPath(dst0_dir)) == nullptr )
{
rc = cwLogError(kOpFailRC,"The backup dest directory '%s' could not be expanded.");
goto errLabel;
}
dst_dir = dst_base_dir;
}
// form the name of the backup file to backup
if((srcFn = filesys::makeFn(dir,name,ext,nullptr)) == nullptr )
2019-12-19 03:24:12 +00:00
{
rc = cwLogError(kOpFailRC,"Backup source file name formation failed.");
goto errLabel;
}
// if the src file does not exist then there is nothing to do
if( filesys::isFile(srcFn) == false )
2019-12-19 03:24:12 +00:00
return rc;
// break the source file name up into dir/fn/ext.
if((pp = filesys::pathParts(srcFn)) == nullptr || pp->fnStr==nullptr)
2019-12-19 03:24:12 +00:00
{
rc = cwLogError(kOpFailRC,"The file name '%s' could not be parsed into its parts.",cwStringNullGuard(srcFn));
goto errLabel;
}
if( dst_dir == nullptr )
dst_dir = pp->dirStr;
2019-12-19 03:24:12 +00:00
// iterate until a unique file name is found
for(n=0; 1; ++n)
{
mem::release(newFn);
2019-12-19 03:24:12 +00:00
// generate a new file name
newName = mem::printf(newName,"%s_%i",pp->fnStr,n);
2019-12-19 03:24:12 +00:00
// form the new file name into a complete path
if((newFn = filesys::makeFn(dst_dir,newName,pp->extStr,nullptr)) == nullptr )
2019-12-19 03:24:12 +00:00
{
rc = cwLogError(kOpFailRC,"A backup file name could not be formed for the file '%s'.",cwStringNullGuard(newName));
goto errLabel;
}
// if the new file name is not already in use ...
if( filesys::isFile(newFn) == false )
2019-12-19 03:24:12 +00:00
{
// .. then duplicate the file
if((rc = copy(srcFn,nullptr,nullptr,newFn,nullptr,nullptr)) != kOkRC )
2019-12-19 03:24:12 +00:00
rc = cwLogError(rc,"The file '%s' could not be duplicated as '%s'.",cwStringNullGuard(srcFn),cwStringNullGuard(newFn));
break;
}
}
errLabel:
mem::release(dst_base_dir);
mem::release(srcFn);
mem::release(newFn);
mem::release(newName);
mem::release(pp);
2019-12-19 03:24:12 +00:00
return rc;
}
cw::rc_t cw::file::backup( const char* fname, const char* dst_dir )
{
rc_t rc = kOkRC;
filesys::pathPart_t* pp = nullptr;
if((pp = filesys::pathParts(fname)) == nullptr )
{
rc = cwLogError(kInvalidArgRC,"The parts (dir,name,ext) of the file name '%s' could not be parsed.");
goto errLabel;
}
rc = backup(pp->dirStr,pp->fnStr,pp->extStr,dst_dir);
errLabel:
mem::release(pp);
return rc;
}
2019-12-19 03:24:12 +00:00
char* cw::file::toBuf( handle_t h, unsigned* bufByteCntPtr )
2019-12-19 03:24:12 +00:00
{ return _fileToBuf(h,0,bufByteCntPtr); }
char* cw::file::fnToBuf( const char* fn, unsigned* bufByteCntPtr )
2019-12-19 03:24:12 +00:00
{ return _fileFnToBuf(fn,0,bufByteCntPtr); }
char* cw::file::toStr( handle_t h, unsigned* bufByteCntPtr )
2019-12-19 03:24:12 +00:00
{ return _fileToBuf(h,1,bufByteCntPtr); }
char* cw::file::fnToStr( const char* fn, unsigned* bufByteCntPtr )
2019-12-19 03:24:12 +00:00
{ return _fileFnToBuf(fn,1,bufByteCntPtr); }
cw::rc_t cw::file::lineCount( handle_t h, unsigned* lineCntPtr )
2019-12-19 03:24:12 +00:00
{
rc_t rc = kOkRC;
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
unsigned lineCnt = 0;
long offs;
int c;
cwAssert( lineCntPtr != nullptr );
*lineCntPtr = 0;
if((rc = tell(h,&offs)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
errno = 0;
while(1)
{
c = fgetc(p->fp);
if( c == EOF )
{
if( errno )
rc = cwLogSysError(kReadFailRC,errno,"File read char failed on 's'.", cwStringNullGuard(name(h)));
2019-12-19 03:24:12 +00:00
else
++lineCnt; // add one in case the last line isn't terminated with a '\n'.
break;
}
// if an end-of-line was encountered
if( c == '\n' )
++lineCnt;
}
if((rc = seek(h,kBeginFl,offs)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
*lineCntPtr = lineCnt;
return rc;
}
cw::rc_t cw::file::getLine( handle_t h, char* buf, unsigned* bufByteCntPtr )
2019-12-19 03:24:12 +00:00
{
cwAssert( bufByteCntPtr != nullptr );
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
unsigned tn = 128;
char t[ tn ];
unsigned on = *bufByteCntPtr;
long offs;
rc_t rc;
// store the current file offset
if((rc = tell(h,&offs)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
// if no buffer was given then use t[]
if( buf == nullptr || *bufByteCntPtr == 0 )
{
*bufByteCntPtr = tn;
buf = t;
}
// fill the buffer from the current line
if((rc = _fileGetLine(p,buf,bufByteCntPtr)) != kOkRC )
return rc;
// get length of the string in the buffer
// (this is one less than the count of bytes written to the buffer)
unsigned n = strlen(buf);
// if the provided buffer was large enough to read the entire string
if( on > n+1 )
{
//*bufByteCntPtr = n+1;
return kOkRC;
}
//
// the provided buffer was not large enough
//
// m tracks the length of the string
unsigned m = n;
while( n+1 == *bufByteCntPtr )
{
// fill the buffer from the current line
if((rc = _fileGetLine(p,buf,bufByteCntPtr)) != kOkRC )
return rc;
n = strlen(buf);
m += n;
}
// restore the original file offset
if((rc = seek(h,kBeginFl,offs)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
// add 1 for /0, 1 for /n and 1 to detect buf-too-short
*bufByteCntPtr = m+3;
return kBufTooSmallRC;
}
cw::rc_t cw::file::getLineAuto( handle_t h, char** bufPtrPtr, unsigned* bufByteCntPtr )
2019-12-19 03:24:12 +00:00
{
rc_t rc = kOkRC;
bool fl = true;
char* buf = *bufPtrPtr;
*bufPtrPtr = nullptr;
while(fl)
{
fl = false;
switch( rc = getLine(h,buf,bufByteCntPtr) )
2019-12-19 03:24:12 +00:00
{
case kOkRC:
{
*bufPtrPtr = buf;
}
break;
case kBufTooSmallRC:
buf = mem::resizeZ<char>(buf,*bufByteCntPtr);
2019-12-19 03:24:12 +00:00
fl = true;
break;
default:
mem::release(buf);
2019-12-19 03:24:12 +00:00
break;
}
}
return rc;
}
cw::rc_t cw::file::readChar( handle_t h, char* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readUChar( handle_t h, unsigned char* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readShort( handle_t h, short* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readUShort( handle_t h, unsigned short* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readLong( handle_t h, long* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readULong( handle_t h, unsigned long* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readInt( handle_t h, int* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readUInt( handle_t h, unsigned int* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readFloat( handle_t h, float* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readDouble( handle_t h, double* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::readBool( handle_t h, bool* buf, unsigned cnt )
{ return read(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeChar( handle_t h, const char* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeUChar( handle_t h, const unsigned char* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeShort( handle_t h, const short* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeUShort( handle_t h, const unsigned short* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeLong( handle_t h, const long* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeULong( handle_t h, const unsigned long* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeInt( handle_t h, const int* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeUInt( handle_t h, const unsigned int* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeFloat( handle_t h, const float* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeDouble( handle_t h, const double* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeBool( handle_t h, const bool* buf, unsigned cnt )
{ return write(h,buf,sizeof(buf[0])*cnt); }
2019-12-19 03:24:12 +00:00
cw::rc_t cw::file::writeStr( handle_t h, const char* s )
2019-12-19 03:24:12 +00:00
{
rc_t rc;
unsigned n = textLength(s);
if((rc = writeUInt(h,&n,1)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
if( n > 0 )
rc = writeChar(h,s,n);
2019-12-19 03:24:12 +00:00
return rc;
}
cw::rc_t cw::file::readStr( handle_t h, char** sRef, unsigned maxCharN )
2019-12-19 03:24:12 +00:00
{
unsigned n;
rc_t rc;
cwAssert(sRef != nullptr );
*sRef = nullptr;
if( maxCharN == 0 )
maxCharN = 16384;
// read the string length
if((rc = readUInt(h,&n,1)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
// verify that string isn't too long
if( n > maxCharN )
{
return cwLogError(kInvalidArgRC,"The stored string is larger than the maximum allowable size of %i.",maxCharN);
}
// allocate a read buffer
char* s = mem::allocZ<char>(n+1);
2019-12-19 03:24:12 +00:00
// fill the buffer from the file
if((rc = readChar(h,s,n)) != kOkRC )
2019-12-19 03:24:12 +00:00
return rc;
s[n] = 0; // terminate the string
*sRef = s;
return rc;
}
cw::rc_t cw::file::print( handle_t h, const char* text )
2019-12-19 03:24:12 +00:00
{
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
errno = 0;
if( fputs(text,p->fp) < 0 )
2020-12-29 15:09:43 +00:00
return p->lastRC = cwLogSysError(kOpFailRC,errno,"File print failed on '%s'.", cwStringNullGuard(name(h)));
2019-12-19 03:24:12 +00:00
return kOkRC;
}
cw::rc_t cw::file::vPrintf( handle_t h, const char* fmt, va_list vl )
2019-12-19 03:24:12 +00:00
{
this_t* p = _handleToPtr(h);
2019-12-19 03:24:12 +00:00
if( vfprintf(p->fp,fmt,vl) < 0 )
2020-12-29 15:09:43 +00:00
return p->lastRC = cwLogSysError(kOpFailRC,errno,"File print failed on '%s'.", cwStringNullGuard(name(h)));
2019-12-19 03:24:12 +00:00
return kOkRC;
}
cw::rc_t cw::file::printf( handle_t h, const char* fmt, ... )
2019-12-19 03:24:12 +00:00
{
va_list vl;
va_start(vl,fmt);
rc_t rc = vPrintf(h,fmt,vl);
2019-12-19 03:24:12 +00:00
va_end(vl);
return rc;
}