--- deliantra/server/include/shstr.h 2008/12/31 17:35:37 1.24 +++ deliantra/server/include/shstr.h 2018/11/17 23:40:01 1.45 @@ -1,21 +1,23 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. - * - * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * - * Deliantra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * + * + * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * + * Deliantra is free software: you can redistribute it and/or modify it under + * the terms of the Affero GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * + * + * You should have received a copy of the Affero GNU General Public License + * and the GNU General Public License along with this program. If not, see + * . + * * The authors can be reached via e-mail to */ @@ -25,23 +27,44 @@ #include #include -#include "util.h" +#include "traits.h" extern size_t shstr_alloc; extern int buf_overflow (const char *buf1, const char *buf2, int bufsize); +template +struct shstr_vec +{ + uint32_t hash; + uint32_t len; + uint32_t refcnt; + // pointer points here + char string [size]; +}; + // this class is a non-refcounted shared string // it cannot be used to create or store shared strings, but -// it can be used to apss shared strings around, i.e. as function arguments +// it can be used to pass shared strings around, i.e. as function arguments // or return values. their lifetime must not span a gc () call, i.e. // they are only valid as temporary values within the same server tick. struct shstr_tmp { - static const char *null; + static shstr_vec nullvec; + static const char *null () { return nullvec.string; } // this is the null pointer value const char *s; + static unsigned int &hash (const char *s) + { + return *((unsigned int *)s - 3); + } + + int hash () const + { + return hash (s); + } + static unsigned int &length (const char *s) { return *((unsigned int *)s - 2); @@ -61,13 +84,19 @@ return length () >= plen && !strncasecmp (s, prefix, plen); } - bool contains (const char *substring) const + // returns true if the substring is contained in the shstr + // if the shstr is 0, then this always returns false. + // the shstr is (theoretically) treated as a comma/colon/space etc. separated list. + bool contains (const char *substring) const; + + //TODO: case sensitive should be eradicated + bool eq_nc (const char *otherstring) const { - return strstr (s, substring); + return !strcasecmp (s, otherstring); } shstr_tmp () - : s (null) + : s (null ()) { } @@ -86,7 +115,14 @@ // this is used for informational messages and the like const char *operator &() const { return s; } - operator const char *() const { return s == null ? 0 : s; } + operator const char *() const { return s == null () ? 0 : s; } + +protected: + // dummy is there so it isn't used as type converter accidentally + shstr_tmp (int dummy, const char *s) + : s(s) + { + } }; inline bool operator ==(const shstr_tmp &a, const shstr_tmp &b) @@ -99,15 +135,12 @@ return a.s != b.s; } -inline int strlen (const shstr_tmp &sh) +inline int strlen (shstr_tmp sh) { return sh.length (); } -// undefined external reference to catch people using strcmp when they shouldn't -int strcmp (const shstr_tmp &a, const shstr_tmp &b); - -static std::ostream &operator <<(std::ostream &o, shstr_tmp sh) +static inline std::ostream &operator <<(std::ostream &o, shstr_tmp sh) { o.write (sh.s, sh.length ()); @@ -148,8 +181,8 @@ } explicit shstr (const char *str) + : shstr_tmp (0, ecb_is_constant (str) && !str ? null () : intern (str)) { - s = is_constant (str) && !str ? null : intern (str); } ~shstr () @@ -180,7 +213,7 @@ shstr &operator =(const char *str) { --refcnt (); - s = is_constant (str) && !str ? null : intern (str); + s = ecb_is_constant (str) && !str ? null () : intern (str); return *this; } @@ -192,17 +225,18 @@ { const char *s; - explicit shstr_cmp (const char *str) - : s (shstr::find (str)) + // initialies to the non-matching string (as opposed to the null string) + shstr_cmp () { + s = 0; } - shstr_cmp (const shstr_cmp &sh) - : s (sh.s) + shstr_cmp (const char *str) + : s (shstr::find (str)) { } - shstr_cmp (const shstr &sh) + shstr_cmp (shstr_tmp sh) : s (sh.s) { } @@ -210,7 +244,6 @@ // this is used for informational messages and the like const char *operator &() const { return s; } - shstr_cmp operator =(const shstr_cmp sh) { s = sh.s; return *this; } operator const char *() const { return s; } }; @@ -224,11 +257,15 @@ return a.s == b.s; } -extern const shstr shstr_null; - -#define def(str) extern const shstr shstr_ ## str; +#define def2(id,str) extern const shstr id; +#define def(id) def2(shstr_ ## id, # id) # include "shstrinc.h" #undef def +#undef def2 + +// undefined external reference to catch people using str* functions when they shouldn't +//template void strcmp (const shstr_tmp &a, any b); +template void strstr (const shstr_tmp &a, any b); #endif