Skip to content

Commit b3c5cc7

Browse files
committed
more GTF/GFF parsing fixes and workarounds
1 parent 99b19bc commit b3c5cc7

9 files changed

Lines changed: 442 additions & 367 deletions

File tree

gclib/GBase.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ int Gstricmp(const char* a, const char* b, int n) {
317317
}
318318

319319
int strsplit(char* str, char** fields, int maxfields, const char* delim) {
320-
//splits by placing 0 where delim chars are found, setting fields[] to the beginning
320+
//splits by placing 0 where any of the delim chars are found, setting fields[] to the beginning
321321
//of each field (stopping after maxfields); returns number of fields parsed
322322
int tidx=0;
323323
bool afterdelim=true;
@@ -452,15 +452,10 @@ char* rstrchr(char* str, char ch) { /* returns a pointer to the rightmost
452452
*/
453453
char* fgetline(char* & buf, int& buf_cap, FILE *stream, off_t* f_pos, int* linelen) {
454454
//reads a char at a time until \n and/or \r are encountered
455-
//int i=0;
456455
int c=0;
457456
GDynArray<char> arr(buf, buf_cap);
458457
off_t fpos=(f_pos!=NULL) ? *f_pos : 0;
459458
while ((c=getc(stream))!=EOF) {
460-
//if (i>=buf_cap-1) {
461-
// buf_cap+=1024;
462-
// GREALLOC(buf, buf_cap);
463-
// }
464459
if (c=='\n' || c=='\r') {
465460
if (c=='\r') {
466461
if ((c=getc(stream))!='\n') ungetc(c,stream);
@@ -470,16 +465,13 @@ char* fgetline(char* & buf, int& buf_cap, FILE *stream, off_t* f_pos, int* linel
470465
break;
471466
}
472467
fpos++;
473-
//buf[i]=(char)c;
474468
arr.Push((char)c);
475-
//i++;
476469
} //while i<buf_cap-1
477470
//if (linelen!=NULL) *linelen=i;
478471
if (linelen!=NULL) *linelen=arr.Count();
479472
if (f_pos!=NULL) *f_pos=fpos;
480473
//if (c==EOF && i==0) return NULL;
481474
if (c==EOF && arr.Count()==0) return NULL;
482-
//buf[i]='\0';
483475
arr.Push('\0');
484476
buf=arr();
485477
buf_cap=arr.Capacity();
@@ -491,7 +483,7 @@ char* GLineReader::getLine(FILE* stream, off_t& f_pos) {
491483
//reads a char at a time until \n and/or \r are encountered
492484
int c=0;
493485
textlen=0;
494-
buf.reset(); //len = 0
486+
buf.Reset(); //len = 0
495487
while ((c=getc(stream))!=EOF) {
496488
if (c=='\n' || c=='\r') {
497489
textlen=buf.Count();

gclib/GBase.h

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -360,20 +360,25 @@ class GSeg {
360360

361361
//basic dynamic array template for primitive types
362362
//which can only grow (reallocate) as needed
363-
#define GDynArray_INDEX_ERR "Error: invalid index (%d) in dynamic array!\n"
363+
364+
//optimize index test
365+
#define GDynArray_INDEX_ERR "Error: use of index (%d) in GDynArray of size %d!\n"
364366
#if defined(NDEBUG) || defined(NODEBUG) || defined(_NDEBUG) || defined(NO_DEBUG)
365367
#define GDynArray_TEST_INDEX(x)
366368
#else
367369
#define GDynArray_TEST_INDEX(x) \
368-
if (x>=fCount) GError(GDynArray_INDEX_ERR, x)
370+
if (fCount==0 || x>=fCount) GError(GDynArray_INDEX_ERR, x, fCount)
369371
#endif
370372

371373
#define GDynArray_MAXCOUNT UINT_MAX-1
372374
#define GDynArray_NOIDX UINT_MAX
373375

376+
//basic dynamic array (vector) template for simple/primitive types or structs
377+
//Warning: uses malloc so it will never call the item's default constructor when growing
378+
374379
template<class OBJ> class GDynArray {
375380
protected:
376-
bool byptr;
381+
bool byptr; //in-place copy (pointer) takeover of existing OBJ[]
377382
OBJ *fArray;
378383
uint fCount;
379384
uint fCapacity; // size of allocated memory
@@ -401,12 +406,12 @@ template<class OBJ> class GDynArray {
401406
Clear();
402407
return *this;
403408
}
404-
setCapacity(a.fCapacity); //set size
409+
increaseCapacity(a.fCapacity); //set size
405410
memcpy(fArray, a.fArray, sizeof(OBJ)*a.fCount);
406411
return *this;
407412
}
408413

409-
OBJ& operator [] (uint idx) {// get array item
414+
OBJ& operator[] (uint idx) {// get array item
410415
GDynArray_TEST_INDEX(idx);
411416
return fArray[idx];
412417
}
@@ -416,53 +421,78 @@ template<class OBJ> class GDynArray {
416421
if (GDynArray_MAXCOUNT-delta<=fCapacity)
417422
delta=GDynArray_MAXCOUNT-fCapacity;
418423
if (delta<=1) GError("Error at GDynArray::Grow(): max capacity reached!\n");
419-
setCapacity(fCapacity + delta);
424+
increaseCapacity(fCapacity + delta);
420425
}
421-
#define GDYNARRAY_ADD(item) \
426+
#define GDynArray_ADD(item) \
422427
if (fCount==MAX_UINT-1) GError("Error at GDynArray: cannot add item, maximum count reached!\n"); \
423428
if ((++fCount) > fCapacity) Grow(); \
424429
fArray[fCount-1] = item;
425430

426-
uint Add(OBJ* item) { // Add item to the end of array by pointer
431+
uint Add(OBJ* item) { // Add item to the end of array
432+
//element given by pointer
427433
if (item==NULL) return GDynArray_NOIDX;
428-
GDYNARRAY_ADD( (*item) );
434+
GDynArray_ADD( (*item) );
429435
return (fCount-1);
430436
}
431437

432-
uint Add(OBJ item) { // Add item copy to the end of array
433-
GDYNARRAY_ADD(item);
438+
uint Add(OBJ item) { // Add OBJ copy to the end of array
439+
GDynArray_ADD(item);
434440
return (fCount-1);
435441
}
436442

437-
uint Push(OBJ item) {
438-
GDYNARRAY_ADD(item);
443+
uint Push(OBJ item) { //same as Add
444+
GDynArray_ADD(item);
439445
return (fCount-1);
440446
}
441447

442-
OBJ Pop() {
443-
if (fCount==0) return (OBJ)NULL;
448+
OBJ Pop() { //shoddy.. Do NOT call this for an empty array!
449+
if (fCount==0) return (OBJ)NULL; //a NULL cast operator is required
444450
--fCount;
445451
return fArray[fCount];
446452
}
447453

448454
uint Count() { return fCount; } // get size of array (elements)
449455
uint Capacity() { return fCapacity; }
450-
virtual void setCapacity(uint newcap) {
451-
if (newcap==0) { Clear(); return; } //better use Clear() instead
452-
if (newcap <= fCapacity) return; //never shrink -- use GVec for this
456+
void increaseCapacity(uint newcap) {
457+
if (newcap==0) { Clear(); return; }
458+
if (newcap <= fCapacity) return; //never shrinks (use Pack() for this)
459+
GREALLOC(fArray, newcap*sizeof(OBJ));
460+
fCapacity=newcap;
461+
}
462+
void Trim(int tcount=1) {
463+
//simply cut (discard) the last tcount items
464+
//new Count is now fCount-tcount
465+
//does NOT shrink capacity accordingly!
466+
if (fCount>=tcount) fCount-=tcount;
467+
}
468+
469+
void Pack() { //shrink capacity to fCount+dyn_array_defcap
470+
if (fCapacity-fCount<=dyn_array_defcap) return;
471+
int newcap=fCount+dyn_array_defcap;
453472
GREALLOC(fArray, newcap*sizeof(OBJ));
454473
fCapacity=newcap;
455474
}
456475

457-
void Clear() { // clear array
476+
inline void Shrink() { Pack(); }
477+
478+
void Delete(uint idx) {
479+
GDynArray_TEST_INDEX(idx);
480+
--fCount;
481+
if (idx<fCount)
482+
memmove(&fArray[idx], &fArray[idx+1], (fCount-idx)*sizeof(OBJ));
483+
}
484+
485+
inline void Remove(uint idx) { Delete(idx); }
486+
487+
void Clear() { // clear array, shrinking its allocated memory
458488
fCount = 0;
459489
GREALLOC(fArray, sizeof(OBJ)*dyn_array_defcap);
460490
// set initial memory size again
461491
fCapacity = dyn_array_defcap;
462492
}
463493

464-
void reset() {
465-
fCount = 0; //do not deallocate, just show it empty
494+
void Reset() {// fast clear array WITHOUT deallocating it
495+
fCount = 0;
466496
}
467497
//pointer getptr() { return (pointer) fArray; }
468498
OBJ* operator()() { return fArray; }

0 commit comments

Comments
 (0)