|
1 | 1 | #ifndef G_BASE_DEFINED |
2 | 2 | #define G_BASE_DEFINED |
3 | | -#ifndef _POSIX_SOURCE |
4 | | -//mostly for MinGW |
5 | | -#define _POSIX_SOURCE |
6 | | -#endif |
| 3 | +//#ifndef _POSIX_SOURCE |
| 4 | +////mostly for MinGW;breaks mkdtemp and possibly other functions on OS X |
| 5 | +//#define _POSIX_SOURCE |
| 6 | +//#endif |
7 | 7 | #ifdef HAVE_CONFIG_H |
8 | 8 | #include "config.h" |
9 | 9 | #endif |
@@ -356,64 +356,166 @@ class GSeg { |
356 | 356 | } |
357 | 357 | }; |
358 | 358 |
|
| 359 | +//basic dynamic array template for primitive types |
| 360 | +//which can only grow (reallocate) as needed |
| 361 | +#define GDynArray_INDEX_ERR "Error: invalid index (%d) in dynamic array!\n" |
| 362 | + #if defined(NDEBUG) || defined(NODEBUG) || defined(_NDEBUG) || defined(NO_DEBUG) |
| 363 | + #define GDynArray_TEST_INDEX(x) |
| 364 | +#else |
| 365 | + #define GDynArray_TEST_INDEX(x) \ |
| 366 | + if (x>=fCount) GError(GDynArray_INDEX_ERR, x) |
| 367 | +#endif |
| 368 | + |
| 369 | +#define GDynArray_MAXCOUNT UINT_MAX-1 |
| 370 | +#define GDynArray_NOIDX UINT_MAX |
| 371 | + |
| 372 | +template<class OBJ> class GDynArray { |
| 373 | + protected: |
| 374 | + OBJ *fArray; |
| 375 | + uint fCount; |
| 376 | + uint fCapacity; // size of allocated memory |
| 377 | + const static uint dyn_array_defcap = 16; // initial capacity (in elements) |
| 378 | + public: |
| 379 | + GDynArray(int initcap=dyn_array_defcap):fArray(NULL), fCount(0), |
| 380 | + fCapacity(initcap) { // constructor |
| 381 | + GMALLOC(fArray, fCapacity*sizeof(OBJ)); |
| 382 | + } |
| 383 | + GDynArray(const GDynArray &a):fCount(a.fCount), fCapacity(a.fCapacity) { // copy constructor |
| 384 | + GMALLOC(fArray, sizeof(OBJ)*a.fCapacity); |
| 385 | + memcpy(fArray, a.fArray, sizeof(OBJ)* a.fCapacity); |
| 386 | + } |
| 387 | + virtual ~GDynArray() { GFREE(fArray); } |
| 388 | + GDynArray& operator = (const GDynArray &a) { // assignment operator |
| 389 | + if (this == &a) return *this; |
| 390 | + if (a.fCount == 0) { |
| 391 | + Clear(); |
| 392 | + return *this; |
| 393 | + } |
| 394 | + setCapacity(a.fCapacity); //set size |
| 395 | + memcpy(fArray, a.fArray, sizeof(OBJ)*a.fCount); |
| 396 | + return *this; |
| 397 | + } |
| 398 | + |
| 399 | + OBJ& operator [] (uint idx) {// get array item |
| 400 | + GDynArray_TEST_INDEX(idx); |
| 401 | + return fArray[idx]; |
| 402 | + } |
| 403 | + |
| 404 | + void Grow() { |
| 405 | + int delta = (fCapacity>16) ? (fCapacity>>2) : 2; |
| 406 | + if (GDynArray_MAXCOUNT-delta<=fCapacity) |
| 407 | + delta=GDynArray_MAXCOUNT-fCapacity; |
| 408 | + if (delta<=1) GError("Error at GDynArray::Grow(): max capacity reached!\n"); |
| 409 | + setCapacity(fCapacity + delta); |
| 410 | + } |
| 411 | +#define GDYNARRAY_ADD(item) \ |
| 412 | + if (fCount==MAX_UINT-1) GError("Error at GDynArray: add item failed, maximum count reached!\n"); \ |
| 413 | + if ((++fCount) > fCapacity) Grow(); \ |
| 414 | + fArray[fCount-1] = item; |
| 415 | + |
| 416 | + uint Add(OBJ* item) { // Add item to the end of array by pointer |
| 417 | + if (item==NULL) return GDynArray_NOIDX; |
| 418 | + GDYNARRAY_ADD( (*item) ); |
| 419 | + return (fCount-1); |
| 420 | + } |
| 421 | + |
| 422 | + uint Add(OBJ item) { // Add item copy to the end of array |
| 423 | + GDYNARRAY_ADD(item); |
| 424 | + return (fCount-1); |
| 425 | + } |
| 426 | + |
| 427 | + uint Push(OBJ item) { |
| 428 | + GDYNARRAY_ADD(item); |
| 429 | + return (fCount-1); |
| 430 | + } |
| 431 | + |
| 432 | + OBJ Pop() { |
| 433 | + if (fCount==0) return (OBJ)NULL; |
| 434 | + --fCount; |
| 435 | + return fArray[fCount]; |
| 436 | + } |
| 437 | + uint Count() { return fCount; } // get size of array (elements) |
| 438 | + |
| 439 | + virtual void setCapacity(uint newcap) { |
| 440 | + if (newcap==0) { Clear(); return; } //better use Clear() instead |
| 441 | + if (newcap <= fCapacity) return; //never shrink -- use GVec for this |
| 442 | + GREALLOC(fArray, newcap*sizeof(OBJ)); |
| 443 | + fCapacity=newcap; |
| 444 | + } |
| 445 | + |
| 446 | + void Clear() { // clear array |
| 447 | + fCount = 0; |
| 448 | + GREALLOC(fArray, sizeof(OBJ)*dyn_array_defcap); |
| 449 | + // set initial memory size again |
| 450 | + fCapacity = dyn_array_defcap; |
| 451 | + } |
| 452 | + //pointer getptr() { return (pointer) fArray; } |
| 453 | + OBJ* operator()() { return fArray; } |
| 454 | +}; |
359 | 455 |
|
360 | 456 |
|
361 | 457 | //-------------------------------------------------------- |
362 | 458 | // ************** simple line reading class for text files |
363 | | - |
364 | 459 | //GLineReader -- text line reading/buffering class |
365 | 460 | class GLineReader { |
366 | 461 | bool closeFile; |
367 | | - int len; |
368 | | - int allocated; |
369 | | - char* buf; |
| 462 | + //int len; |
| 463 | + //int allocated; |
| 464 | + GDynArray<char> buf; |
370 | 465 | bool isEOF; |
371 | 466 | FILE* file; |
372 | 467 | off_t filepos; //current position |
373 | 468 | bool pushed; //pushed back |
374 | 469 | int lcount; //line counter (read lines) |
375 | 470 | public: |
376 | | - char* chars() { return buf; } |
377 | | - char* line() { return buf; } |
| 471 | + char* chars() { return buf(); } |
| 472 | + char* line() { return buf(); } |
378 | 473 | int readcount() { return lcount; } //number of lines read |
379 | 474 | void setFile(FILE* stream) { file=stream; } |
380 | | - int length() { return len; } |
381 | | - int size() { return len; } //same as size(); |
| 475 | + int length() { return buf.Count(); } |
| 476 | + int size() { return buf.Count(); } //same as size(); |
382 | 477 | bool isEof() {return isEOF; } |
383 | 478 | bool eof() { return isEOF; } |
384 | 479 | off_t getfpos() { return filepos; } |
385 | 480 | off_t getFpos() { return filepos; } |
386 | 481 | char* nextLine() { return getLine(); } |
387 | | - char* getLine() { if (pushed) { pushed=false; return buf; } |
| 482 | + char* getLine() { if (pushed) { pushed=false; return buf(); } |
388 | 483 | else return getLine(file); } |
389 | 484 | char* getLine(FILE* stream) { |
390 | | - if (pushed) { pushed=false; return buf; } |
| 485 | + if (pushed) { pushed=false; return buf(); } |
391 | 486 | else return getLine(stream, filepos); } |
392 | 487 | char* getLine(FILE* stream, off_t& f_pos); //read a line from a stream and update |
393 | 488 | // the given file position |
394 | 489 | void pushBack() { if (lcount>0) pushed=true; } // "undo" the last getLine request |
395 | 490 | // so the next call will in fact return the same line |
396 | | - GLineReader(const char* fname) { |
| 491 | + GLineReader(const char* fname):closeFile(false),buf(1024),isEOF(false),file(NULL), |
| 492 | + filepos(0), pushed(false), lcount(0) { |
397 | 493 | FILE* f=fopen(fname, "rb"); |
398 | 494 | if (f==NULL) GError("Error opening file '%s'!\n",fname); |
399 | 495 | closeFile=true; |
400 | | - init(f); |
| 496 | + file=f; |
| 497 | + //s_init(f); |
401 | 498 | } |
402 | | - GLineReader(FILE* stream=NULL, off_t fpos=0) { |
403 | | - closeFile=false; |
404 | | - init(stream,fpos); |
| 499 | + GLineReader(FILE* stream=NULL, off_t fpos=0):closeFile(false),buf(1024),isEOF(false),file(stream), |
| 500 | + filepos(fpos), pushed(false), lcount(0) { |
| 501 | + //closeFile=false; |
| 502 | + //s_init(stream,fpos); |
405 | 503 | } |
406 | | - void init(FILE* stream, off_t fpos=0) { |
407 | | - len=0; |
408 | | - isEOF=false; |
409 | | - allocated=1024; |
410 | | - GMALLOC(buf,allocated); |
| 504 | + /* |
| 505 | + void s_init(FILE* stream, off_t fpos=0) { |
| 506 | + //len=0; |
| 507 | + //allocated=1024; |
| 508 | + //GMALLOC(buf,allocated); |
| 509 | + //buf.Clear(); |
| 510 | + //buf.setCapacity(1024); |
| 511 | + isEOF=false; |
411 | 512 | lcount=0; |
412 | | - buf[0]=0; |
| 513 | + //buf[0]=0; |
413 | 514 | file=stream; |
414 | 515 | filepos=fpos; |
415 | 516 | pushed=false; |
416 | 517 | } |
| 518 | + */ |
417 | 519 | ~GLineReader() { |
418 | 520 | GFREE(buf); |
419 | 521 | if (closeFile) fclose(file); |
@@ -447,7 +549,7 @@ int fileExists(const char* fname); |
447 | 549 | //returns 0 if path doesn't exist |
448 | 550 | // 1 if it's a directory |
449 | 551 | // 2 if it's a regular file |
450 | | -// 3 otherwise (?) |
| 552 | +// 3 something else (but entry exists) |
451 | 553 |
|
452 | 554 | int64 fileSize(const char* fpath); |
453 | 555 |
|
|
0 commit comments