#ifndef SHSTR_H__ #define SHSTR_H__ #include "util.h" extern int buf_overflow (const char *buf1, const char *buf2, int bufsize); struct shstr { static const char *null; const char *s; static int &refcnt (const char *s) { return *((int *)s - 1); } static int &length (const char *s) { return *((int *)s - 2); } int &refcnt () const { return refcnt (s); } int length () const { return length (s); } 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 const char *operator &() const { return s; } const char &operator [](int i) const { return s[i]; } operator const char *() const { return s == null ? 0 : s; } shstr () : s (null) { } shstr (const shstr &sh) : s (sh.s) { ++refcnt (); } explicit shstr (const char *s) : s (intern (s)) { } ~shstr () { --refcnt (); } const shstr &operator =(const shstr &sh) { --refcnt (); s = sh.s; ++refcnt (); return *this; } const shstr &operator =(const char *str) { --refcnt (); #if 0 // this optimises the important case of str == constant 0 if (is_constant (str)) s = str ? intern (str) : null; else #endif s = intern (str); return *this; } }; 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