--- deliantra/server/include/shstr.h 2006/08/31 17:54:14 1.4 +++ deliantra/server/include/shstr.h 2006/09/03 00:18:41 1.5 @@ -1,101 +1,87 @@ #ifndef SHSTR_H__ #define SHSTR_H__ -//// OLD STUFF - -/* The size of the shared strings hashtable. This must be smaller than - * 32767, but 947 ought to be plenty enough. - */ -#define TABLESIZE 4133 - -/* This specifies how many characters the hashing routine should look at. - * You may actually save CPU by increasing this number if the typical string - * is large. - */ -#ifndef MAXSTRING -#define MAXSTRING 20 -#endif - -/* In the unlikely occurence that 16383 references to a string are too - * few, you can modify the below type to something bigger. - * (The top bit of "refcount" is used to signify that "u.array" points - * at the array entry.) - */ -#define REFCOUNT_TYPE int - -/* The offsetof macro is part of ANSI C, but many compilers lack it, for - * example "gcc -ansi" - */ -#if !defined (offsetof) -#define offsetof(type, member) (int)&(((type *)0)->member) -#endif - -/* SS(string) will return the address of the shared_string struct which - * contains "string". - */ -#define SS(x) ((shared_string *) ((x) - offsetof(shared_string, string))) - -#define SS_STATISTICS - -#define SS_DUMP_TABLE 1 -#define SS_DUMP_TOTALS 2 - -#ifdef SS_STATISTICS -static struct statistics { - int calls; - int hashed; - int strcmps; - int search; - int linked; -} add_stats, add_ref_stats, free_stats, find_stats, hash_stats; -#define GATHER(n) (++n) -#else /* !SS_STATISTICS */ -#define GATHER(n) -#endif /* SS_STATISTICS */ - -#define TOPBIT ((unsigned REFCOUNT_TYPE) 1 << (sizeof(REFCOUNT_TYPE) * CHAR_BIT - 1)) - -#define PADDING ((2 * sizeof(long) - sizeof(REFCOUNT_TYPE)) % sizeof(long)) + 1 - -typedef struct _shared_string { - union { - struct _shared_string **array; - struct _shared_string *previous; - } u; - struct _shared_string *next; - /* The top bit of "refcount" is used to signify that "u.array" points - * at the array entry. - */ - unsigned REFCOUNT_TYPE refcount; - /* Padding will be unused memory, since we can't know how large - * the padding when allocating memory. We assume here that - * sizeof(long) is a good boundary. - */ - char string[PADDING]; -} shared_string; - -extern void init_hash_table(void); -extern const char *add_string(const char *str); -extern const char *add_refcount(const char *str); -extern int query_refcount(const char *str); -extern const char *find_string(const char *str); -extern void free_string(const char *str); -extern void ss_dump_statistics(void); -extern const char *ss_dump_table(int what); extern int buf_overflow(const char *buf1, const char *buf2, int bufsize); -//// NEW STUFF - -#if 0 struct shstr { const char *s; - operator const char *() const { return s; }; - shstr &operator =(const char *str) { s = str; }; + + int &refcnt () + { + return *((int *)s - 1); + } + + static const char *find (const char *s); + static const char *intern (const char *s); + + static void gc (); // garbage collect a few strings + + // this is used for informational messages and the like I/O + const char *operator &() const { return s ? s : ""; } + + const char &operator [](int i) { return s[i]; } + operator const char *() const { return s; } + + int length () const + { + return s ? *((int *)s - 2) : 0; + } + + shstr () + : s (0) + { + } + + shstr (shstr &sh) + : s (sh.s) + { + if (s) ++refcnt (); + } + + explicit shstr (const char *s) + : s (intern (s)) + { + if (s) ++refcnt (); + } + + ~shstr () + { + if (s) --refcnt (); + } + + const shstr &operator =(const shstr &sh) + { + if (s) --refcnt (); + s = sh.s; + if (s) ++refcnt (); + + return *this; + } + + const shstr &operator =(const char *str) + { + if (s) --refcnt (); + s = intern (str); + + return *this; + } }; -#else -typedef const char *shstr; -#endif + +inline int strlen (const shstr &sh) +{ + return sh.length (); +} + +inline bool operator ==(const shstr &a, const shstr &b) +{ + return a.s == b.s; +} + +inline bool operator !=(const shstr &a, const shstr &b) +{ + return !(a == b); +} #endif