switched to GPLv3 ONLY, because i don't trust FSF anymore
[gaemu.git] / gaem / runner / strpool.d
blob466630377e377129cd02855677c445d9244e4edf
1 /* GML runner
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module gaem.runner.strpool is aliced;
20 // ////////////////////////////////////////////////////////////////////////// //
21 private:
23 struct Str {
24 string val; // string value
25 uint rc; // refcount; <0: persistent string; also serves as free list index with 31 bit set
28 __gshared Str[] spool; // pool of strings
29 __gshared uint spoolFree = 0x8000_0000; // none
32 shared static this () {
33 // preallocate small strings
34 spool ~= Str("", 0);
35 foreach (ubyte c; 0..256) spool ~= Str(""~cast(char)c, 0);
39 // ////////////////////////////////////////////////////////////////////////// //
40 public:
42 uint newInternalStr(T) (T str) if (is(T : const(char)[])) {
43 if (str.length == 0) return 0;
44 if (str.length == 1) return cast(uint)str.ptr[0]+1;
45 //FIXME: speed this up!
46 foreach (immutable idx, ref st; spool) {
47 if (st.val == str) return cast(uint)idx;
49 static if (is(T == string)) alias sv = str; else auto sv = str.idup;
50 // allocate new
51 auto sid = cast(uint)spool.length;
52 if (sid > 0x3F_FFFF) assert(0, "too many strings");
53 spool ~= Str(sv, 0);
54 return sid;
58 // returnted string has rc of 1
59 uint newDynStr(T) (T str) if (is(T : const(char)[])) {
60 if (str.length == 0) return 0;
61 if (str.length == 1) return cast(uint)str.ptr[0]+1;
62 static if (is(T == string)) alias sv = str; else auto sv = str.idup;
63 if (spoolFree&0x7fff_ffff) {
64 // reuse existing
65 auto sid = spoolFree&0x7fff_ffff;
66 auto ss = spool.ptr+sid;
67 spoolFree = ss.rc;
68 ss.val = sv;
69 ss.rc = 1;
70 return sid;
71 } else {
72 // allocate new
73 auto sid = cast(uint)spool.length;
74 if (sid > 0x3F_FFFF) assert(0, "too many dynamic strings");
75 spool ~= Str(sv, 1);
76 return sid;
81 void dynStrIncRef (uint sid) {
82 pragma(inline, true);
83 if (sid < spool.length && spool.ptr[sid].rc > 0) {
84 assert(spool.ptr[sid].rc < 0x8000_0000);
85 ++spool.ptr[sid].rc;
90 void dynStrDecRef (uint sid) {
91 pragma(inline, true);
92 if (sid < spool.length && spool.ptr[sid].rc > 0) {
93 assert(spool.ptr[sid].rc < 0x8000_0000);
94 if (--spool.ptr[sid].rc == 0) {
95 spool.ptr[sid].rc = spoolFree;
96 spoolFree = sid|0x8000_0000;
102 string getDynStr (uint sid) {
103 pragma(inline, true);
104 return (sid < spool.length && spool.ptr[sid].rc < 0x8000_0000 ? spool.ptr[sid].val : null);