[med-svn] [Git][med-team/libgclib][upstream] New upstream version 0.11.9

Michael R. Crusoe gitlab at salsa.debian.org
Mon Jun 1 15:07:21 BST 2020



Michael R. Crusoe pushed to branch upstream at Debian Med / libgclib


Commits:
34c651e5 by Michael R. Crusoe at 2020-06-01T15:48:17+02:00
New upstream version 0.11.9
- - - - -


18 changed files:

- GBase.cpp
- GBase.h
- GFastaIndex.cpp
- GHash.hh
- GIntHash.hh
- + GResUsage.cpp
- + GResUsage.h
- GThreads.cpp
- GThreads.h
- Makefile
- README.md
- gcdb.cpp
- gcdb.h
- gsocket.cpp
- gsocket.h
- gstopwatch.cpp
- gstopwatch.h
- + htest.cpp


Changes:

=====================================
GBase.cpp
=====================================
@@ -10,6 +10,10 @@
 #define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
 #endif
 
+//#ifdef _WIN32
+// int (WINAPIV * __vsnprintf)(char *, size_t, const char*, va_list) = _vsnprintf;
+//#endif
+
 //************************* Debug helpers **************************
 // Assert failed routine
 void GAssert(const char* expression, const char* filename, unsigned int lineno){
@@ -25,7 +29,7 @@ void GAssert(const char* expression, const char* filename, unsigned int lineno){
 
 // Error routine (prints error message and exits!)
 void GError(const char* format,...){
-  #ifdef __WIN32__
+  #ifdef _WIN32
     char msg[4096];
     va_list arguments;
     va_start(arguments,format);
@@ -50,7 +54,7 @@ void GError(const char* format,...){
 
 // Warning routine (just print message without exiting)
 void GMessage(const char* format,...){
-  #ifdef __WIN32__
+  #ifdef _WIN32
     char msg[4096];
     va_list arguments;
     va_start(arguments,format);
@@ -71,7 +75,8 @@ void GMessage(const char* format,...){
 // Allocate memory
 bool GMalloc(pointer* ptr,unsigned long size){
   //GASSERT(ptr);
-  if (size!=0) *ptr=malloc(size);
+  if (size!=0)
+	  *ptr=malloc(size);
   return *ptr!=NULL;
   }
 
@@ -150,16 +155,17 @@ int Gstrcmp(const char* a, const char* b, int n) {
 
 int G_mkdir(const char* path, int perms = (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) ) {
    //int perms=(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) ) {
- #ifdef __WIN32__
-     return _mkdir(path);
+ #ifdef _WIN32
+     //return _mkdir(path);
+	 return CreateDirectoryA(path, NULL);
  #else
-     return  mkdir(path, perms);
+     return mkdir(path, perms);
  #endif
 }
 
 
 void Gmktempdir(char* templ) {
-#ifdef __WIN32__
+#ifdef _WIN32
   int blen=strlen(templ);
   if (_mktemp_s(templ, blen)!=0)
 	  GError("Error creating temp dir %s!\n", templ);
@@ -379,6 +385,7 @@ char* rstrchr(char* str, char ch) {  /* returns a pointer to the rightmost
 }
 
 
+
 /* DOS/UNIX safer fgets : reads a text line from a (binary) file and
   update the file position accordingly and the buffer capacity accordingly.
   The given buf is resized to read the entire line in memory
@@ -717,9 +724,9 @@ int fileExists(const char* fname) {
 }
 
 int64 fileSize(const char* fpath) {
-#ifdef __WIN32__
+#ifdef _WIN32
     WIN32_FILE_ATTRIBUTE_DATA fad;
-    if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
+    if (!GetFileAttributesEx(fpath, GetFileExInfoStandard, &fad))
         return -1; // error condition, could call GetLastError to find out more
     LARGE_INTEGER size;
     size.HighPart = fad.nFileSizeHigh;


=====================================
GBase.h
=====================================
@@ -1,10 +1,22 @@
 #ifndef G_BASE_DEFINED
 #define G_BASE_DEFINED
-#define GCLIB_VERSION "0.11.8"
+#define GCLIB_VERSION "0.11.9"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+
+#if defined(__WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) || defined(__MINGW64__) || defined(__WINDOWS__)
+  #ifndef _WIN32
+    #define _WIN32
+  #endif
+  #ifndef _WIN64
+    #define _WIN64
+  #endif
+  #define __USE_MINGW_ANSI_STDIO 1
+  //#define __ISO_C_VISIBLE 1999
+#endif
+
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -15,19 +27,9 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-#if defined __WIN32 || defined __WIN32__ || defined _WIN32 || defined _WIN32_ || defined _WINDOWS
-  #ifndef __WIN32__
-    #define __WIN32__
-  #endif
+#ifdef _WIN32
   #include <windows.h>
-  #include <direct.h>
   #include <io.h>
-  #ifndef strcasecmp
-      #define strcasecmp _stricmp
-  #endif
-  #ifndef strncasecmp
-      #define strncasecmp _strnicmp
-  #endif
   #define CHPATHSEP '\\'
   #undef off_t
   #define off_t int64_t
@@ -204,7 +206,6 @@ bool GCalloc(pointer* ptr, unsigned long size); // Allocate and initialize memor
 bool GRealloc(pointer* ptr,unsigned long size); // Resize memory
 void GFree(pointer* ptr); // Free memory, resets ptr to NULL
 
-
 //int saprintf(char **retp, const char *fmt, ...);
 
 void GError(const char* format,...); // Error routine (aborts program)
@@ -233,6 +234,7 @@ char* loCase(const char* str);
 char* strlower(char * str);
 char* strupper(char * str);
 
+
 //strstr but for memory zones: scans a memory region
 //for a substring:
 void* Gmemscan(void *mem, unsigned int len,
@@ -436,7 +438,7 @@ template<class OBJ> class GDynArray {
     		Clear();
     		return *this;
     	}
-    	increaseCapacity(a.fCapacity); //set size
+    	growTo(a.fCapacity); //set size
         memcpy(fArray, a.fArray, sizeof(OBJ)*a.fCount);
         return *this;
     }
@@ -451,7 +453,7 @@ template<class OBJ> class GDynArray {
     	if (GDynArray_MAXCOUNT-delta<=fCapacity)
     		delta=GDynArray_MAXCOUNT-fCapacity;
     	if (delta<=1) GError("Error at GDynArray::Grow(): max capacity reached!\n");
-    	increaseCapacity(fCapacity + delta);
+    	growTo(fCapacity + delta);
     }
 #define GDynArray_ADD(item) \
     	if (fCount==MAX_UINT-1) GError("Error at GDynArray: cannot add item, maximum count reached!\n"); \
@@ -483,12 +485,27 @@ template<class OBJ> class GDynArray {
 
     uint Count() { return fCount; } // get size of array (elements)
     uint Capacity() { return fCapacity; }
-    void increaseCapacity(uint newcap) {
+    void growTo(uint newcap) {
     	if (newcap==0) { Clear(); return; }
-    	if (newcap <= fCapacity) return; //never shrinks (use Pack() for this)
+    	if (newcap <= fCapacity) return; //never shrink! (use Pack() for shrinking)
     	GREALLOC(fArray, newcap*sizeof(OBJ));
     	fCapacity=newcap;
     }
+
+    void append(OBJ* arr, uint count) {
+    	//fast adding of a series of objects
+    	growTo(fCount+count);
+    	memcpy(fArray+fCount, arr, count*sizeof(OBJ));
+    	fCount+=count;
+    }
+
+    void append(GDynArray<OBJ> arr) {
+    	//fast adding of a series of objects
+    	growTo(fCount+arr.fCount);
+    	memcpy(fArray+fCount, arr.fArray, arr.fCount*sizeof(OBJ));
+    	fCount+=arr.fCount;
+    }
+
     void Trim(int tcount=1) {
     	//simply cut (discard) the last tcount items
     	//new Count is now fCount-tcount
@@ -503,6 +520,15 @@ template<class OBJ> class GDynArray {
     	fCapacity=newcap;
     }
 
+    void zPack(OBJ z) { //shrink capacity to fCount+1 and adds a z terminator
+    	if (fCapacity-fCount<=1) { fArray[fCount]=z; return; }
+    	int newcap=fCount+1;
+    	GREALLOC(fArray, newcap*sizeof(OBJ));
+    	fCapacity=newcap;
+    	fArray[fCount]=z;
+    }
+
+
     inline void Shrink() { Pack(); }
 
     void Delete(uint idx) {
@@ -527,7 +553,7 @@ template<class OBJ> class GDynArray {
 
     OBJ* operator()() { return fArray; }
 
-    //use below to prevent freeing the fArray pointer
+    //use methods below in order to prevent deallocation of fArray pointer on destruct
     //could be handy for adopting stack objects (e.g. cheap dynamic strings)
     void ForgetPtr() { byptr=true;  }
     void DetachPtr() { byptr=true;  }
@@ -547,7 +573,6 @@ int strsplit(char* str, GDynArray<char*>& fields, int maxfields=MAX_INT); //spli
 //splits a string by placing 0 where tab or space is found, setting fields[] to the beginning
 //of each field (stopping after maxfields); returns number of fields parsed
 
-//--------------------------------------------------------
 // ************** simple line reading class for text files
 //GLineReader -- text line reading/buffering class
 class GLineReader {


=====================================
GFastaIndex.cpp
=====================================
@@ -47,7 +47,7 @@ int GFastaIndex::loadIndex(const char* finame) { //load record info from existin
       p++;
       uint len=0;
       int line_len=0, line_blen=0;
-#ifdef __WIN32__
+#ifdef _WIN32
          long offset=-1;
          sscanf(p, "%d%ld%d%d", &len, &offset, &line_len, &line_blen);
 #else
@@ -164,7 +164,7 @@ int GFastaIndex::storeIndex(FILE* fai) {
     }
   //reclist has records sorted by file offset
   for (int i=0;i<reclist.Count();i++) {
-#ifdef __WIN32__
+#ifdef _WIN32
     int written=fprintf(fai, "%s\t%d\t%ld\t%d\t%d\n",
             reclist[i]->seqname,reclist[i]->seqlen,(long)reclist[i]->fpos,
               reclist[i]->line_len, reclist[i]->line_blen);


=====================================
GHash.hh
=====================================
@@ -1,139 +1,129 @@
 /********************************************************************************
-*                  Hash table class template (char* based)                               *
-*********************************************************************************/
+ *                  Hash table class template (char* based)                               *
+ *********************************************************************************/
 
 #ifndef GHash_HH
 #define GHash_HH
 #include "GBase.h"
 
 /**
-* This class maintains a fast-access hash table of entities
-* indexed by a character string (essentially, maps strings to pointers)
-*/
+ * This class maintains a fast-access hash table of entities
+ * indexed by a character string (essentially, maps strings to pointers)
+ */
 
 //#define HASH_DBG_PRINT 1
 
 #define GSTR_HASH(s) strhash(s)
 //#define GSTR_HASH(s) djb_hash(s)
 //#define GSTR_HASH(s) fnv1a_hash(s)
+//#define GSTR_HASH(s) murmur3(s)
 
 template <class OBJ> class GHash {
- protected:
+protected:
 	struct GHashEntry {
-	     char*   key;              // Key string
-	     bool    keyalloc;         //shared key flag (to not free the key chars)
-	     int     hash;             // Hash value of key
-	     pointer data;              // Data
-	     bool    mark;             // Entry is marked
-	     };
-  GHashEntry* hash;         // Hash
-  int         fCapacity;     // table size
-  int         fCount;        // number of valid entries
-  int  fCurrentEntry;
-  char* lastkeyptr; //pointer to last key string added
-    //---------- Raw data retrieval (including empty entries
-  // Return key at position pos.
-  const char* Key(uint pos) const { return hash[pos].key; }
-  // return data OBJ* at given position
-  OBJ* Data(uint pos) const { return (OBJ*) hash[pos].data; }
-  // Return mark flag of entry at position pos.
-  bool Mark(uint pos) const { return hash[pos].mark; }
-  // Return position of first filled slot, or >= fCapacity
-  int First() const;
-  // Return position of last filled slot or -1
-  int Last() const;
-  // Return position of next filled slot in hash table
-  // or a value greater than or equal to fCapacity if no filled
-  // slot was found
-  int Next(int pos) const;
-  //Return position of previous filled slot in hash table
-  //or a -1 if no filled slot was found
-  int Prev(int pos) const;
+		char*   key;              // Key string
+		bool    keyalloc;         // shared key flag (to free/not the key)
+		int     hash;             // Hash value of key
+		pointer data;             // Data
+	};
+	GHashEntry* hash;          // Hash
+	int         fCapacity;     // table size
+	int         fCount;        // number of valid entries
+	int  fCurrentEntry;
+	char* lastkeyptr; //pointer to last key string added
+	//---------- Raw data retrieval (including empty entries)
+	// Return key at position pos.
+	const char* Key(uint pos) const { return hash[pos].key; }
+	// return data OBJ* at given position
+	OBJ* Data(uint pos) const { return (OBJ*) hash[pos].data; }
+	// Return position of first filled slot, or >= fCapacity
+	int First() const;
+	// Return position of last filled slot or -1
+	int Last() const;
+	// Return position of next filled slot in hash table
+	// or a value greater than or equal to fCapacity if no filled
+	// slot was found
+	int Next(int pos) const;
+	//Return position of previous filled slot in hash table
+	//or a -1 if no filled slot was found
+	int Prev(int pos) const;
 
 private:
-  GHash(const GHash&);
-  GHash &operator=(const GHash&);
-  GFreeProc* fFreeProc; //procedure to free item data
+	GHash(const GHash&);
+	GHash &operator=(const GHash&);
+	GFreeProc* fFreeProc; //procedure to free item data
 protected:
 public:
-  static void DefaultFreeProc(pointer item) {
-      delete (OBJ*)item;
-  }
+	static void DefaultFreeProc(pointer item) {
+		delete (OBJ*)item;
+	}
 public:
-  GHash(GFreeProc* freeProc); // constructs of an empty hash
-  GHash(bool doFree=true); // constructs of an empty hash (free the item objects)
-  void setFreeItem(GFreeProc *freeProc) { fFreeProc=freeProc; }
-  void setFreeItem(bool doFree) { fFreeProc=(doFree)? &DefaultFreeProc : NULL; }
-  int Capacity() const { return fCapacity; } // table's size, including the empty slots.
-  void Resize(int m);  // Resize the table to the given size.
-  int Count() const { return fCount; }// the total number of entries in the table.
-
-  // Insert a new entry into the table given key and mark.
-  // If there is already an entry with that key, leave it unchanged
-  OBJ* Add(const char* ky, OBJ* ptr=NULL, bool mrk=false);
-
-  //same with Add, but frees the old element if it's a replacement
-  OBJ* fAdd(const char* ky, OBJ* ptr=NULL);
-
-  //same as Add, but the key pointer is stored directly, no string duplicate
-  //is made (shared-key-Add)
-  OBJ* shkAdd(const char* ky, OBJ* ptr, bool mrk=false);
-
-  // Replace data at key, if the entry's mark is less than
-  // or equal to the given mark.  If there was no existing entry,
-  // a new entry is inserted with the given mark.
-  OBJ* Replace(const char* ky, OBJ* ptr, bool mrk=false);
-  // Remove a given key and its data
-  OBJ* Remove(const char* ky);
-  // Find data OBJ* given key.
-  OBJ* Find(const char* ky, char** keyptr=NULL);
-  bool hasKey(const char* ky);
-  char* getLastKey() { return lastkeyptr; }
-  OBJ* operator[](const char* ky) { return Find(ky); }
-  void startIterate(); //iterator-like initialization
-  char* NextKey(); //returns next valid key in the table (NULL if no more)
-  OBJ* NextData(); //returns next valid hash[].data
-  OBJ* NextData(char*& nextkey); //returns next valid hash[].data
-                                //or NULL if no more
-                                //nextkey is SET to the corresponding key
-  GHashEntry* NextEntry() { //returns a pointer to a GHashEntry
-  	 int pos=fCurrentEntry;
-  	 while (pos<fCapacity && hash[pos].hash<0) pos++;
-  	 if (pos==fCapacity) {
-  	                 fCurrentEntry=fCapacity;
-  	                 return NULL;
-  	                 }
-  	              else {
-  	                 fCurrentEntry=pos+1;
-  	                 return &hash[pos];
-  	                 }
-  }
-  /// Clear all entries
-  void Clear();
-
-  /// Destructor
-  virtual ~GHash();
-  };
+	GHash(GFreeProc* freeProc); // constructs of an empty hash
+	GHash(bool doFree=true); // constructs of an empty hash (free the item objects)
+	void setFreeItem(GFreeProc *freeProc) { fFreeProc=freeProc; }
+	void setFreeItem(bool doFree) { fFreeProc=(doFree)? &DefaultFreeProc : NULL; }
+	int Capacity() const { return fCapacity; } // table's size, including the empty slots.
+	void Resize(int m);  // Resize the table to the given size.
+	int Count() const { return fCount; }// the total number of entries in the table.
+
+	// Insert a new entry into the table given key.
+	// If there is already an entry with that key, leave it unchanged
+	OBJ* Add(const char* ky, OBJ* ptr=NULL);
+
+	//same with Add, but frees the old element if it's a replacement
+	OBJ* fAdd(const char* ky, OBJ* ptr=NULL);
+
+	//same as Add, but the key pointer is stored directly, no string copy needed
+	//(shared-key-Add)
+	OBJ* shkAdd(const char* ky, OBJ* ptr);
+
+	// Replace data at key. If there was no existing entry,
+	// a new entry is inserted.
+	OBJ* Replace(const char* ky, OBJ* ptr);
+	// Remove a given key and its data
+	OBJ* Remove(const char* ky);
+	// Find data OBJ* given key.
+	OBJ* Find(const char* ky, char** keyptr=NULL);
+	bool hasKey(const char* ky);
+	char* getLastKey() { return lastkeyptr; }
+	OBJ* operator[](const char* ky) { return Find(ky); }
+	void startIterate(); //iterator-like initialization
+	char* NextKey(); //returns next valid key in the table (NULL if no more)
+	OBJ* NextData(); //returns next valid hash[].data
+	OBJ* NextData(char*& nextkey); //returns next valid hash[].data
+	//or NULL if no more
+	//nextkey is SET to the corresponding key
+	GHashEntry* NextEntry() { //returns a pointer to a GHashEntry
+		int pos=fCurrentEntry;
+		while (pos<fCapacity && hash[pos].hash<0) pos++;
+		if (pos==fCapacity) {
+			fCurrentEntry=fCapacity;
+			return NULL;
+		}
+		else {
+			fCurrentEntry=pos+1;
+			return &hash[pos];
+		}
+	}
+	/// Clear all entries
+	void Clear();
+
+	/// Destructor
+	virtual ~GHash();
+};
 //
 //======================== method definitions ========================
 //
 /*
   Notes:
-  - The hash algorithm should yield a fCount in the range [0...GHash::EMPTY)
-     GHash::EMPTY and GHash::UNUSED are needed for flag purposes.
   - Since the algorithm doubles the table size when exceeding MAX_LOAD,
     it would be prudent to keep MIN_LOAD less than 1/2 MAX_LOAD;
-    otherwise, the algorithm might hip-hop between halving and doubling,
-    which would be quite expensive!!
-  - Not many people seem to know that hash tables don't have to be prime
-    numbers; in fact, a table size of 2**n and odd probe distance are very
-    easy to arrange, and this works just as well!
-  - We store the hash key, so that 99.999% of the time we can compare hash numbers;
-    only when hash numbers match do we need to compare keys.
-    Thus, with a good hash function, the fCount of calls to strcmp() should be
+    otherwise, the algorithm might flip between halving and doubling!
+  - We store the key hash value so that 99.999% of the time we can compare hash numbers;
+    only when hash numbers match we need to compare keys.
+  - Thus with a good hash function the fCount of calls to strcmp() should be
     roughly the same as the fCount of successful lookups.
-  - The hash table should NEVER get full, or stuff will loop forever!!
-*/
+ */
 
 // Initial table size (MUST be power of 2)
 #define DEF_HASH_SIZE      32
@@ -141,6 +131,7 @@ public:
 #define MAX_LOAD           80
 // Minimum hash table load factor (%)
 #define MIN_LOAD           10
+
 // Probe Position [0..n-1]
 #define HASH1(x,n) (((unsigned int)(x)*13)%(n))
 // Probe Distance [1..n-1]
@@ -151,544 +142,462 @@ public:
 /*******************************************************************************/
 // Construct empty hash
 template <class OBJ> GHash<OBJ>::GHash(GFreeProc* freeProc) {
-  GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);
-  fCurrentEntry=-1;
-  fFreeProc=freeProc;
-  lastkeyptr=NULL;
-  for (uint i=0; i<DEF_HASH_SIZE; i++)
-         hash[i].hash=-1; //this will be an indicator for 'empty' entries
-  fCapacity=DEF_HASH_SIZE;
-  fCount=0;
-  }
+	GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);
+	fCurrentEntry=-1;
+	fFreeProc=freeProc;
+	lastkeyptr=NULL;
+	for (uint i=0; i<DEF_HASH_SIZE; i++)
+		hash[i].hash=-1; //this will be an indicator for 'empty' entries
+	fCapacity=DEF_HASH_SIZE;
+	fCount=0;
+}
 
 template <class OBJ> GHash<OBJ>::GHash(bool doFree) {
-  GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);
-  fCurrentEntry=-1;
-  lastkeyptr=NULL;
-  fFreeProc = (doFree)?&DefaultFreeProc : NULL;
-  for (uint i=0; i<DEF_HASH_SIZE; i++)
-         hash[i].hash=-1; //this will be an indicator for 'empty' entries
-  fCapacity=DEF_HASH_SIZE;
-  fCount=0;
-  }
+	GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);
+	fCurrentEntry=-1;
+	lastkeyptr=NULL;
+	fFreeProc = (doFree)?&DefaultFreeProc : NULL;
+	for (uint i=0; i<DEF_HASH_SIZE; i++)
+		hash[i].hash=-1; //this will be an indicator for 'empty' entries
+	fCapacity=DEF_HASH_SIZE;
+	fCount=0;
+}
 
 
 // Resize table
-template <class OBJ> void GHash<OBJ>::Resize(int m){
-  int i,n,p,x,h;
-  GHashEntry *k;
-  GASSERT(fCount<=fCapacity);
-  if(m<DEF_HASH_SIZE) m=DEF_HASH_SIZE;
-  n=fCapacity;
-  while((n>>2)>m) n>>=1;            // Shrink until n/4 <= m
-  while((n>>1)<m) n<<=1;            // Grow until m <= n/2
-  GASSERT(m<=(n>>1));
-  GASSERT(DEF_HASH_SIZE<=n);
-  if(n!=fCapacity){
-    GASSERT(m<=n);
-    GMALLOC(k, sizeof(GHashEntry)*n);
-    for(i=0; i<n; i++) k[i].hash=-1;
-    for(i=0; i<fCapacity; i++){
-      h=hash[i].hash;
-      if(0<=h){
-        p=HASH1(h,n);
-        GASSERT(0<=p && p<n);
-        x=HASH2(h,n);
-        GASSERT(1<=x && x<n);
-        while(k[p].hash!=-1) p=(p+x)%n;
-        GASSERT(k[p].hash<0);
-        k[p]=hash[i];
-        }
-      }
-    GFREE(hash);
-    hash=k;
-    fCapacity=n;
-    }
-  }
+template <class OBJ> void GHash<OBJ>::Resize(int m) {
+	int i,n,p,x,h;
+	GHashEntry *k;
+	GASSERT(fCount<=fCapacity);
+	if(m<DEF_HASH_SIZE) m=DEF_HASH_SIZE;
+	n=fCapacity;
+	while((n>>2)>m) n>>=1;            // Shrink until n/4 <= m
+	while((n>>1)<m) n<<=1;            // Grow until m <= n/2
+	GASSERT(m<=(n>>1));
+	GASSERT(DEF_HASH_SIZE<=n);
+	if(n!=fCapacity){
+		GASSERT(m<=n);
+		GMALLOC(k, sizeof(GHashEntry)*n);
+		for(i=0; i<n; i++) k[i].hash=-1;
+		for(i=0; i<fCapacity; i++){
+			h=hash[i].hash;
+			if(h>=0){
+				p=HASH1(h,n);
+				GASSERT(0<=p && p<n);
+				x=HASH2(h,n);
+				GASSERT(1<=x && x<n);
+				while(k[p].hash!=-1) p=(p+x)%n;
+				GASSERT(k[p].hash<0);
+				k[p]=hash[i];
+			}
+		}
+		GFREE(hash);
+		hash=k;
+		fCapacity=n;
+	}
+}
 
 // add a new entry, or update it if it already exists
 
 
-template <class OBJ> OBJ* GHash<OBJ>::Add(const char* ky,
-	                      OBJ* pdata, bool mrk){
-	  int p,i,x,h,n;
-	  if(!ky) GError("GHash::insert: NULL key argument.\n");
-	  GASSERT(fCount<fCapacity);
-	  h=GSTR_HASH(ky);
-	  GASSERT(0<=h);
-	  p=HASH1(h,fCapacity);
-	  GASSERT(0<=p && p<fCapacity);
-	  x=HASH2(h,fCapacity);
-	  GASSERT(1<=x && x<fCapacity);
-	  i=-1;
-	  n=fCapacity;
+template <class OBJ> OBJ* GHash<OBJ>::Add(const char* ky, OBJ* pdata) {
+	int p,i,x,h,n;
+	if(!ky) GError("GHash::insert: NULL key argument.\n");
+	GASSERT(fCount<fCapacity);
+	h=GSTR_HASH(ky);
+	GASSERT(0<=h);
+	p=HASH1(h,fCapacity);
+	GASSERT(0<=p && p<fCapacity);
+	x=HASH2(h,fCapacity);
+	GASSERT(1<=x && x<fCapacity);
+	i=-1;
+	n=fCapacity;
 #ifdef HASH_DBG_PRINT
-	  int iterations=0;
-	  int init_p=p;
-	  int init_x=x;
+	int iterations=0;
+	int init_p=p;
+	int init_x=x;
 #endif
-	  while(n && hash[p].hash!=-1) {
-	    if ((i==-1)&&(hash[p].hash==-2)) i=p;
-	    if (hash[p].hash==h && strcmp(hash[p].key,ky)==0) {
-	      //replace hash data for this key!
-	      lastkeyptr=hash[p].key;
-	      OBJ* r = (OBJ*) hash[p].data;
-	      hash[p].data = (void*) pdata;
+	while(n && hash[p].hash!=-1) {
+		if ((i==-1)&&(hash[p].hash==-2)) i=p;
+		if (hash[p].hash==h && strcmp(hash[p].key,ky)==0) {
+			//replace hash data for this key!
+			lastkeyptr=hash[p].key;
+			OBJ* r = (OBJ*) hash[p].data;
+			hash[p].data = (void*) pdata;
 #ifdef HASH_DBG_PRINT
-	      GMessage("Add.R\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
-	    		  ky, h,init_p,init_x, iterations,  fCount, fCapacity);
+			GMessage("Add.R\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
+					ky, h,init_p,init_x, iterations,  fCount, fCapacity);
 #endif
-	      //return (OBJ*)hash[p].data;
-	      return r;
-	      }
-	    p=(p+x)%fCapacity;
-	    n--;
-	    }
-	  if(i==-1) i=p;
+			return r;
+		}
+		p=(p+x)%fCapacity;
+		n--;
+	}
+	if(i==-1) i=p;
 #ifdef HASH_DBG_PRINT
-      GMessage("Add.N\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
-    		  ky, h,init_p,init_x, iterations,  fCount, fCapacity);
+	GMessage("Add.N\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
+			ky, h,init_p,init_x, iterations,  fCount, fCapacity);
 #endif
-	  GTRACE(("GHash::insert: key=\"%s\"\n",ky));
-	  //GMessage("GHash::insert: key=\"%s\"\n",ky);
-	  GASSERT(0<=i && i<fCapacity);
-	  GASSERT(hash[i].hash<0);
-	  hash[i].hash=h;
-	  hash[i].mark=mrk;
-	  hash[i].key=Gstrdup(ky);
-	  hash[i].keyalloc=true;
-	  lastkeyptr=hash[i].key;
-	  hash[i].data= (void*) pdata;
-	  fCount++;
-	  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
-	  GASSERT(fCount<fCapacity);
-	  return pdata;
- }
+	GTRACE(("GHash::insert: key=\"%s\"\n",ky));
+	//GMessage("GHash::insert: key=\"%s\"\n",ky);
+	GASSERT(0<=i && i<fCapacity);
+	GASSERT(hash[i].hash<0);
+	hash[i].hash=h;
+	hash[i].key=Gstrdup(ky);
+	hash[i].keyalloc=true;
+	lastkeyptr=hash[i].key;
+	hash[i].data= (void*) pdata;
+	fCount++;
+	if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
+	GASSERT(fCount<fCapacity);
+	return pdata;
+}
 
-/*
-  int p,i,x,h;
-  if(!ky) GError("GHash::insert: NULL key argument.\n");
-  GASSERT(fCount<fCapacity);
-  h=GSTR_HASH(ky);
-  GASSERT(0<=h);
-  p=HASH1(h,fCapacity);
-  GASSERT(0<=p && p<fCapacity);
-  x=HASH2(h,fCapacity);
-  GASSERT(1<=x && x<fCapacity);
-  if (checkReplace(ky, pdata, p, i, h, x)) {
-	  return (OBJ*)hash[p].data;
-  }
-  GTRACE(("GHash::insert: key=\"%s\"\n",ky));
-  //GMessage("GHash::insert: key=\"%s\"\n",ky);
-  GASSERT(0<=i && i<fCapacity);
-  GASSERT(hash[i].hash<0);
-  hash[i].hash=h;
-  hash[i].mark=mrk;
-  hash[i].key=Gstrdup(ky);
-  hash[i].keyalloc=true;
-  lastkeyptr=hash[i].key;
-  hash[i].data= (void*) pdata;
-  fCount++;
-  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
-  GASSERT(fCount<fCapacity);
-  return pdata;
-  }
-*/
-template <class OBJ> OBJ* GHash<OBJ>::fAdd(const char* ky,
-                      OBJ* pdata){
-  int p,i,x,h,n;
-  if(!ky) GError("GHash::insert: NULL key argument.\n");
-  GASSERT(fCount<fCapacity);
-  h=GSTR_HASH(ky);
-  GASSERT(0<=h);
-  p=HASH1(h,fCapacity);
-  GASSERT(0<=p && p<fCapacity);
-  x=HASH2(h,fCapacity);
-  GASSERT(1<=x && x<fCapacity);
-  i=-1;
-  n=fCapacity;
+template <class OBJ> OBJ* GHash<OBJ>::fAdd(const char* ky, OBJ* pdata) {
+	int p,i,x,h,n;
+	if(!ky) GError("GHash::insert: NULL key argument.\n");
+	GASSERT(fCount<fCapacity);
+	h=GSTR_HASH(ky);
+	GASSERT(0<=h);
+	p=HASH1(h,fCapacity);
+	GASSERT(0<=p && p<fCapacity);
+	x=HASH2(h,fCapacity);
+	GASSERT(1<=x && x<fCapacity);
+	i=-1;
+	n=fCapacity;
 #ifdef HASH_DBG_PRINT
-  int iterations=0;
-  int init_p=p;
-  int init_x=x;
+	int iterations=0;
+	int init_p=p;
+	int init_x=x;
 #endif
-  while(n && hash[p].hash!=-1) {
-    if ((i==-1)&&(hash[p].hash==-2)) i=p;
-    if (hash[p].hash==h && strcmp(hash[p].key,ky)==0) {
-      //replace hash data for this key!
-      lastkeyptr=hash[p].key;
-      if (FREEDATA) (*fFreeProc)(hash[p].data);
-      hash[p].data = (void*) pdata;
+	while(n && hash[p].hash!=-1) {
+		if ((i==-1)&&(hash[p].hash==-2)) i=p;
+		if (hash[p].hash==h && strcmp(hash[p].key,ky)==0) {
+			//replace hash data for this key!
+			lastkeyptr=hash[p].key;
+			if (FREEDATA) (*fFreeProc)(hash[p].data);
+			hash[p].data = (void*) pdata;
 #ifdef HASH_DBG_PRINT
-      GMessage("Add.R\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
-    		  ky, h,init_p,init_x, iterations,  fCount, fCapacity);
+			GMessage("Add.R\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
+					ky, h,init_p,init_x, iterations,  fCount, fCapacity);
 #endif
-      return pdata;
-      }
-    p=(p+x)%fCapacity;
+			return pdata;
+		}
+		p=(p+x)%fCapacity;
 #ifdef HASH_DBG_PRINT
-    ++iterations;
+		++iterations;
 #endif
-    n--;
-    }
-  if(i==-1) i=p;
+		n--;
+	}
+	if(i==-1) i=p;
 #ifdef HASH_DBG_PRINT
-  GMessage("Add.N\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
-		  ky, h,init_p,init_x, iterations,  fCount, fCapacity);
+	GMessage("Add.N\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
+			ky, h,init_p,init_x, iterations,  fCount, fCapacity);
 #endif
-  GTRACE(("GHash::insert: key=\"%s\"\n",ky));
-  //GMessage("GHash::insert: key=\"%s\"\n",ky);
-  GASSERT(0<=i && i<fCapacity);
-  GASSERT(hash[i].hash<0);
-  hash[i].hash=h;
-  hash[i].mark=false;
-  hash[i].key=Gstrdup(ky);
-  hash[i].keyalloc=true;
-  lastkeyptr=hash[i].key;
-  hash[i].data= (void*) pdata;
-  fCount++;
-  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
-  GASSERT(fCount<fCapacity);
-  return pdata;
-  }
-
-
-
-template <class OBJ> OBJ* GHash<OBJ>::shkAdd(const char* ky,
-                      OBJ* pdata,bool mrk){
-  int p,i,x,h,n;
-  if(!ky) GError("GHash::insert: NULL key argument.\n");
-  GASSERT(fCount<fCapacity);
-  h=GSTR_HASH(ky);
-  GASSERT(0<=h);
-  p=HASH1(h,fCapacity);
-  GASSERT(0<=p && p<fCapacity);
-  x=HASH2(h,fCapacity);
-  GASSERT(1<=x && x<fCapacity);
-  i=-1;
-  n=fCapacity;
-  while(n && hash[p].hash!=-1){
-    if((i==-1)&&(hash[p].hash==-2)) i=p;
-    if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
-      //replace hash data for this key!
-      lastkeyptr=hash[p].key;
-      hash[p].data = (void*) pdata;
-      return (OBJ*)hash[p].data;
-      }
-    p=(p+x)%fCapacity;
-    n--;
-    }
-  if(i==-1) i=p;
-  GTRACE(("GHash::insert: key=\"%s\"\n",ky));
-  //GMessage("GHash::insert: key=\"%s\"\n",ky);
-  GASSERT(0<=i && i<fCapacity);
-  GASSERT(hash[i].hash<0);
-  hash[i].hash=h;
-  hash[i].mark=mrk;
-  hash[i].key=(char *)ky;
-  lastkeyptr=hash[i].key;
-  hash[i].keyalloc=false;
-  hash[i].data= (void*) pdata;
-  fCount++;
-  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
-  GASSERT(fCount<fCapacity);
-  return pdata;
-  }
+	GTRACE(("GHash::insert: key=\"%s\"\n",ky));
+	//GMessage("GHash::insert: key=\"%s\"\n",ky);
+	GASSERT(0<=i && i<fCapacity);
+	GASSERT(hash[i].hash<0);
+	hash[i].hash=h;
+	hash[i].key=Gstrdup(ky);
+	hash[i].keyalloc=true;
+	lastkeyptr=hash[i].key;
+	hash[i].data= (void*) pdata;
+	fCount++;
+	if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
+	GASSERT(fCount<fCapacity);
+	return pdata;
+}
 
+template <class OBJ> OBJ* GHash<OBJ>::shkAdd(const char* ky, OBJ* pdata) {
+	int p,i,x,h,n;
+	if(!ky) GError("GHash::insert: NULL key argument.\n");
+	GASSERT(fCount<fCapacity);
+	h=GSTR_HASH(ky);
+	GASSERT(0<=h);
+	p=HASH1(h,fCapacity);
+	GASSERT(0<=p && p<fCapacity);
+	x=HASH2(h,fCapacity);
+	GASSERT(1<=x && x<fCapacity);
+	i=-1;
+	n=fCapacity;
+	while(n && hash[p].hash!=-1){
+		if((i==-1)&&(hash[p].hash==-2)) i=p;
+		if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
+			//replace hash data for this key!
+			lastkeyptr=hash[p].key;
+			hash[p].data = (void*) pdata;
+			return (OBJ*)hash[p].data;
+		}
+		p=(p+x)%fCapacity;
+		n--;
+	}
+	if(i==-1) i=p;
+	GTRACE(("GHash::insert: key=\"%s\"\n",ky));
+	//GMessage("GHash::insert: key=\"%s\"\n",ky);
+	GASSERT(0<=i && i<fCapacity);
+	GASSERT(hash[i].hash<0);
+	hash[i].hash=h;
+	hash[i].key=(char *)ky;
+	lastkeyptr=hash[i].key;
+	hash[i].keyalloc=false;
+	hash[i].data= (void*) pdata;
+	fCount++;
+	if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
+	GASSERT(fCount<fCapacity);
+	return pdata;
+}
 
 // Add or replace entry
-template <class OBJ>  OBJ* GHash<OBJ>::Replace(const char* ky, OBJ* pdata, bool mrk){
-  int p,i,x,h,n;
-  if(!ky){ GError("GHash::replace: NULL key argument.\n"); }
-  GASSERT(fCount<fCapacity);
-  h=GSTR_HASH(ky);
-  GASSERT(0<=h);
-  p=HASH1(h,fCapacity);
-  GASSERT(0<=p && p<fCapacity);
-  x=HASH2(h,fCapacity);
-  GASSERT(1<=x && x<fCapacity);
-  i=-1;
-  n=fCapacity;
-  while(n && hash[p].hash!=-1){
-    if((i==-1)&&(hash[p].hash==-2)) i=p;
-    if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
-      if(hash[p].mark<=mrk){
-        GTRACE(("GHash::replace: %08x: replacing: \"%s\"\n",this,ky));
-        if (FREEDATA) (*fFreeProc)(hash[p].data);
-        hash[p].mark=mrk;
-        hash[p].data=pdata;
-        }
-      return hash[p].data;
-      }
-    p=(p+x)%fCapacity;
-    n--;
-    }
-  if(i==-1) i=p;
-  GTRACE(("GHash::replace: %08x: inserting: \"%s\"\n",this,ky));
-  GASSERT(0<=i && i<fCapacity);
-  GASSERT(hash[i].hash<0);
-  hash[i].hash=h;
-  hash[i].mark=mrk;
-  hash[i].key=Gstrdup(ky);
-  hash[i].data=pdata;
-  fCount++;
-  if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
-  GASSERT(fCount<fCapacity);
-  return pdata;
-  }
+template <class OBJ>  OBJ* GHash<OBJ>::Replace(const char* ky, OBJ* pdata){
+	int p,i,x,h,n;
+	if(!ky){ GError("GHash::replace: NULL key argument.\n"); }
+	GASSERT(fCount<fCapacity);
+	h=GSTR_HASH(ky);
+	GASSERT(0<=h);
+	p=HASH1(h,fCapacity);
+	GASSERT(0<=p && p<fCapacity);
+	x=HASH2(h,fCapacity);
+	GASSERT(1<=x && x<fCapacity);
+	i=-1;
+	n=fCapacity;
+	while(n && hash[p].hash!=-1){
+		if((i==-1)&&(hash[p].hash==-2)) i=p;
+		if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
+			GTRACE(("GHash::replace: %08x: replacing: \"%s\"\n",this,ky));
+			if (FREEDATA) (*fFreeProc)(hash[p].data);
+			hash[p].data=pdata;
+			return hash[p].data;
+		}
+		p=(p+x)%fCapacity;
+		n--;
+	}
+	if(i==-1) i=p;
+	GTRACE(("GHash::replace: %08x: inserting: \"%s\"\n",this,ky));
+	GASSERT(0<=i && i<fCapacity);
+	GASSERT(hash[i].hash<0);
+	hash[i].hash=h;
+	hash[i].key=Gstrdup(ky);
+	hash[i].data=pdata;
+	fCount++;
+	if((100*fCount)>=(MAX_LOAD*fCapacity)) Resize(fCount);
+	GASSERT(fCount<fCapacity);
+	return pdata;
+}
 
 
 // Remove entry
 template <class OBJ> OBJ* GHash<OBJ>::Remove(const char* ky){
-  int p,x,h,n;
-  if(!ky){ GError("GHash::remove: NULL key argument.\n"); }
-  OBJ* removed=NULL;
-  if(0<fCount){
-    h=GSTR_HASH(ky);
-    GASSERT(0<=h);
-    p=HASH1(h,fCapacity);
-    GASSERT(0<=p && p<fCapacity);
-    x=HASH2(h,fCapacity);
-    GASSERT(1<=x && x<fCapacity);
-    GASSERT(fCount<fCapacity);
-    n=fCapacity;
-    while(n && hash[p].hash!=-1){
-      if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
-        GTRACE(("GHash::remove: %08x removing: \"%s\"\n",this,ky));
-        hash[p].hash=-2;
-        hash[p].mark=false;
-        if (hash[p].keyalloc) GFREE((hash[p].key));
-        if (FREEDATA) (*fFreeProc)(hash[p].data);
-            else removed=(OBJ*)hash[p].data;
-        hash[p].key=NULL;
-        hash[p].data=NULL;
-        fCount--;
-        if((100*fCount)<=(MIN_LOAD*fCapacity)) Resize(fCount);
-        GASSERT(fCount<fCapacity);
-        return removed;
-        }
-      p=(p+x)%fCapacity;
-      n--;
-      }
-    }
-  return removed;
-  }
+	int p,x,h,n;
+	if(!ky){ GError("GHash::remove: NULL key argument.\n"); }
+	OBJ* removed=NULL;
+	if(0<fCount){
+		h=GSTR_HASH(ky);
+		GASSERT(0<=h);
+		p=HASH1(h,fCapacity);
+		GASSERT(0<=p && p<fCapacity);
+		x=HASH2(h,fCapacity);
+		GASSERT(1<=x && x<fCapacity);
+		GASSERT(fCount<fCapacity);
+		n=fCapacity;
+		while(n && hash[p].hash!=-1){
+			if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
+				GTRACE(("GHash::remove: %08x removing: \"%s\"\n",this,ky));
+				hash[p].hash=-2;
+				if (hash[p].keyalloc) GFREE((hash[p].key));
+				if (FREEDATA) (*fFreeProc)(hash[p].data);
+				else removed=(OBJ*)hash[p].data;
+				hash[p].key=NULL;
+				hash[p].data=NULL;
+				fCount--;
+				if((100*fCount)<=(MIN_LOAD*fCapacity)) Resize(fCount);
+				GASSERT(fCount<fCapacity);
+				return removed;
+			}
+			p=(p+x)%fCapacity;
+			n--;
+		}
+	}
+	return removed;
+}
 
 
 // Find entry
 template <class OBJ> bool GHash<OBJ>::hasKey(const char* ky) {
-  int p,x,h,n;
-  if(!ky){ GError("GHash::find: NULL key argument.\n"); }
-  if(0<fCount){
-    h=GSTR_HASH(ky);
-    GASSERT(0<=h);
-    p=HASH1(h,fCapacity);
-    GASSERT(0<=p && p<fCapacity);
-    x=HASH2(h,fCapacity);
-    GASSERT(1<=x && x<fCapacity);
-    GASSERT(fCount<fCapacity);
-    n=fCapacity;
-    while(n && hash[p].hash!=-1){
-      if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
-        return true;
-        }
-      p=(p+x)%fCapacity;
-      n--;
-      }
-    }
-  return false;
+	int p,x,h,n;
+	if(!ky){ GError("GHash::find: NULL key argument.\n"); }
+	if(0<fCount){
+		h=GSTR_HASH(ky);
+		GASSERT(0<=h);
+		p=HASH1(h,fCapacity);
+		GASSERT(0<=p && p<fCapacity);
+		x=HASH2(h,fCapacity);
+		GASSERT(1<=x && x<fCapacity);
+		GASSERT(fCount<fCapacity);
+		n=fCapacity;
+		while(n && hash[p].hash!=-1){
+			if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
+				return true;
+			}
+			p=(p+x)%fCapacity;
+			n--;
+		}
+	}
+	return false;
 }
 
 
 template <class OBJ> OBJ* GHash<OBJ>::Find(const char* ky, char** keyptr){
-  int p,x,h,n;
-  if(!ky){ GError("GHash::find: NULL key argument.\n"); }
-  if (fCount==0) return NULL;
-  h=GSTR_HASH(ky);
-  GASSERT(0<=h);
-  p=HASH1(h,fCapacity);
-  GASSERT(0<=p && p<fCapacity);
-  x=HASH2(h,fCapacity);
-  GASSERT(1<=x && x<fCapacity);
-  GASSERT(fCount<fCapacity);
-  n=fCapacity;
+	int p,x,h,n;
+	if(!ky){ GError("GHash::find: NULL key argument.\n"); }
+	if (fCount==0) return NULL;
+	h=GSTR_HASH(ky);
+	GASSERT(0<=h);
+	p=HASH1(h,fCapacity);
+	GASSERT(0<=p && p<fCapacity);
+	x=HASH2(h,fCapacity);
+	GASSERT(1<=x && x<fCapacity);
+	GASSERT(fCount<fCapacity);
+	n=fCapacity;
 #ifdef HASH_DBG_PRINT
-  int iterations=0;
-  int init_p=p;
-  int init_x=x;
+	int iterations=0;
+	int init_p=p;
+	int init_x=x;
 #endif
-  while(n && hash[p].hash!=-1){
-      if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
-        if (keyptr!=NULL) *keyptr = hash[p].key;
+	while(n && hash[p].hash!=-1){
+		if(hash[p].hash==h && strcmp(hash[p].key,ky)==0){
+			if (keyptr!=NULL) *keyptr = hash[p].key;
 #ifdef HASH_DBG_PRINT
-         GMessage("Found \t%s\t%d,%d,%d\t%d\t%d\t%d\n",
-             ky, h,init_p,init_x, iterations,  fCount, fCapacity);
+			GMessage("Found \t%s\t%d,%d,%d\t%d\t%d\t%d\n",
+					ky, h,init_p,init_x, iterations,  fCount, fCapacity);
 #endif
-        return (OBJ*)hash[p].data;
-        }
-      p=(p+x)%fCapacity;
-      n--;
+			return (OBJ*)hash[p].data;
+		}
+		p=(p+x)%fCapacity;
+		n--;
 #ifdef HASH_DBG_PRINT
-      ++iterations;
+		++iterations;
 #endif
-  }
+	}
 #ifdef HASH_DBG_PRINT
-   GMessage("Nfound\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
-       ky, h,init_p,init_x, iterations,  fCount, fCapacity);
+	GMessage("Nfound\t%s\t%d,%d,%d\t%d\t%d\t%d\n",
+			ky, h,init_p,init_x, iterations,  fCount, fCapacity);
 #endif
-  return NULL;
- }
+	return NULL;
+}
 
 template <class OBJ> void GHash<OBJ>::startIterate() {// initialize a key iterator; call
- fCurrentEntry=0;
+	fCurrentEntry=0;
 }
 
 template <class OBJ> char* GHash<OBJ>::NextKey() {
- int pos=fCurrentEntry;
- while (pos<fCapacity && hash[pos].hash<0) pos++;
- if (pos==fCapacity) {
-                 fCurrentEntry=fCapacity;
-                 return NULL;
-                 }
-              else {
-                 fCurrentEntry=pos+1;
-                 return hash[pos].key;
-                 }
+	int pos=fCurrentEntry;
+	while (pos<fCapacity && hash[pos].hash<0) pos++;
+	if (pos==fCapacity) {
+		fCurrentEntry=fCapacity;
+		return NULL;
+	}
+	else {
+		fCurrentEntry=pos+1;
+		return hash[pos].key;
+	}
 }
 
 template <class OBJ> OBJ* GHash<OBJ>::NextData() {
- int pos=fCurrentEntry;
- while (pos<fCapacity && hash[pos].hash<0) pos++;
- if (pos==fCapacity) {
-                 fCurrentEntry=fCapacity;
-                 return NULL;
-                 }
-              else {
-                 fCurrentEntry=pos+1;
-                 return (OBJ*)hash[pos].data;
-                 }
+	int pos=fCurrentEntry;
+	while (pos<fCapacity && hash[pos].hash<0) pos++;
+	if (pos==fCapacity) {
+		fCurrentEntry=fCapacity;
+		return NULL;
+	}
+	else {
+		fCurrentEntry=pos+1;
+		return (OBJ*)hash[pos].data;
+	}
 
 }
 
 template <class OBJ> OBJ* GHash<OBJ>::NextData(char* &nextkey) {
- int pos=fCurrentEntry;
- while (pos<fCapacity && hash[pos].hash<0) pos++;
- if (pos==fCapacity) {
-                 fCurrentEntry=fCapacity;
-                 nextkey=NULL;
-                 return NULL;
-                 }
-              else {
-                 fCurrentEntry=pos+1;
-                 nextkey=hash[pos].key;
-                 return (OBJ*)hash[pos].data;
-                 }
+	int pos=fCurrentEntry;
+	while (pos<fCapacity && hash[pos].hash<0) pos++;
+	if (pos==fCapacity) {
+		fCurrentEntry=fCapacity;
+		nextkey=NULL;
+		return NULL;
+	}
+	else {
+		fCurrentEntry=pos+1;
+		nextkey=hash[pos].key;
+		return (OBJ*)hash[pos].data;
+	}
 
 }
 
 
 // Get first non-empty entry
 template <class OBJ> int GHash<OBJ>::First() const {
-  int pos=0;
-  while(pos<fCapacity){ if(0<=hash[pos].hash) break; pos++; }
-  GASSERT(fCapacity<=pos || 0<=hash[pos].hash);
-  return pos;
-  }
+	int pos=0;
+	while(pos<fCapacity){ if(0<=hash[pos].hash) break; pos++; }
+	GASSERT(fCapacity<=pos || 0<=hash[pos].hash);
+	return pos;
+}
 
 // Get last non-empty entry
 template <class OBJ> int GHash<OBJ>::Last() const {
-  int pos=fCapacity-1;
-  while(0<=pos){ if(0<=hash[pos].hash) break; pos--; }
-  GASSERT(pos<0 || 0<=hash[pos].hash);
-  return pos;
-  }
+	int pos=fCapacity-1;
+	while(0<=pos){ if(0<=hash[pos].hash) break; pos--; }
+	GASSERT(pos<0 || 0<=hash[pos].hash);
+	return pos;
+}
 
 
 // Find next valid entry
 template <class OBJ> int GHash<OBJ>::Next(int pos) const {
-  GASSERT(0<=pos && pos<fCapacity);
-  while(++pos <= fCapacity-1){ if(0<=hash[pos].hash) break; }
-  GASSERT(fCapacity<=pos || 0<=hash[pos].hash);
-  return pos;
-  }
+	GASSERT(0<=pos && pos<fCapacity);
+	while(++pos <= fCapacity-1){ if(0<=hash[pos].hash) break; }
+	GASSERT(fCapacity<=pos || 0<=hash[pos].hash);
+	return pos;
+}
 
 
 // Find previous valid entry
 template <class OBJ> int GHash<OBJ>::Prev(int pos) const {
-  GASSERT(0<=pos && pos<fCapacity);
-  while(--pos >= 0){ if(0<=hash[pos].hash) break; }
-  GASSERT(pos<0 || 0<=hash[pos].hash);
-  return pos;
-  }
+	GASSERT(0<=pos && pos<fCapacity);
+	while(--pos >= 0){ if(0<=hash[pos].hash) break; }
+	GASSERT(pos<0 || 0<=hash[pos].hash);
+	return pos;
+}
 
 
 // Remove all
 template <class OBJ> void GHash<OBJ>::Clear(){
-  int i;
-  for(i=0; i<fCapacity; i++){
-    if(hash[i].hash>=0){
-      if (hash[i].keyalloc) GFREE((hash[i].key));
-      if (FREEDATA)
-            (*fFreeProc)(hash[i].data);
-      }
-    }
-  GFREE(hash);
-  GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);
-  //reinitialize it
-  for (i=0; i<DEF_HASH_SIZE; i++)
-         hash[i].hash=-1; //this will be an indicator for 'empty' entries
-  fCapacity=DEF_HASH_SIZE;
-  fCount=0;
-  }
-
-
-// Save data
-/*
-void GHash::Save(Stream& store) const {
-  Object::save(store);
-  store << fCapacity;
-  store << fCount;
-  for(int i=0; i<fCapacity; i++){
-    store << hash[i].hash;
-    if(hash[i].hash>=0){
-      uint len=strlen(hash[i].key);
-      store << len;
-      store << hash[i].mark;
-      store.save(hash[i].key,len);
-      }
-    }
-  }
-
-
-// Load data
-void GHash::Load(Stream& store){
-  Object::load(store);
-  store >> fCapacity;
-  store >> fCount;
-  for(int i=0; i<fCapacity; i++){
-    store >> hash[i].hash;
-    if(hash[i].hash>=0){
-      uint len;
-      store >> len;
-      store >> hash[i].mark;
-      GMALLOC(hash[i].key,len+1);
-      store.load(hash[i].key,len);
-      hash[i].key[len]='\0';
-      }
-    }
-  }
-*/
+	int i;
+	for(i=0; i<fCapacity; i++){
+		if(hash[i].hash>=0){
+			if (hash[i].keyalloc) GFREE((hash[i].key));
+			if (FREEDATA)
+				(*fFreeProc)(hash[i].data);
+		}
+	}
+	GFREE(hash);
+	GMALLOC(hash, sizeof(GHashEntry)*DEF_HASH_SIZE);
+	//reinitialize it
+	for (i=0; i<DEF_HASH_SIZE; i++)
+		hash[i].hash=-1; //this will be an indicator for 'empty' entries
+	fCapacity=DEF_HASH_SIZE;
+	fCount=0;
+}
 
 // Destroy table
 template <class OBJ> GHash<OBJ>::~GHash(){
-  for(int i=0; i<fCapacity; i++){
-    if(hash[i].hash>=0){
-      if (hash[i].keyalloc) GFREE((hash[i].key));
-      if (FREEDATA) (*fFreeProc)(hash[i].data);
-      }
-    }
-  GFREE(hash);
-  }
+	for(int i=0; i<fCapacity; i++){
+		if(hash[i].hash>=0){
+			if (hash[i].keyalloc) GFREE((hash[i].key));
+			if (FREEDATA) (*fFreeProc)(hash[i].data);
+		}
+	}
+	GFREE(hash);
+}
 
 class GStrSet:public GHash<int> {
 protected:


=====================================
GIntHash.hh
=====================================
@@ -228,7 +228,7 @@ public:
 };
 
 
-// from code.google.com/p/smhasher/wiki/MurmurHash3
+// -- from code.google.com/p/smhasher/wiki/MurmurHash3
 inline uint32_t integerHash(uint32_t h)
 {
 	h ^= h >> 16;
@@ -239,15 +239,19 @@ inline uint32_t integerHash(uint32_t h)
 	return h;
 }
 
-// from code.google.com/p/smhasher/wiki/MurmurHash3
-inline uint64_t integerHash(uint64_t k)
-{
-	k ^= k >> 33;
-	k *= 0xff51afd7ed558ccd;
-	k ^= k >> 33;
-	k *= 0xc4ceb9fe1a85ec53;
-	k ^= k >> 33;
-	return k;
+inline int32_t int_hashfunc_Wang(int32_t key) {
+ key += ~(key << 15);
+ key ^=  (key >> 10);
+ key +=  (key << 3);
+ key ^=  (key >> 6);
+ key += ~(key << 11);
+ key ^=  (key >> 16);
+ return key;
+}
+
+// -- from Heng Li's khash.h:
+inline uint32_t int64_hashfunc(uint64_t k) {
+	return (uint32_t)(k>>33^k^k<<11);
 }
 
 #define GIHASH_FIRST_CELL(hash) (m_cells + ((hash) & (m_arraySize - 1)))


=====================================
GResUsage.cpp
=====================================
@@ -0,0 +1,278 @@
+#include "GResUsage.h"
+
+#if defined(__APPLE__) && defined(__MACH__)
+  #include <AvailabilityMacros.h>
+  #include <sys/resource.h>
+  #include <mach/mach.h>
+  #include <mach/task_info.h>
+
+  #ifndef MAC_OS_X_VERSION_10_12
+    #define MAC_OS_X_VERSION_10_12 101200
+  #endif
+  #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
+    #define G_gettime(s) clock_gettime(CLOCK_MONOTONIC, &s);
+  #else
+    #include <mach/mach_time.h>
+	#define MACHGT_NANO (+1.0E-9)
+	#define MACHGT_GIGA UINT64_C(1000000000)
+	void mach_gettime( struct timespec* t) {
+	  // be more careful in a multithreaded environement
+	  static double machgt_timebase = 0.0;
+	  static uint64_t machgt_timestart = 0;
+	  if (!machgt_timestart) {
+		mach_timebase_info_data_t tb;
+		tb.numer=0;tb.denom=0;
+		mach_timebase_info(&tb);
+		machgt_timebase = tb.numer;
+		machgt_timebase /= tb.denom;
+		machgt_timestart = mach_absolute_time();
+	  }
+	 ;
+	  double diff = (mach_absolute_time() - machgt_timestart) * machgt_timebase;
+	  t->tv_sec = diff * MACHGT_NANO;
+	  t->tv_nsec = diff - (t->tv_sec * MACHGT_GIGA);
+	}
+    #define G_gettime(s) mach_gettime(&s)
+  #endif
+#else
+ #ifdef _WIN32
+    //Windows implementation:
+    #include <psapi.h>
+	LARGE_INTEGER
+	getFILETIMEoffset() {
+	    SYSTEMTIME s;
+	    FILETIME f;
+	    LARGE_INTEGER t;
+	    s.wYear = 1970;  s.wMonth = 1; s.wDay = 1;
+	    s.wHour = 0; s.wMinute = 0; s.wSecond = 0;
+	    s.wMilliseconds = 0;
+	    SystemTimeToFileTime(&s, &f);
+	    t.QuadPart = f.dwHighDateTime;
+	    t.QuadPart <<= 32;
+	    t.QuadPart |= f.dwLowDateTime;
+	    return (t);
+	}
+
+	static void	usage_to_timeval(FILETIME *ft, struct timeval *tv) {
+	    ULARGE_INTEGER time;
+	    time.LowPart = ft->dwLowDateTime;
+	    time.HighPart = ft->dwHighDateTime;
+
+	    tv->tv_sec = time.QuadPart / 10000000;
+	    tv->tv_usec = (time.QuadPart % 10000000) / 10;
+	}
+
+    //implementation of getrusage for Windows
+	int	getrusage(int who, rusage *usage) {
+	    FILETIME creation_time, exit_time, kernel_time, user_time;
+	    PROCESS_MEMORY_COUNTERS pmc;
+
+	    memset(usage, 0, sizeof(rusage));
+
+	    if (who == RUSAGE_SELF) {
+	        if (!GetProcessTimes(GetCurrentProcess(), &creation_time, &exit_time,
+	                             &kernel_time, &user_time)) {
+	            GMessage("Error: GetProcessTimes() failed!\n");
+	            return -1;
+	        }
+
+	        if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
+	            GMessage("Error: GetProcessMemoryInfo() failed!\n");
+	            return -1;
+	        }
+
+	        usage_to_timeval(&kernel_time, &usage->ru_stime);
+	        usage_to_timeval(&user_time, &usage->ru_utime);
+	        usage->ru_majflt = pmc.PageFaultCount;
+	        usage->ru_maxrss = pmc.PeakWorkingSetSize / 1024;
+	        return 0;
+	    } else if (who == RUSAGE_THREAD) {
+	        if (!GetThreadTimes(GetCurrentThread(), &creation_time, &exit_time,
+	                            &kernel_time, &user_time)) {
+	            GMessage("Error: GetThreadTimes() failed!\n");
+	            return -1;
+	        }
+	        usage_to_timeval(&kernel_time, &usage->ru_stime);
+	        usage_to_timeval(&user_time, &usage->ru_utime);
+	        return 0;
+	    } else {
+	        return -1;
+	    }
+	}
+
+
+	void win_gettime(struct timespec* ts) {
+	    LARGE_INTEGER           t;
+	    FILETIME            f;
+	    double                  microseconds;
+	    static LARGE_INTEGER    offset;
+	    static double           frequencyToMicroseconds;
+	    static int              initialized = 0;
+	    static BOOL             usePerformanceCounter = 0;
+
+	    if (!initialized) {
+	        LARGE_INTEGER performanceFrequency;
+	        initialized = 1;
+	        usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
+	        if (usePerformanceCounter) {
+	            QueryPerformanceCounter(&offset);
+	            frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
+	        } else {
+	            offset = getFILETIMEoffset();
+	            frequencyToMicroseconds = 10.;
+	        }
+	    }
+	    if (usePerformanceCounter) QueryPerformanceCounter(&t);
+	    else {
+	        GetSystemTimeAsFileTime(&f);
+	        t.QuadPart = f.dwHighDateTime;
+	        t.QuadPart <<= 32;
+	        t.QuadPart |= f.dwLowDateTime;
+	    }
+
+	    t.QuadPart -= offset.QuadPart;
+	    microseconds = (double)t.QuadPart / frequencyToMicroseconds;
+	    t.QuadPart = microseconds;
+	    ts->tv_sec = t.QuadPart / 1000000;
+	    ts->tv_nsec = (t.QuadPart % 1000000)*1000;
+	}
+   #define G_gettime(s) win_gettime(&s)
+ #else  //assume Linux compatible
+   #define G_gettime(s) clock_gettime(CLOCK_MONOTONIC, &s)
+ #endif
+#endif
+
+// Returns the peak (maximum so far) resident set size (physical
+// memory use) measured in bytes
+size_t getPeakMemUse() {
+#if defined(_WIN32)
+	// -- Windows
+	PROCESS_MEMORY_COUNTERS info;
+	GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
+	return (size_t)info.PeakWorkingSetSize/1024;
+#else // defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
+	// asssume BSD, Linux, or OSX
+	struct rusage rusage;
+	getrusage( RUSAGE_SELF, &rusage );
+ #if defined(__APPLE__) && defined(__MACH__)
+	return (size_t)rusage.ru_maxrss/1024;
+ #else
+	return (size_t)(rusage.ru_maxrss);
+ #endif
+#endif
+}
+
+/**
+ * Returns the current resident set size (physical memory use) measured
+ * in bytes, or zero if the value cannot be determined on this OS.
+ */
+size_t getCurrentMemUse() {
+#if defined(_WIN32)
+	// -- Windows
+	PROCESS_MEMORY_COUNTERS info;
+	GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
+	return (size_t)info.WorkingSetSize;
+
+#elif defined(__APPLE__) && defined(__MACH__)
+#if defined MACH_TASK_BASIC_INFO
+	struct mach_task_basic_info info;
+#else
+  struct task_basic_info info;
+  #define MACH_TASK_BASIC_INFO TASK_BASIC_INFO
+  #define MACH_TASK_BASIC_INFO_COUNT TASK_BASIC_INFO_COUNT
+#endif
+
+	mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
+	if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
+		(task_info_t)&info, &infoCount ) != KERN_SUCCESS )
+		return (size_t)0L;		// Can't access?
+	return (size_t)info.resident_size;
+#else
+	//-- assume Linux
+	long progsize = 0L;
+	FILE* fp = NULL;
+	if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
+		return (size_t)0L;		/* Can't open? */
+	//if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
+	if ( fscanf( fp, "%*s%ld", &progsize ) != 1 )
+	{
+		fclose( fp );
+		return (size_t)0L;		/* Can't read? */
+	}
+	fclose( fp );
+	int page_size=sysconf(_SC_PAGESIZE);
+	return ((size_t)progsize * (size_t)page_size)/1024;
+#endif
+}
+
+// get_mem_usage(double &, double &) - takes two doubles by reference,
+// attempts to read the system-dependent data for a process' virtual memory
+// size and resident set size, and return the results in KB.
+//
+// On failure, returns 0.0, 0.0
+void printMemUsage(FILE* fout) {
+  double rs= getCurrentMemUse();
+  rs/=1024;
+  fprintf(fout, "Resident Size: %6.1fMB\n", rs);
+}
+
+double get_usecTime() {
+	struct timespec start_ts;
+	G_gettime(start_ts);
+	return (((double)start_ts.tv_sec)*1000000.0 + ((double)start_ts.tv_nsec)/1000.0);
+}
+
+double GResUsage::start() {
+	started=true;
+	stopped=false;
+	start_mem=getCurrentMemUse();
+	getrusage(RUSAGE_SELF, &start_ru);
+	G_gettime(start_ts);
+	double tm=start_ts.tv_sec*1000000.0 + start_ts.tv_nsec/1000.0;
+	return tm;
+}
+
+double GResUsage::stop() {
+	if (started!=true)
+		GError("Error: calling GResUsage::stop() without starting it first?\n");
+	stopped=true;
+	G_gettime(stop_ts);
+	getrusage(RUSAGE_SELF, &stop_ru);
+	double tm=stop_ts.tv_sec*1000000.0 + stop_ts.tv_nsec/1000.0;
+	stop_mem=getCurrentMemUse();
+	return tm;
+}
+
+#define RUSAGE_STOPCHECK
+
+void GResUsage::stopCheck(const char* s) {
+	if (!started || !stopped)
+      GError("Error: GResUsage::%s() cannot be used before start&stop\n", s);
+}
+
+double GResUsage::elapsed() {
+	stopCheck("elapsed");
+	double st=start_ts.tv_sec*1000000.0 + start_ts.tv_nsec/1000.0;
+	double et=stop_ts.tv_sec*1000000.0 + stop_ts.tv_nsec/1000.0;
+	return (et-st);
+}
+
+double GResUsage::u_elapsed() {
+	stopCheck("u_elapsed");
+	double st=start_ru.ru_utime.tv_sec*1000000.0 + start_ru.ru_utime.tv_usec;
+	double et=stop_ru.ru_utime.tv_sec*1000000.0 + stop_ru.ru_utime.tv_usec;
+	return (et-st);
+}
+
+double GResUsage::s_elapsed() {
+	stopCheck("s_elapsed");
+	double st=start_ru.ru_stime.tv_sec*1000000.0 + start_ru.ru_stime.tv_usec;
+	double et=stop_ru.ru_stime.tv_sec*1000000.0 + stop_ru.ru_stime.tv_usec;
+	return (et-st);
+}
+
+size_t GResUsage::memoryUsed() {
+	stopCheck("memoryUsed");
+	return (stop_mem-start_mem);
+}
+


=====================================
GResUsage.h
=====================================
@@ -0,0 +1,53 @@
+#ifndef _GRESUSAGE_
+#define _GRESUSAGE_
+#include "GBase.h"
+#if defined _WIN32 && ! defined __CYGWIN__
+  #define	RUSAGE_SELF	0		/* calling process */
+  #define	RUSAGE_CHILDREN	-1		/* terminated child processes */
+  #define	RUSAGE_THREAD	1
+
+  struct rusage {
+	struct timeval ru_utime;	/* user time used */
+	struct timeval ru_stime;	/* system time used */
+	long ru_maxrss;
+	long ru_majflt;
+  };
+#else
+ #include <sys/resource.h>
+#endif
+#include <time.h>
+
+// report the memory usage of the current process, rounded to kilobytes
+size_t getCurrentMemUse(); //current memory usage of the program (RSS)
+size_t getPeakMemUse(); //maximum memory usage (RSS) for the program until now
+
+void printMemUsage(FILE* fout=stderr);
+
+double get_usecTime();
+
+class GResUsage {
+  protected:
+	bool started;
+	bool stopped;
+	size_t start_mem;
+	size_t stop_mem;
+	struct rusage start_ru;
+	struct rusage stop_ru;
+	struct timespec start_ts;
+	struct timespec stop_ts;
+	void stopCheck(const char* s);
+  public:
+	GResUsage(bool do_start=false):started(false),
+	   stopped(false), start_mem(0), stop_mem(0) {
+          if (do_start) start();
+	}
+
+	double start(); //returns microseconds time using clock_gettime(CLOCK_MONOTONIC
+	double stop(); //stop the stopwatch, returns the current time in microseconds
+	double elapsed(); //microseconds elapsed between start and stop (wallclock time)
+	double u_elapsed(); //microseconds of user time elapsed
+	double s_elapsed(); //microseconds of system time elapsed
+	size_t memoryUsed(); //memory increase between start and stop in KB (can be negative)
+};
+
+#endif


=====================================
GThreads.cpp
=====================================
@@ -1,6 +1,6 @@
 /*
 Copyright (c) 2010 Marcus Geelnard
-(with minor modifications by Geo Pertea)
+(with minor modifications and naming changes by Geo Pertea)
 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any damages
 arising from the use of this software.


=====================================
GThreads.h
=====================================
@@ -2,16 +2,13 @@
 #define _GTHREADS_
 
 /*
-GThread - multi-platform threads utility class
-This is heavily based on the source code of TinyThread++ 1.0 package
-by Marcus Geelnard (with only minor modifications),
-so all merits for the code go to Marcus, except the bugs which
-were probably introduced by me.
+GThread - multi-platform thread management utility class
+This code is taken from the TinyThread++ 1.0 package
+by Marcus Geelnard (with only very minor alterations and 
+naming changes).
 
-Original Copyright notice below
-*/
-
-/*
+Original Copyright notice follows:
+----
 Copyright (c) 2010 Marcus Geelnard
 
 This software is provided 'as-is', without any express or implied


=====================================
Makefile
=====================================
@@ -95,20 +95,23 @@ endif
 
 
 .PHONY : all
-all:    mdtest
+all:    htest
+#mdtest
 nodebug: all
 release: all
 debug: all
 
-OBJS := GBase.o GStr.o GArgs.o
+OBJS := GBase.o GStr.o GArgs.o GResUsage.o
 
 version: ; @echo "GCC Version is: "$(GCC_MAJOR)":"$(GCC_MINOR)":"$(GCC_SUB)
 	@echo "> GCC Opt. string is: "$(GCC45OPTS)
+htest:  $(OBJS) htest.o GHash.hh
+	${LINKER} ${LDFLAGS} $(GCC45OPTS) $(GCC45OPTMAIN) -o $@ ${filter-out %.a %.so, $^} ${LIBS}
 mdtest: $(OBJS) mdtest.o
 	${LINKER} ${LDFLAGS} $(GCC45OPTS) $(GCC45OPTMAIN) -o $@ ${filter-out %.a %.so, $^} ${LIBS}
 # target for removing all object files
 
 .PHONY : clean
 clean:: 
-	@${RM} $(OBJS) *.o mdtest$(EXE)
+	@${RM} $(OBJS) *.o mdtest$(EXE) htest$(EXE)
 	@${RM} core.*


=====================================
README.md
=====================================
@@ -1,9 +1,8 @@
-## GCLib - Genomic C++/Code Library
-This is an eclectic gathering of (mostly) C++ code which I am using for some of my bioinformatics projects. 
-The main idea is to provide lean code and efficient data structures, trying to avoid too many code 
-dependencies of heavy libraries while minimizing production cycles (and this also implies a decent compile/build time -- 
-I am looking at you, bloated configure scripts and lengthy compile times of Boost code or other heavy C++ template code..).
+## GCLib - Genomic C++ Library
+This is an eclectic collection of basic C++ code (functions, classes, templates) which is shared between a few of my bioinformatics projects. The main idea was to provide a core collection of data structures, trying to avoid unnecessary code dependencies of other heavy libraries, while minimizing build time. 
+
+I had started gathering this code even before the C++ STL had been fully adopted as a cross-platform "standard". Even STL itself seems a bit on the heavy side (and keeps growing) compared to what I need in practice for many of my C++ projects, so often times I prefer to just use these simpler and leaner C++ classes and templates to provide most common data structures needed for my projects.
+
+## Build/Install
+Do not build. Do not install. This is not meant to be built into an object library, it's a simple _source code library_ for other projects to include and link statically into the final executable(s). The makefile included here is just for simple, extemporaneous tests I occasionally perform as new functionality is added to this code collection.
 
-I had started gathering this code even before the C++ STL had been fully adopted as a cross-platform "standard", and because 
-I also think that STL by itself is a bit heavier for most of my C++ needs, I do prefer to use simpler&leaner C++ 
-classes or templates for basic strings, containers, basic algorithms etc.


=====================================
gcdb.cpp
=====================================
@@ -1,14 +1,14 @@
 #include "gcdb.h"
 #include <errno.h>
 
-#ifdef __WIN32__
-/*   m m a p           ===      from imagick sources
+#ifdef _WIN32
+/*   mmap on Windows (from imagick sources)
 %  Method mmap emulates the Unix method of the same name.
 %  The format of the mmap method is:
 %    void *mmap(char *address,size_t length,int protection,
 %      int access,int file,off_t offset)
 */
-void *mmap(char *address,size_t length,int protection,int access,
+void *mmap(char *address, size_t length, int protection, int access,
   int file, off_t offset) {
   void *map;
   HANDLE handle;
@@ -65,7 +65,7 @@ void *mmap(char *address,size_t length,int protection,int access,
 %    > length: The length of the binary large object.
 %
 */
-int munmap(void *map,size_t length) {
+int munmap(void *map, size_t length) {
   if (!UnmapViewOfFile(map))
     return(-1);
   return(0);
@@ -580,7 +580,7 @@ GCdbWrite::GCdbWrite(int afd) {
 }
 
 GCdbWrite::GCdbWrite(char* afname) {
-#ifdef __WIN32__
+#ifdef _WIN32
    fd = open(afname,O_WRONLY | O_TRUNC | O_BINARY | O_CREAT, S_IREAD|S_IWRITE);
 #else
    fd = open(afname,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT, 0664);
@@ -604,7 +604,7 @@ GCdbWrite::GCdbWrite(char* afname) {
 
 GCdbWrite::~GCdbWrite() {
   cdbuf->flush();
-  #ifndef __WIN32__
+  #ifndef _WIN32
    /* NFS silliness  */
    if (fsync(fd) == -1)
       GError("GCdbWrite: Error at fsync() for file '%s'\n",
@@ -828,7 +828,7 @@ GCdbRead::GCdbRead(char* afname):map(NULL) {
   gcvt_endian_setup();
 
   findstart();
-  #ifdef __WIN32__
+  #ifdef _WIN32
     fd = open(afname, O_RDONLY|O_BINARY);
   #else
     fd = open(afname, O_RDONLY);


=====================================
gcdb.h
=====================================
@@ -4,7 +4,7 @@
 #include <stddef.h>
 #include <fcntl.h>
 
-#ifdef __WIN32__
+#ifdef _WIN32
   #define PROT_READ  1
   #define PROT_WRITE  2
   #define PROT_READWRITE  3
@@ -99,9 +99,10 @@ class GCDBuffer {
 //=====================================================
 //-------------     cdb utils       -------------------
 //=====================================================
-#ifndef __WIN32__
+#ifndef _WIN32
  extern int errno;
 #endif
+
 extern int error_intr;
 extern int error_nomem;
 extern int error_proto;


=====================================
gsocket.cpp
=====================================
@@ -1,7 +1,7 @@
 #include "gsocket.h"
 #include <errno.h>             // For errno
 
-#ifdef WIN32
+#ifdef _WIN32
 static bool initialized = false;
 #endif
 
@@ -33,7 +33,7 @@ static void fillAddr(const GStr &address, unsigned short port,
 // GSocket Code
 
 GSocket::GSocket(int type, int protocol) {
-  #ifdef WIN32
+  #ifdef _WIN32
     if (!initialized) {
       WORD wVersionRequested;
       WSADATA wsaData;
@@ -53,7 +53,7 @@ GSocket::GSocket(int type, int protocol) {
 }
 
 GSocket::~GSocket() {
-  #ifdef WIN32
+  #ifdef _WIN32
     ::closesocket(sockDesc);
   #else
     ::close(sockDesc);
@@ -106,7 +106,7 @@ void GSocket::setLocalAddressAndPort(const GStr &localAddress,
 }
 
 void GSocket::cleanUp() {
-  #ifdef WIN32
+  #ifdef _WIN32
     if (WSACleanup() != 0) {
       GSocketErr("WSACleanup() failed");
     }
@@ -125,7 +125,7 @@ unsigned short GSocket::resolveService(const GStr &service,
 
 // GCommSocket Code
 void GCommSocket::setTimeout(int microsecs) {
- #ifdef WIN32
+ #ifdef _WIN32
    DWORD timeout = microsecs;
    setsockopt(sockDesc, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
  #else
@@ -241,7 +241,7 @@ void GUDPSocket::disconnect() {
 
   // Try to disconnect
   if (::connect(sockDesc, (sockaddr *) &nullAddr, sizeof(nullAddr)) < 0) {
-   #ifdef WIN32
+   #ifdef _WIN32
     if (errno != WSAEAFNOSUPPORT) {
    #else
     if (errno != EAFNOSUPPORT) {


=====================================
gsocket.h
=====================================
@@ -3,7 +3,7 @@
 #include "GBase.h"
 #include "GStr.h"
 
-#ifdef WIN32
+#ifdef _WIN32
   #include <winsock.h>         // For socket(), connect(), send(), and recv()
   typedef int socklen_t;
   typedef char raw_type;       // Type used for raw data on this platform


=====================================
gstopwatch.cpp
=====================================
@@ -1,6 +1,6 @@
 #include "gstopwatch.h"
 
-#ifdef __WIN32__
+#ifdef _WIN32
 double GStopWatch::LIToSecs( LARGE_INTEGER & L) {
   return ((double)L.QuadPart /(double)frequency.QuadPart);
 }


=====================================
gstopwatch.h
=====================================
@@ -2,7 +2,7 @@
 #define __GSTOPWATCH_H
 #include "GBase.h"
 
-#ifdef __WIN32__
+#ifdef _WIN32
 typedef struct {
     LARGE_INTEGER start;
     LARGE_INTEGER stop;


=====================================
htest.cpp
=====================================
@@ -0,0 +1,104 @@
+#include "GBase.h"
+#include "GArgs.h"
+#include "GStr.h"
+#include "GVec.hh"
+#include "GHash.hh"
+#include "GResUsage.h"
+
+#define USAGE "Usage:\n\
+  htest textfile.. \n\
+  \n\
+ "
+static void strFreeProc(pointer item) {
+      GFREE(item);
+}
+
+struct HStrData {
+	int cmd; // 0=add, 1=remove, 2=clear
+	GStr str;
+	HStrData(char* s=NULL, int c=0):cmd(c), str(s) { }
+};
+
+int loadStrings(FILE* f, GPVec<HStrData>& strgsuf, GPVec<HStrData>& strgs) {
+  int num=0;
+  GLineReader lr(f);
+  char* line=NULL;
+  while ((line=lr.nextLine())!=NULL) {
+	  int len=strlen(line);
+	  if (len<4) continue;
+	  if (strcmp(line, "HCLR")==0) {
+		  strgs.Add(new HStrData(NULL, 2));
+		  strgsuf.Add(new HStrData(NULL, 2));
+		  continue;
+	  }
+	  if (startsWith(line, "RM ")) {
+	     strgsuf.Add(new HStrData(line+3,1) );
+	     line[len-3]=0;
+	     strgs.Add(new HStrData(line+3,1));
+	     continue;
+	  }
+      strgsuf.Add(new HStrData(line));
+      line[len-3]=0;
+      strgs.Add(new HStrData(line));
+	  num++;
+  } //while line
+  return num;
+}
+
+int main(int argc, char* argv[]) {
+ GPVec<HStrData> strs;
+ GPVec<HStrData> sufstrs;
+ GHash<int> thash;
+ GHash<int> sufthash;
+ strs.setFreeItem(strFreeProc);
+ sufstrs.setFreeItem(strFreeProc);
+ //GArgs args(argc, argv, "hg:c:s:t:o:p:help;genomic-fasta=COV=PID=seq=out=disable-flag;test=");
+ GArgs args(argc, argv, "h");
+ //fprintf(stderr, "Command line was:\n");
+ //args.printCmdLine(stderr);
+ args.printError(USAGE, true);
+ if (args.getOpt('h') || args.getOpt("help")) GMessage(USAGE);
+ int numargs=args.startNonOpt();
+ if (numargs>0) {
+   char* a=NULL;
+   FILE* f=NULL;
+   int total=0;
+   while ((a=args.nextNonOpt())) {
+	   f=fopen(a, "r");
+	   if (f==NULL) GError("Error: could not open file %s !\n", a);
+	   int num=loadStrings(f, sufstrs, strs);
+	   total+=num;
+   }
+   GResUsage swatch;
+   //timing starts here
+   GMessage("----------------- loading no-suffix strings ----------------\n");
+   swatch.start();
+   for (int i=0;i<strs.Count();i++) {
+	  switch (strs[i]->cmd) {
+	    case 0:thash.fAdd(strs[i]->str.chars(), new int(1)); break;
+	    case 1:thash.Remove(strs[i]->str.chars()); break;
+	    case 2:thash.Clear(); break;
+	  }
+   }
+   swatch.stop();
+   GMessage("Elapsed time (microseconds): %.0f us\n", swatch.elapsed());
+   GMessage("                  user time: %.0f us\n", swatch.u_elapsed());
+   GMessage("                system time: %.0f us\n", swatch.s_elapsed());
+   // timing here
+
+   GMessage("----------------- loading suffix strings ----------------\n");
+   swatch.start();
+   for (int i=0;i<sufstrs.Count();i++) {
+		  switch (sufstrs[i]->cmd) {
+		    case 0:sufthash.fAdd(sufstrs[i]->str.chars(), new int(1)); break;
+		    case 1:sufthash.Remove(sufstrs[i]->str.chars()); break;
+		    case 2:sufthash.Clear(); break;
+		  }
+   }
+   swatch.stop();
+   GMessage("Elapsed time (microseconds): %.0f us\n", swatch.elapsed());
+   GMessage("                  user time: %.0f us\n", swatch.u_elapsed());
+   GMessage("                system time: %.0f us\n", swatch.s_elapsed());
+
+ }
+}



View it on GitLab: https://salsa.debian.org/med-team/libgclib/-/commit/34c651e55e08e96c3cdd8a7bc8367d43ab609582

-- 
View it on GitLab: https://salsa.debian.org/med-team/libgclib/-/commit/34c651e55e08e96c3cdd8a7bc8367d43ab609582
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20200601/43e8c8e3/attachment-0001.html>


More information about the debian-med-commit mailing list