#ifndef SHSTR_H__ #define SHSTR_H__ #include #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 (); // this optimises the important case of str == constant 0 if (is_constant (str)) s = str ? intern (str) : null; else s = intern (str); return *this; } bool operator ==(const shstr &b) { return s == b.s; } bool operator !=(const shstr &b) { return !(*this == b); } }; inline int strlen (const shstr &sh) { return sh.length (); } inline int strcmp (const shstr &a, const shstr &b) { // TODO: use this to find all the occurences of people using strcmp // all uses should be bogus, as we should be never interested in // comparing shstr's alphabetically #if 0 extern void do_not_use_strcmp_to_compare_shstr_values (); do_not_use_strcmp_to_compare_shstr_values (); #endif return a != b; } std::ostream &operator <<(std::ostream &o, const shstr &sh) { o.write (sh.s, sh.length ()); return o; } // only good for mass comparisons to shstr objects struct shstr_cmp { const char *s; explicit shstr_cmp (const char *s) : s (shstr::find (s)) { } shstr_cmp (const shstr_cmp &sh) : s (sh.s) { } shstr_cmp &operator =(const shstr_cmp sh) { s = sh.s; return *this; } operator const char *() const { return s; } }; inline bool operator ==(const shstr_cmp &a, const shstr &b) { return a.s == b.s; } inline bool operator ==(const shstr &a, const shstr_cmp &b) { return b == a; } extern const shstr undead_name; /* Used in hit_player() in main.c */ #endif