Skip to content

Commit 8556211

Browse files
committed
updated gclib
1 parent da3fdbc commit 8556211

9 files changed

Lines changed: 702 additions & 338 deletions

File tree

gclib/GBase.cpp

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -62,61 +62,17 @@ void GMessage(const char* format,...){
6262
_vsnprintf(msg, 4095, format, arguments);
6363
msg[4095]=0;
6464
va_end(arguments);
65-
OutputDebugString(msg);
65+
fflush(stderr);
66+
//OutputDebugString(msg);
6667
#else
6768
va_list arguments;
6869
va_start(arguments,format);
6970
vfprintf(stderr,format,arguments);
7071
va_end(arguments);
72+
fflush(stderr);
7173
#endif
7274
}
7375

74-
/*************** Memory management routines *****************/
75-
// Allocate memory
76-
bool GMalloc(pointer* ptr,unsigned long size){
77-
//GASSERT(ptr);
78-
if (size!=0)
79-
*ptr=malloc(size);
80-
return *ptr!=NULL;
81-
}
82-
83-
// Allocate cleaned memory (0 filled)
84-
bool GCalloc(pointer* ptr,unsigned long size){
85-
GASSERT(ptr);
86-
*ptr=calloc(size,1);
87-
return *ptr!=NULL;
88-
}
89-
90-
// Resize memory
91-
bool GRealloc(pointer* ptr,unsigned long size){
92-
//GASSERT(ptr);
93-
if (size==0) {
94-
GFree(ptr);
95-
return true;
96-
}
97-
if (*ptr==NULL) {//simple malloc
98-
void *p=malloc(size);
99-
if (p != NULL) {
100-
*ptr=p;
101-
return true;
102-
}
103-
else return false;
104-
}//malloc
105-
else {//realloc
106-
void *p=realloc(*ptr,size);
107-
if (p) {
108-
*ptr=p;
109-
return true;
110-
}
111-
return false;
112-
}
113-
}
114-
// Free memory, resets ptr to NULL afterward
115-
void GFree(pointer* ptr){
116-
GASSERT(ptr);
117-
if (*ptr) free(*ptr);
118-
*ptr=NULL;
119-
}
12076

12177
char* Gstrdup(const char* str, int xtracap) {
12278
if (str==NULL) return NULL;
@@ -184,6 +140,44 @@ void Gmktempdir(char* templ) {
184140
#endif
185141
}
186142

143+
char *to_unix_path(char *p) {
144+
if (p != NULL) {
145+
char *pp = p;
146+
while (*pp != 0) {
147+
if (*pp == '\\')
148+
*pp = '/';
149+
++pp;
150+
}
151+
}
152+
return p;
153+
}
154+
155+
char* Grealpath(const char *path, char *resolved_path) {
156+
#ifdef _WIN32
157+
//char *realpath(const char *path, char *resolved_path) {
158+
char *ret = NULL;
159+
if (path == NULL) {
160+
errno = EINVAL;
161+
} else if (access(path, R_OK) == 0) {
162+
ret = resolved_path;
163+
if (ret == NULL) {
164+
GMALLOC(ret, _MAX_PATH);
165+
}
166+
if (ret == NULL) {
167+
errno = ENOMEM;
168+
} else {
169+
ret = _fullpath(ret, path, _MAX_PATH);
170+
if (ret == NULL)
171+
errno = EIO;
172+
}
173+
}
174+
return to_unix_path(ret);
175+
#else
176+
return realpath(path, resolved_path);
177+
#endif
178+
}
179+
180+
187181
int Gmkdir(const char *path, bool recursive, int perms) {
188182
if (path==NULL || path[0]==0) return -1;
189183
mode_t process_mask = umask(0); //is this really needed?

gclib/GBase.h

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#ifndef G_BASE_DEFINED
22
#define G_BASE_DEFINED
3-
#define GCLIB_VERSION "0.12.6"
3+
#define GCLIB_VERSION "0.12.7"
44

55
#ifdef HAVE_CONFIG_H
66
#include "config.h"
@@ -165,6 +165,11 @@ typedef int GCompareProc(const pointer item1, const pointer item2);
165165
typedef long GFStoreProc(const pointer item1, FILE* fstorage); //for serialization
166166
typedef pointer GFLoadProc(FILE* fstorage); //for deserialization
167167

168+
void GError(const char* format,...); // Error routine (aborts program)
169+
void GMessage(const char* format,...);// Log message to stderr
170+
// Assert failed routine:- usually not called directly but through GASSERT
171+
void GAssert(const char* expression, const char* filename, unsigned int lineno);
172+
168173
typedef void GFreeProc(pointer item); //usually just delete,
169174
//but may also support structures with embedded dynamic members
170175

@@ -189,9 +194,11 @@ inline int iround(double x) {
189194
return (int)floor(x + 0.5);
190195
}
191196

197+
char* Grealpath(const char *path, char *resolved_path);
198+
192199
int Gmkdir(const char *path, bool recursive=true, int perms = (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));
193-
void Gmktempdir(char* templ);
194200

201+
void Gmktempdir(char* templ);
195202

196203
bool haveStdInput(); //if stdin is from a pipe or redirection
197204

@@ -232,21 +239,52 @@ template<class T>
232239
std::is_same<char *, typename std::decay<T>::type>::value
233240
> {};
234241

235-
/**************** Memory management ***************************/
236-
237-
bool GMalloc(pointer* ptr, unsigned long size); // Allocate memory
238-
bool GCalloc(pointer* ptr, unsigned long size); // Allocate and initialize memory
239-
bool GRealloc(pointer* ptr,unsigned long size); // Resize memory
240242

241-
void GFree(pointer* ptr); // Free memory, resets ptr to NULL
242-
243-
//int saprintf(char **retp, const char *fmt, ...);
244-
245-
void GError(const char* format,...); // Error routine (aborts program)
246-
void GMessage(const char* format,...);// Log message to stderr
247-
// Assert failed routine:- usually not called directly but through GASSERT
248-
void GAssert(const char* expression, const char* filename, unsigned int lineno);
249243

244+
inline void GFree(pointer* ptr){
245+
GASSERT(ptr);
246+
if (*ptr) free(*ptr);
247+
*ptr=NULL;
248+
}
249+
250+
inline bool GMalloc(pointer* ptr,unsigned long size){
251+
//GASSERT(ptr);
252+
if (size!=0)
253+
*ptr=malloc(size);
254+
return *ptr!=NULL;
255+
}
256+
257+
// Allocate 0-filled memory
258+
inline bool GCalloc(pointer* ptr,unsigned long size){
259+
GASSERT(ptr);
260+
*ptr=calloc(size,1);
261+
return *ptr!=NULL;
262+
}
263+
264+
// Resize memory
265+
inline bool GRealloc(pointer* ptr,unsigned long size){
266+
//GASSERT(ptr);
267+
if (size==0) {
268+
GFree(ptr);
269+
return true;
270+
}
271+
if (*ptr==NULL) {//simple malloc
272+
void *p=malloc(size);
273+
if (p != NULL) {
274+
*ptr=p;
275+
return true;
276+
}
277+
else return false;
278+
}//malloc
279+
else {//realloc
280+
void *p=realloc(*ptr,size);
281+
if (p) {
282+
*ptr=p;
283+
return true;
284+
}
285+
return false;
286+
}
287+
}
250288

251289
template<class T> T* GDupAlloc(T& data) {
252290
T* tmp=NULL;
@@ -283,7 +321,6 @@ char* strupper(char * str);
283321
void* Gmemscan(void *mem, unsigned int len,
284322
void *part, unsigned int partlen);
285323

286-
287324
FILE* Gfopen(const char *path, char *mode=NULL);
288325

289326
// test if a char is in a string:
@@ -441,9 +478,6 @@ struct GRangeParser: GSeg {
441478
}
442479
};
443480

444-
445-
446-
447481
//basic dynamic array template for primitive types
448482
//which can only grow (reallocate) as needed
449483

gclib/GHashMap.hh

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#define XXH_INLINE_ALL 1
1313
#include "xxhash.h"
14+
#include "wyhash.h"
1415

1516
template <typename K> struct GHashKey_xxHash32 { //K generic (class, primitive, pointer except const char* )
1617
//template <typename T=K> inline typename std::enable_if< std::is_trivial<T>::value, uint32_t>::type
@@ -40,6 +41,21 @@ template <> struct GHashKey_xxHash<const char*> {
4041
}
4142
};
4243

44+
45+
template <typename K> struct GHashKey_wyHash { //K generic (class, primitive, pointer except const char* )
46+
//template <typename T=K> inline typename std::enable_if< std::is_trivial<T>::value, uint32_t>::type
47+
uint64_t operator()(const K& s) const { //only works for trivial types!
48+
static_assert(std::is_trivial<K>::value, "Error: cannot use this for non-trivial types!\n");
49+
return wyhash((const void *) &s, sizeof(K), 0, _wyp);
50+
}
51+
};
52+
53+
template <> struct GHashKey_wyHash<const char*> {
54+
inline uint32_t operator()(const char* s) const {
55+
return wyhash(s, strlen(s), 0, _wyp);
56+
}
57+
};
58+
4359
template <typename K> struct GHashKey_Eq { //K is a type having the == operator defined
4460
inline bool operator()(const K& x, const K& y) const {
4561
return (x == y); //requires == operator to be defined for K
@@ -52,8 +68,9 @@ template <> struct GHashKey_Eq<const char*> {
5268
}
5369
};
5470

55-
//GHashSet is never making a deep copy of the char* key, it only stores the pointer
56-
template <typename K=const char*, class Hash=GHashKey_xxHash<K>, class Eq=GHashKey_Eq<K>, typename khInt_t=uint64_t >
71+
// GHashSet<KType> never makes a deep copy of a char* key, it only stores the pointer
72+
// - for pointer keys like char*, key allocation must be managed separately (and should always survive the GHashSet)
73+
template <typename K=const char*, class Hash=GHashKey_wyHash<K>, class Eq=GHashKey_Eq<K>, typename khInt_t=uint64_t >
5774
class GHashSet: public std::conditional< is_char_ptr<K>::value,
5875
klib::KHashSetCached< K, Hash, Eq, khInt_t >,
5976
klib::KHashSet< K, Hash, Eq, khInt_t > >::type {
@@ -125,9 +142,9 @@ public:
125142

126143
};
127144

128-
//GStrSet always allocates a copy of each added string;
129-
// if you don't want that (keys are shared), just use GHashSet<const char*> instead
130-
template <class Hash=GHashKey_xxHash<const char*>, class Eq=GHashKey_Eq<const char*>, typename khInt_t=uint64_t>
145+
// GStrSet always allocates a new copy of each added string;
146+
// if you don't want that, just use GHashSet<const char*> instead and manage the key allocation separately
147+
template <class Hash=GHashKey_wyHash<const char*>, class Eq=GHashKey_Eq<const char*>, typename khInt_t=uint64_t>
131148
class GStrSet: public GHashSet<const char*, Hash, Eq, khInt_t> {
132149
protected:
133150
const char* lastKey=NULL;
@@ -183,9 +200,12 @@ template <class Hash=GHashKey_xxHash<const char*>, class Eq=GHashKey_Eq<const ch
183200

184201
};
185202

186-
//generic hash map where keys and values can be of any type
187-
//Warning: keys are always copied (shared), including const char* keys -- no deep copy!
188-
template <class K, class V, class Hash=GHashKey_xxHash<K>, class Eq=GHashKey_Eq<K>, typename khInt_t=uint64_t>
203+
// Generic hash map where keys and values can be of any type
204+
// Note: keys are always copied (shared) as simple value, there is no deep copy/allocation for pointers
205+
// so pointer keys must me managed separately
206+
// Note: pointer values are automatically deallocated on container destruction by default,
207+
// use GHashMap(false) to disable that when V is a pointer
208+
template <class K, class V, class Hash=GHashKey_wyHash<K>, class Eq=GHashKey_Eq<K>, typename khInt_t=uint64_t>
189209
class GHashMap:public std::conditional< is_char_ptr<K>::value,
190210
klib::KHashMapCached< K, V, Hash, Eq, khInt_t>,
191211
klib::KHashMap< K, V, Hash, Eq, khInt_t> >::type {
@@ -227,7 +247,6 @@ public:
227247
return -1;
228248
}
229249

230-
231250
template <typename T=V> inline
232251
typename std::enable_if< std::is_pointer<T>::value, void>::type
233252
Clear() {
@@ -258,7 +277,6 @@ public:
258277
}
259278

260279
// -- these can be shared with GHash:
261-
262280
GHashMap(bool doFree=std::is_pointer<V>::value):freeItems(doFree) {
263281
static_assert(std::is_trivial<K>::value,
264282
"Error: cannot use this for non-trivial types!\n");
@@ -361,13 +379,14 @@ public:
361379
return val;
362380
}
363381

364-
365-
366382
inline uint32_t Count() { return this->count; }
367383

368384
};
369385

370-
template <class V, class Hash=GHashKey_xxHash<const char*>, class Eq=GHashKey_Eq<const char*>, typename khInt_t=uint64_t >
386+
// GHash<VType>(doFree=true) -- basic string hashmap
387+
// Note: this hash map always makes a copy of the string key which can be costly
388+
// use GHashMap<const char*, VTYPE> for a faster alternative
389+
template <class V, class Hash=GHashKey_wyHash<const char*>, class Eq=GHashKey_Eq<const char*>, typename khInt_t=uint64_t >
371390
class GHash:public GHashMap<const char*, V, Hash, Eq, khInt_t> {
372391
protected:
373392
const char* lastKey=NULL;

0 commit comments

Comments
 (0)