1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231 |
- #include "cmPrefix.h"
- #include "cmGlobal.h"
- #include "cmRpt.h"
- #include "cmErr.h"
- #include "cmCtx.h"
- #include "cmMem.h"
- #include "cmMallocDebug.h"
- #include "cmLex.h"
- #include "cmLinkedHeap.h"
- #include "cmHashTbl.h"
- #include "cmCsv.h"
- #include "cmText.h"
-
- enum
- {
- kCommaLexTId = kUserLexTId+1,
-
- kMaxLexTId // always last in the lex id list
- };
-
- typedef struct
- {
- const char* text;
- unsigned id;
- } cmCsvToken_t;
-
-
- cmCsvToken_t _cmCsvTokenArray[] =
- {
- { ",", kCommaLexTId },
- { "", kErrorLexTId }
- };
-
- // The binder linked list contains a list of records which tracks the first
- // (left-most) non-blank column in each row.
- typedef struct cmCsvBind_str
- {
- struct cmCsvBind_str* linkPtr;
- cmCsvCell_t* rowPtr;
- } cmCsvBind_t;
-
- typedef struct cmCsvUdef_str
- {
- struct cmCsvUdef_str* linkPtr;
- unsigned id;
- } cmCsvUdef_t;
-
- typedef struct
- {
- cmErr_t err;
- void* rptDataPtr; //
- cmLexH lexH; // parsing lexer
- cmHashTblH_t htH; // hash table handle
- cmLHeapH_t heapH;
- cmCsvBind_t* bindPtr; // base of the binder linked list
- cmCsvCell_t* curRowPtr; // used by the parser to track the row being filled
- cmCsvUdef_t* udefList;
- } cmCsv_t;
-
- cmCsvH_t cmCsvNullHandle = { NULL };
-
- cmCsv_t* _cmCsvHandleToPtr( cmCsvH_t h )
- {
- cmCsv_t* p = (cmCsv_t*)h.h;
- assert( p != NULL );
- cmErrClearRC(&p->err);
- return p;
- }
-
- cmCsvRC_t _cmCsvVError( cmCsv_t* p, cmCsvRC_t rc, const char* fmt, va_list vl )
- { return cmErrVMsg(&p->err,rc,fmt,vl); }
-
- cmCsvRC_t _cmCsvError( cmCsv_t* p, cmCsvRC_t rc, const char* fmt, ... )
- {
- va_list vl;
- va_start(vl,fmt);
- rc = _cmCsvVError(p,rc,fmt,vl);
- va_end(vl);
- return rc;
- }
-
-
- cmCsvRC_t cmCsvInitialize( cmCsvH_t *hp, cmCtx_t* ctx )
- {
- cmCsvRC_t rc;
- cmCsv_t* p = NULL;
- unsigned i;
-
- if((rc = cmCsvFinalize(hp)) != kOkCsvRC )
- return rc;
-
- // create the base object
- p = cmMemAllocZ( cmCsv_t, 1 );
- assert(p != NULL);
-
- cmErrSetup(&p->err,&ctx->rpt,"CSV");
-
- // create the hash table
- if( cmHashTblCreate(ctx,&p->htH,8192) != kOkHtRC )
- {
- rc = _cmCsvError(p,kHashTblErrCsvRC,"Hash table creation failed.");
- goto errLabel;
- }
-
- // allocate the linked heap mgr
- if( cmLHeapIsValid(p->heapH = cmLHeapCreate(8192,ctx)) == false )
- {
- rc = _cmCsvError(p,kMemAllocErrCsvRC,"Linked heap object allocation failed.");
- goto errLabel;
- }
-
- // allocate the lexer
- if(cmLexIsValid(p->lexH = cmLexInit(NULL,0,0,&ctx->rpt)) == false )
- {
- rc = _cmCsvError(p,kLexErrCsvRC,"Lex allocation failed.");
- goto errLabel;
- }
-
- // register CSV specific tokens with the lexer
- for(i=0; _cmCsvTokenArray[i].id != kErrorLexTId; ++i)
- {
- cmRC_t lexRC;
- if( (lexRC = cmLexRegisterToken(p->lexH, _cmCsvTokenArray[i].id, _cmCsvTokenArray[i].text )) != kOkLexRC )
- {
- rc = _cmCsvError(p,kLexErrCsvRC,"Lex token registration failed for:'%s'.\nLexer Error:%s",_cmCsvTokenArray[i].text, cmLexRcToMsg(lexRC) );
- goto errLabel;
- }
- }
-
- hp->h = p;
-
- return kOkCsvRC;
-
- errLabel:
-
- cmMemPtrFree(&p);
-
- if( cmLHeapIsValid(p->heapH) )
- cmLHeapDestroy(&p->heapH);
-
- if( cmLexIsValid(p->lexH) )
- cmLexFinal(&p->lexH);
-
- return rc;
-
- }
- cmCsvRC_t cmCsvFinalize( cmCsvH_t *hp )
- {
-
- cmRC_t lexRC;
-
- if( hp == NULL || hp->h == NULL )
- return kOkCsvRC;
-
- cmCsv_t* p = _cmCsvHandleToPtr(*hp);
-
- // free the internal heap object
- cmLHeapDestroy( &p->heapH );
-
- // free the lexer
- if((lexRC = cmLexFinal(&p->lexH)) != kOkLexRC )
- return _cmCsvError(p,kLexErrCsvRC,"Lexer finalization failed.\nLexer Error:%s",cmLexRcToMsg(lexRC));
-
- // free the hash table
- cmHashTblDestroy(&p->htH);
-
- // free the handle
- cmMemPtrFree(&hp->h);
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvInitializeFromFile( cmCsvH_t *hp, const char* fn, unsigned maxRowCnt, cmCtx_t* ctx )
- {
- cmCsvRC_t rc;
-
- if((rc = cmCsvInitialize(hp,ctx)) != kOkCsvRC )
- return rc;
-
- return cmCsvParseFile( *hp, fn, maxRowCnt);
- }
-
-
- bool cmCsvIsValid( cmCsvH_t h)
- { return h.h != NULL; }
-
- cmCsvRC_t cmCsvLastRC( cmCsvH_t h )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- return cmErrLastRC(&p->err);
- }
-
- void cmCsvClearRC( cmCsvH_t h )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- cmErrClearRC(&p->err);
- }
-
-
- cmCsvRC_t cmCsvParseFile( cmCsvH_t h, const char* fn, unsigned maxRowCnt )
- {
- cmCsvRC_t rc = kOkCsvRC;
- FILE* fp = NULL;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- unsigned n = 0;
- char* textBuf = NULL;
-
- assert( fn != NULL && p != NULL );
-
- // open the file
- if((fp = fopen(fn,"rb")) == NULL )
- return _cmCsvError(p,kFileOpenErrCsvRC,"Unable to open the file:'%s'.",fn);
-
- // seek to the end
- if( fseek(fp,0,SEEK_END) != 0 )
- {
- rc= _cmCsvError(p,kFileSeekErrCsvRC,"Unable to seek to the end of '%s'.",fn);
- goto errLabel;
- }
-
- // get the length of the file
- if( (n=ftell(fp)) == 0 )
- {
- rc = _cmCsvError(p,kFileOpenErrCsvRC,"The file '%s' appears to be empty.",fn);
- goto errLabel;
- }
-
- // rewind the file
- if( fseek(fp,0,SEEK_SET) != 0 )
- {
- rc = _cmCsvError(p,kFileSeekErrCsvRC,"Unable to seek to the beginning of '%s'.",fn);
- goto errLabel;
- }
-
- // allocate the text buffer
- if((textBuf = cmMemAllocZ( char, n+1)) == NULL )
- {
- rc = _cmCsvError(p,kMemAllocErrCsvRC,"Unable to allocate the text file buffer for:'%s'.",fn);
- goto errLabel;
- }
-
- // read the file into the text buffer
- if( fread(textBuf,n,1,fp) != 1 )
- {
- rc = _cmCsvError(p,kFileReadErrCsvRC,"File read failed on:'%s'.",fn);
- goto errLabel;
- }
-
- rc = cmCsvParse(h,textBuf,n,maxRowCnt);
-
- errLabel:
-
- // close the file
- if( fclose(fp) != 0 )
- {
- rc = _cmCsvError(p,kFileCloseErrCsvRC,"File close failed on:'%s'.",fn);
- goto errLabel;
- }
-
- // free the buffer
- if( textBuf != NULL )
- cmMemFree(textBuf);
-
- return rc;
-
- }
-
- cmCsvRC_t _cmCsvAppendNewBindRecd( cmCsv_t* p, cmCsvBind_t** newBindPtrPtr, unsigned* newRowIdxPtr )
- {
- cmCsvBind_t* nbp;
- cmCsvBind_t* bp = p->bindPtr;
- unsigned newRowIdx = 0;
-
- if( newBindPtrPtr != NULL )
- *newBindPtrPtr = NULL;
-
- if( newRowIdxPtr != NULL )
- *newRowIdxPtr = cmInvalidIdx;
-
- // allocate the binder record
- if((nbp = cmLHeapAllocZ( p->heapH, sizeof(cmCsvBind_t))) == NULL )
- return _cmCsvError(p,kMemAllocErrCsvRC,"Binding record allocation failed.");
-
- // if this is the first binder record
- if( p->bindPtr == NULL )
- {
- p->bindPtr = nbp;
- bp = nbp;
- }
- else
- {
- newRowIdx = 1;
-
- // iterate to the bottom of the binding
- while( bp->linkPtr != NULL )
- {
- bp = bp->linkPtr;
-
- ++newRowIdx;
- }
-
- bp->linkPtr = nbp;
- }
-
- if( newBindPtrPtr != NULL )
- *newBindPtrPtr = nbp;
-
- if( newRowIdxPtr != NULL )
- *newRowIdxPtr = newRowIdx;
-
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t _cmCsvCreateBind( cmCsv_t* p, cmCsvCell_t* cp, const char* tokenText, unsigned lexRow, unsigned lexCol )
- {
- cmCsvRC_t rc;
- cmCsvBind_t* nbp;
- if((rc = _cmCsvAppendNewBindRecd(p,&nbp,NULL)) != kOkCsvRC )
- return _cmCsvError(p,kMemAllocErrCsvRC,"Binding record allocation failed for '%s' on line %i column %i.",tokenText,lexRow,lexCol);
-
- nbp->rowPtr = cp;
-
- return rc;
- }
-
- cmCsvRC_t _cmCsvAllocCell( cmCsv_t* p, unsigned symId, unsigned flags, unsigned cellRow, unsigned cellCol, cmCsvCell_t** cpp, unsigned lexTId )
- {
- cmCsvCell_t* cp;
-
- // allocate cell memory
- if(( cp = cmLHeapAllocZ(p->heapH, sizeof(cmCsvCell_t) )) == NULL )
- return _cmCsvError(p,kMemAllocErrCsvRC,"Cell allocation failed. for row: %i column %i.",cellRow+1,cellCol+1);
-
- cp->row = cellRow;
- cp->col = cellCol;
- cp->symId = symId;
- cp->flags = flags;
- cp->lexTId= lexTId;
-
- *cpp = cp;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t _cmCsvCreateCell( cmCsv_t* p, const char* tokenText, unsigned flags, unsigned cellRow, unsigned cellCol, unsigned lexTId )
- {
- unsigned symId = cmInvalidId;
- cmCsvCell_t* cp = NULL;
- unsigned lexRow = cmLexCurrentLineNumber(p->lexH);
- unsigned lexCol = cmLexCurrentColumnNumber(p->lexH);
- cmCsvRC_t rc = kOkCsvRC;
-
- // register the token text as a symbol
- if((symId = cmHashTblStoreStr(p->htH,tokenText)) == cmInvalidId )
- return _cmCsvError(p,kHashTblErrCsvRC,"Symbol registration failed. for '%s' on line %i column %i.",tokenText,lexRow,lexCol);
-
- // allocate a cell
- if((rc = _cmCsvAllocCell(p,symId,flags,cellRow,cellCol,&cp,lexTId)) != kOkCsvRC )
- return rc;
-
- // if this is the first cell in the row
- if( p->curRowPtr == NULL )
- {
- // link in a new binding record
- if((rc = _cmCsvCreateBind( p, cp,tokenText,lexRow,lexCol)) != kOkCsvRC )
- return rc; // this return will result in a leak from the lheap but it is a fatal error so ignore it
-
- // update the current row ptr
- p->curRowPtr = cp;
- }
- else
- {
- // iterate to the end of the row
- cmCsvCell_t* rp = p->curRowPtr;
- while( rp->rowPtr != NULL )
- rp = rp->rowPtr;
-
- rp->rowPtr = cp;
- }
-
- return rc;
-
- }
-
- const cmCsvUdef_t* _cmCsvFindUdef( cmCsv_t* p, unsigned id )
- {
- const cmCsvUdef_t* u = p->udefList;
- while( u != NULL )
- {
- if( u->id == id )
- return u;
-
- u = u->linkPtr;
- }
-
- return NULL;
- }
-
- cmCsvRC_t _cmCsvRegUdef( cmCsv_t* p, unsigned id )
- {
- if( _cmCsvFindUdef(p,id) != NULL )
- return _cmCsvError(p,kDuplicateLexCsvId,"%i has already been used as a user defined id.",id);
-
- cmCsvUdef_t* u = cmLhAllocZ(p->heapH,cmCsvUdef_t,1);
- u->id = id;
- u->linkPtr = p->udefList;
- p->udefList = u;
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvLexRegisterToken( cmCsvH_t h, unsigned id, const cmChar_t* token )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- if(cmLexRegisterToken(p->lexH,id,token) != kOkLexRC )
- return _cmCsvError(p, kLexErrCsvRC,"Error registering user defined token '%s'.",cmStringNullGuard(token));
-
- return _cmCsvRegUdef(p,id);
- }
-
- cmCsvRC_t cmCsvLexRegisterMatcher( cmCsvH_t h, unsigned id, cmLexUserMatcherPtr_t matchFunc )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- if( cmLexRegisterMatcher(p->lexH,id,matchFunc) != kOkLexRC )
- return _cmCsvError(p, kLexErrCsvRC,"Error registering user defined matching function.");
-
- return _cmCsvRegUdef(p,id);
- }
-
- unsigned cmCsvLexNextAvailId( cmCsvH_t h )
- { return kMaxLexTId; }
-
- cmCsvRC_t cmCsvParse( cmCsvH_t h, const char* buf, unsigned bufCharCnt, unsigned maxRowCnt )
- {
- cmCsvRC_t rc = kOkCsvRC;
- unsigned prvLexRow = 1;
- unsigned csvRowIdx = 0;
- unsigned csvColIdx = 0;
- unsigned lexTId = kErrorLexTId; // cur lex token type id
- cmCsv_t* p = _cmCsvHandleToPtr(h);
-
- // assign the text buffer and reset the lexer
- if((rc = cmLexSetTextBuffer( p->lexH, buf, bufCharCnt )) != kOkLexRC )
- return _cmCsvError( p, kLexErrCsvRC, "Error setting lexer buffer.\nLexer Error:%s",cmLexRcToMsg(rc));
-
- // get the next token
- while( (lexTId = cmLexGetNextToken( p->lexH )) != kErrorLexTId && (lexTId != kEofLexTId ) && (rc==kOkCsvRC) && (maxRowCnt==0 || csvRowIdx<maxRowCnt))
- {
- unsigned flags = 0;
- unsigned curLexRow = cmLexCurrentLineNumber(p->lexH);
-
- // if we are starting a new row
- if( curLexRow != prvLexRow )
- {
- prvLexRow = curLexRow;
- ++csvRowIdx;
- csvColIdx = 0;
- p->curRowPtr = NULL; // force a new binding record
- }
-
-
- // copy the token text in a buffer
- unsigned n = cmLexTokenCharCount(p->lexH);
- char buf[n+1];
- strncpy(buf, cmLexTokenText(p->lexH), n );
- buf[n]=0;
-
- // do cell data type specific processing
- switch( lexTId )
- {
- case kCommaLexTId:
- ++csvColIdx;
- break;
-
- case kRealLexTId: flags = kRealCsvTFl; break;
- case kIntLexTId: flags = kIntCsvTFl; break;
- case kHexLexTId: flags = kHexCsvTFl; break;
- case kIdentLexTId:flags = kIdentCsvTFl; break;
- case kQStrLexTId: flags = kStrCsvTFl; break;
-
- default:
- {
- const cmCsvUdef_t* u;
- if((u = _cmCsvFindUdef(p,lexTId)) == NULL )
- rc = _cmCsvError(p, kSyntaxErrCsvRC, "Unrecognized token type: '%s' for token: '%s' row:%i col:%i.",cmLexIdToLabel(p->lexH,lexTId),buf,csvRowIdx+1,csvColIdx+1);
- else
- flags = kStrCsvTFl | kUdefCsvTFl;
- }
- }
-
- // if no error occurred and the token is not a comma and the cell is not empty
- if( rc == kOkCsvRC && lexTId != kCommaLexTId && strlen(buf) > 0 )
- if((rc = _cmCsvCreateCell( p, buf,flags, csvRowIdx, csvColIdx, lexTId )) != kOkCsvRC )
- rc = _cmCsvError(p,rc,"CSV cell create fail on row:%i col:%i\n",csvRowIdx+1,csvColIdx+1);
- }
-
- if( lexTId == kErrorLexTId )
- rc = _cmCsvError(p, kSyntaxErrCsvRC,"The lexer encountered an unrecognized token row:%i col:%i.",csvRowIdx+1,csvColIdx+1);
-
- return rc;
- }
-
- unsigned cmCsvRowCount( cmCsvH_t h )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
-
- unsigned rowCnt = 0;
- cmCsvBind_t* bp = p->bindPtr;
-
- for(; bp != NULL; ++rowCnt )
- bp = bp->linkPtr;
-
- return rowCnt;
- }
-
- cmCsvCell_t* cmCsvRowPtr( cmCsvH_t h, unsigned row )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- cmCsvBind_t* bp = p->bindPtr;
-
- while( bp != NULL )
- {
- // note: bp->rowPtr of blank rows will be NULL
- if( bp->rowPtr!=NULL && bp->rowPtr->row == row )
- return bp->rowPtr;
-
- bp = bp->linkPtr;
- }
-
- return NULL;
- }
-
- cmCsvCell_t* cmCsvCellPtr( cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
-
- if((cp = cmCsvRowPtr(h,row)) == NULL )
- return NULL;
-
- while( cp != NULL )
- {
- if( cp->col == col )
- return cp;
-
- cp = cp->rowPtr;
- }
-
- return NULL;
- }
-
- cmCsvCell_t* _cmCsvCellPtr( cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
- if((cp = cmCsvCellPtr(h,row,col)) == NULL )
- _cmCsvError(_cmCsvHandleToPtr(h),kCellNotFoundCsvRC,"Cell at row:%i col:%i not found.",row,col);
- return cp;
- }
-
- const char* cmCsvCellSymText( cmCsvH_t h, unsigned symId )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- const char* cp;
-
- if((cp = cmHashTblStr(p->htH,symId)) == NULL )
- _cmCsvError(p,kHashTblErrCsvRC,"The text associated with the symbol '%i' was not found.",symId);
-
- return cp;
- }
-
- cmCsvRC_t cmCsvCellSymInt( cmCsvH_t h, unsigned symId, int* vp )
- {
- const char* cp;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
-
- if((cp = cmCsvCellSymText(h,symId)) == NULL )
- return kHashTblErrCsvRC;
-
- if( cmTextToInt(cp,vp,&p->err) != kOkTxRC )
- return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to int value failed.");
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvCellSymUInt( cmCsvH_t h, unsigned symId, unsigned* vp )
- {
- const char* cp;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
-
- if((cp = cmCsvCellSymText(h,symId)) == NULL )
- return kHashTblErrCsvRC;
-
- if( cmTextToUInt(cp,vp,&p->err) != kOkTxRC )
- return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to uint value failed.");
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvCellSymFloat( cmCsvH_t h, unsigned symId, float* vp )
- {
- const char* cp;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
-
- if((cp = cmCsvCellSymText(h,symId)) == NULL )
- return kHashTblErrCsvRC;
-
- if( cmTextToFloat(cp,vp,&p->err) != kOkTxRC )
- return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to float value failed.");
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvCellSymDouble( cmCsvH_t h, unsigned symId, double* vp )
- {
- const char* cp;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
-
- if((cp = cmCsvCellSymText(h,symId)) == NULL )
- return kHashTblErrCsvRC;
-
- if( cmTextToDouble(cp,vp,&p->err) != kOkTxRC )
- return _cmCsvError(p,kDataCvtErrCsvRC,"CSV text to double value failed.");
-
- return kOkCsvRC;
- }
-
- const char* cmCsvCellText( cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
- if((cp = cmCsvCellPtr(h,row,col)) == NULL )
- return NULL;
-
- return cmCsvCellSymText(h,cp->symId);
- }
-
- int cmCsvCellInt( cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
- int v;
-
- if((cp = cmCsvCellPtr(h,row,col)) == NULL )
- return INT_MAX;
-
- if(cmCsvCellSymInt(h,cp->symId,&v) != kOkCsvRC )
- return INT_MAX;
-
- return v;
- }
-
- unsigned cmCsvCellUInt( cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
- unsigned v;
-
- if((cp = cmCsvCellPtr(h,row,col)) == NULL )
- return UINT_MAX;
-
- if(cmCsvCellSymUInt(h,cp->symId,&v) != kOkCsvRC )
- return UINT_MAX;
-
- return v;
- }
-
- float cmCsvCellFloat( cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
- float v;
-
- if((cp = cmCsvCellPtr(h,row,col)) == NULL )
- return FLT_MAX;
-
- if(cmCsvCellSymFloat(h,cp->symId,&v) != kOkCsvRC )
- return FLT_MAX;
-
- return v;
- }
-
- double cmCsvCellDouble(cmCsvH_t h, unsigned row, unsigned col )
- {
- cmCsvCell_t* cp;
- double v;
-
- if((cp = cmCsvCellPtr(h,row,col)) == NULL )
- return DBL_MAX;
-
- if(cmCsvCellSymDouble(h,cp->symId,&v) != kOkCsvRC )
- return DBL_MAX;
-
- return v;
- }
-
-
-
- unsigned cmCsvInsertSymText( cmCsvH_t h, const char* text )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- unsigned symId;
-
- if((symId = cmHashTblStoreStr(p->htH,text)) == cmInvalidId )
- _cmCsvError(p,kHashTblErrCsvRC,"'%s' could not be inserted into the symbol table.",text);
-
- return symId;
- }
-
- unsigned cmCsvInsertSymInt( cmCsvH_t h, int v )
- {
- const char* fmt = "%i";
- unsigned n = snprintf(NULL,0,fmt,v)+1;
- char buf[n];
-
- buf[0]= 0;
- if( snprintf(buf,n,fmt,v) == n-1 )
- return cmCsvInsertSymText(h,buf);
-
- _cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The integer %i could not be converted to text.",v);
- return cmInvalidId;
- }
-
- unsigned cmCsvInsertSymUInt( cmCsvH_t h, unsigned v )
- {
- const char* fmt = "%i";
- unsigned n = snprintf(NULL,0,fmt,v)+1;
- char buf[n];
-
- buf[0]= 0;
- if( snprintf(buf,n,fmt,v) == n-1 )
- return cmCsvInsertSymText(h,buf);
-
- _cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The unsigned int %i could not be converted to text.",v);
- return cmInvalidId;
- }
-
- unsigned cmCsvInsertSymHex( cmCsvH_t h, unsigned v )
- {
- const char* fmt = "0x%x";
- unsigned n = snprintf(NULL,0,fmt,v)+1;
- char buf[n];
-
- buf[0]= 0;
- if( snprintf(buf,n,fmt,v) == n-1 )
- return cmCsvInsertSymText(h,buf);
-
- _cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The unsigned int 0x%x could not be converted to text.",v);
- return cmInvalidId;
- }
-
- unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v )
- {
- const char* fmt = "%f";
- unsigned n = snprintf(NULL,0,fmt,v)+1;
- char buf[n];
-
- buf[0] = 0;
- if( snprintf(buf,n,fmt,v) == n-1 )
- return cmCsvInsertSymText(h,buf);
-
- _cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The float %f could not be converted to text.",v);
- return cmInvalidId;
- }
-
- unsigned cmCsvInsertSymDouble( cmCsvH_t h, double v )
- {
- const char* fmt = "%f";
- unsigned n = snprintf(NULL,0,fmt,v)+1;
- char buf[n];
-
- buf[0]= 0;
- if( snprintf(buf,n,fmt,v) == n-1 )
- return cmCsvInsertSymText(h,buf);
-
- _cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The double %f could not be converted to text.",v);
- return cmInvalidId;
-
- }
-
- cmCsvRC_t cmCsvSetCellIdent( cmCsvH_t h, unsigned row, unsigned col, const char* text )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymText(h,text)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kIdentCsvTFl;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvSetCellText( cmCsvH_t h, unsigned row, unsigned col, const char* text )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymText(h,text)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kStrCsvTFl;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvSetCellInt( cmCsvH_t h, unsigned row, unsigned col, int v )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymInt(h,v)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kIntCsvTFl;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvSetCellUInt( cmCsvH_t h, unsigned row, unsigned col, unsigned v )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymUInt(h,v)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kIntCsvTFl;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvSetCellHex( cmCsvH_t h, unsigned row, unsigned col, unsigned v )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymHex(h,v)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kIntCsvTFl;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymFloat(h,v)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kRealCsvTFl;
-
- return kOkCsvRC;
- }
-
- cmCsvRC_t cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v )
- {
- cmCsvCell_t* cp;
- unsigned symId;
-
- if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- if((symId = cmCsvInsertSymDouble(h,v)) == cmInvalidId )
- return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
-
- cp->symId = symId;
- cp->flags &= !kTypeTMask;
- cp->flags |= kRealCsvTFl;
-
- return kOkCsvRC;
- }
-
-
- cmCsvRC_t cmCsvInsertRowBefore( cmCsvH_t h, unsigned row, cmCsvCell_t** cellPtrPtr, unsigned symId, unsigned flags, unsigned lexTId )
- {
- cmCsvRC_t rc = kOkCsvRC;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- cmCsvBind_t* bp = p->bindPtr;
- cmCsvBind_t* nbp = NULL;
- unsigned i = 0;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- // allocate the binder record
- if((nbp = cmLHeapAllocZ( p->heapH, sizeof(cmCsvBind_t))) == NULL )
- return _cmCsvError(p,kMemAllocErrCsvRC,"Binding record allocation failed row %i column %i.",row,0);
-
- // if a new first row is being inserted
- if( row == 0 )
- {
- bp = p->bindPtr;
- nbp->linkPtr = p->bindPtr;
- p->bindPtr = nbp;
- }
- else
- {
- bp = p->bindPtr;
-
- // iterate to the row before the new row
- for(i=0; bp != NULL; ++i )
- {
- if( i == (row-1) || bp->linkPtr == NULL )
- break;
-
- bp = bp->linkPtr;
- }
-
- assert( bp != NULL );
-
- nbp->linkPtr = bp->linkPtr;
- bp->linkPtr = nbp;
- bp = bp->linkPtr;
- }
-
- // update the row numbers in all cells below the new row
- while( bp != NULL )
- {
- cmCsvCell_t* cp = bp->rowPtr;
- while( cp != NULL )
- {
- cp->row += 1;
- cp = cp->rowPtr;
- }
- bp = bp->linkPtr;
- }
-
- // allocate the first cell in the new row
- if(cellPtrPtr != NULL && symId != cmInvalidId )
- {
- if((rc = _cmCsvAllocCell(p, symId, flags, row, 0, cellPtrPtr, lexTId )) != kOkCsvRC )
- return rc;
-
- nbp->rowPtr = *cellPtrPtr;
- }
- return rc;
- }
-
- cmCsvRC_t cmCsvAppendRow( cmCsvH_t h, cmCsvCell_t** cellPtrPtr, unsigned symId, unsigned flags, unsigned lexTId )
- {
- cmCsvRC_t rc = kOkCsvRC;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- cmCsvBind_t* nbp = NULL;
- unsigned newRowIdx = cmInvalidIdx;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = _cmCsvAppendNewBindRecd(p,&nbp,&newRowIdx)) != kOkCsvRC )
- return rc;
-
-
- // allocate the first cell in the new row
- if(cellPtrPtr != NULL && symId != cmInvalidId )
- {
- if((rc = _cmCsvAllocCell(p, symId, flags, newRowIdx, 0, cellPtrPtr, lexTId )) != kOkCsvRC )
- return rc;
-
- nbp->rowPtr = *cellPtrPtr;
- }
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned symId, unsigned flags, unsigned lexTId )
- {
- cmCsvRC_t rc = kOkCsvRC;
- cmCsvCell_t* ncp = NULL;
- cmCsvCell_t* cp = NULL;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- unsigned col;
-
- if(cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- // allocate the new cell
- if((rc = _cmCsvAllocCell(p, symId, flags, leftCellPtr->row, leftCellPtr->col+1, &ncp, lexTId )) != kOkCsvRC )
- return rc;
-
- // update the col values of cells to right of new cell
- cp = leftCellPtr->rowPtr;
- col = leftCellPtr->col + 1;
-
- for(; cp != NULL; ++col )
- {
- // don't update any col numbers after a blank (missing) column
- if( cp->col == col )
- cp->col += 1;
-
- cp = cp->rowPtr;
- }
-
- // link in the new cell
- ncp->rowPtr = leftCellPtr->rowPtr;
- leftCellPtr->rowPtr = ncp;
-
- if(cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
-
- }
-
- cmCsvRC_t cmCsvInsertIdentColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* text, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellIdent(h, ncp->row, ncp->col, text )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertQTextColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* text, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertHexColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellHex(h, ncp->row, ncp->col, val )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
- cmCsvRC_t cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, double val, unsigned lexTId )
- {
- cmCsvRC_t rc;
- cmCsvCell_t* ncp;
-
- if( cellPtrPtr != NULL )
- *cellPtrPtr = NULL;
-
- if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
- if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC )
- if( cellPtrPtr != NULL )
- *cellPtrPtr = ncp;
-
- return rc;
- }
-
-
- cmCsvRC_t cmCsvWrite( cmCsvH_t h, const char* fn )
- {
- FILE* fp = NULL;
- cmCsvRC_t rc = kOkCsvRC;
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- cmCsvBind_t* bp = p->bindPtr;
-
- if((fp = fopen(fn,"wt")) == NULL )
- return _cmCsvError(p,kFileCreateErrCsvRC,"Unable to create the output CSV file:'%s'.",fn);
-
- bp = p->bindPtr;
-
- // for each row
- while( bp != NULL )
- {
- cmCsvCell_t* cp = bp->rowPtr;
- unsigned col = 0;
-
- // for each column
- for(; cp != NULL; ++col )
- {
- // skip blank columns
- if( cp->col == col )
- {
- const char* tp;
-
- if((tp = cmHashTblStr(p->htH,cp->symId)) == NULL )
- return _cmCsvError(p,kHashTblErrCsvRC,"Unable to locate the symbol text for cell at row:%i col:%i.",cp->row,cp->col);
-
- if( cmIsFlag(cp->flags,kStrCsvTFl) )
- fprintf(fp,"\"");
-
- fputs(tp,fp);
-
- if( cmIsFlag(cp->flags,kStrCsvTFl) )
- fprintf(fp,"\"");
-
- cp = cp->rowPtr;
- }
-
- if( cp == NULL )
- fprintf(fp,"\n"); // end of row
- else
- fprintf(fp,","); // between columns
- }
-
- bp = bp->linkPtr;
- }
-
- fclose(fp);
-
- return rc;
- }
-
- cmCsvRC_t cmCsvPrint( cmCsvH_t h, unsigned rowCnt )
- {
- cmCsv_t* p = _cmCsvHandleToPtr(h);
- cmCsvBind_t* bp = p->bindPtr;
- unsigned i;
-
- for(i=0; bp!=NULL && i<rowCnt; ++i,bp=bp->linkPtr)
- {
- cmCsvCell_t* cp = bp->rowPtr;
- unsigned j;
-
- for(j=0; cp!=NULL; ++j)
- {
- if( cp->col == j )
- {
- const char* tp;
-
- if((tp = cmHashTblStr(p->htH,cp->symId)) == NULL )
- _cmCsvError(p,kHashTblErrCsvRC,"The text associated with the symbol '%i' was not found.",cp->symId);
-
- fputs(tp,stdin);
- }
-
- cp=cp->rowPtr;
- if( cp == NULL )
- printf("\n");
- else
- printf(",");
-
- }
- }
- return kOkCsvRC;
- }
|