ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/shstr.C
Revision: 1.36
Committed: Thu Jan 1 11:41:17 2009 UTC (15 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.35: +3 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.28 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.23 *
4 root 1.29 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.23 *
6 root 1.28 * Deliantra is free software: you can redistribute it and/or modify
7 root 1.24 * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10 root 1.23 *
11 root 1.24 * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15 root 1.23 *
16 root 1.24 * You should have received a copy of the GNU General Public License
17     * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 root 1.23 *
19 root 1.28 * The authors can be reached via e-mail to <support@deliantra.net>
20 root 1.22 */
21    
22     /*
23 root 1.3 * shstr.C
24 elmex 1.1 */
25    
26 root 1.3 #include <cstring>
27     #include <cstdlib>
28 root 1.10 #include <glib.h>
29 root 1.3 #include <tr1/unordered_set>
30 elmex 1.1
31 root 1.16 #include "global.h"
32 elmex 1.1
33 root 1.26 size_t shstr_alloc;
34    
35 root 1.31 typedef std::tr1::unordered_set <const char *, str_hash, str_equal, slice_allocator<const char *> > HT;
36 elmex 1.1
37 root 1.16 static HT ht;
38 root 1.29 static int next_gc;
39 elmex 1.1
40 root 1.13 static const char *
41     makevec (const char *s)
42 root 1.7 {
43 root 1.17 int len = strlen (s);
44 root 1.7
45 root 1.33 shstr_alloc += sizeof (uint32_t) * 2 + len + 1;
46     const char *v = (const char *) (2 + (int *)g_slice_alloc (sizeof (uint32_t) * 2 + len + 1));
47 root 1.7
48     shstr::length (v) = len;
49     shstr::refcnt (v) = 1;
50    
51 root 1.13 memcpy ((char *) v, s, len + 1);
52 root 1.7
53 root 1.8 return v;
54 root 1.7 }
55    
56 root 1.33 shstr_vec<sizeof "(null)"> shstr_tmp::nullvec = { 0, 0xffffffff, "(null)" };
57 root 1.15
58 elmex 1.1 const char *
59 root 1.3 shstr::find (const char *s)
60     {
61 root 1.4 if (!s)
62     return s;
63    
64 root 1.21 auto (i, ht.find (s));
65 elmex 1.1
66 root 1.13 return i != ht.end ()? *i : 0;
67 elmex 1.1 }
68    
69     const char *
70 root 1.3 shstr::intern (const char *s)
71     {
72 root 1.4 if (!s)
73 root 1.33 return null ();
74 elmex 1.1
75 root 1.4 if (const char *found = find (s))
76 root 1.5 {
77     ++refcnt (found);
78     return found;
79     }
80 elmex 1.1
81 root 1.29 --next_gc;
82 root 1.7 s = makevec (s);
83     ht.insert (s);
84     return s;
85 elmex 1.1 }
86    
87 root 1.5 // periodically test refcounts == 0 for a few strings
88     // this is the ONLY thing that erases stuff from ht. keep it that way.
89 elmex 1.1 void
90 root 1.3 shstr::gc ()
91     {
92 root 1.29 if (expect_true (next_gc > 0))
93     return;
94    
95 root 1.5 static const char *curpos;
96    
97 root 1.21 auto (i, curpos ? ht.find (curpos) : ht.begin ());
98 root 1.5
99     if (i == ht.end ())
100     i = ht.begin ();
101    
102 root 1.11 int n = ht.size () / 256 + 16;
103 root 1.29 next_gc += n >> 1;
104 root 1.6
105     for (;;)
106 root 1.5 {
107     if (i == ht.end ())
108     {
109     curpos = 0;
110     return;
111     }
112 root 1.6 else if (!--n)
113     break;
114     else if (!refcnt (*i))
115 root 1.5 {
116 root 1.21 auto (o, i++);
117 root 1.5 const char *s = *o;
118 root 1.13
119 root 1.5 ht.erase (o);
120    
121     //printf ("GC %4d %3d %d >%s<%d\n", (int)ht.size (), n, shstr::refcnt (s), s, shstr::length (s));
122 root 1.33 shstr_alloc -= sizeof (uint32_t) * 2 + length (s) + 1;
123     g_slice_free1 (sizeof (uint32_t) * 2 + length (s) + 1, -2 + (int *) s);
124 root 1.5 }
125     else
126     ++i;
127     }
128    
129     curpos = *i;
130 elmex 1.1 }
131    
132 root 1.25 // declare these here to get correct initialisation order
133 root 1.36 #define def2(id,str) const shstr shstr_ ## id (str);
134     #define def(id) def2(id, # id)
135 root 1.25 # include "shstrinc.h"
136     #undef def
137 root 1.36 #undef def2
138 root 1.25
139 root 1.16 shstr skill_names[NUM_SKILLS];
140    
141 root 1.5 //TODO: this should of course not be here
142 root 1.13
143 elmex 1.1 /* buf_overflow() - we don't want to exceed the buffer size of
144     * buf1 by adding on buf2! Returns true if overflow will occur.
145     */
146 root 1.13 int
147 elmex 1.1 buf_overflow (const char *buf1, const char *buf2, int bufsize)
148     {
149 root 1.13 int len1 = 0, len2 = 0;
150 elmex 1.1
151 root 1.13 if (buf1)
152     len1 = strlen (buf1);
153 root 1.26
154 root 1.13 if (buf2)
155     len2 = strlen (buf2);
156 root 1.26
157 root 1.13 if ((len1 + len2) >= bufsize)
158     return 1;
159 root 1.22
160 root 1.13 return 0;
161 elmex 1.1 }