1 /*
2  * wordbuf.h -
3  *
4  * Written By:  MURAOKA Taro <koron.kaoriya@gmail.com>
5  * Last Change: 25-Oct-2011.
6  */
7 module migemo_d.wordbuf;
8 
9 
10 private static import core.memory;
11 private static import core.stdc..string;
12 
13 public alias wordbuf_t = ._wordbuf_t;
14 public alias wordbuf_p = ._wordbuf_t*;
15 
16 public struct _wordbuf_t
17 {
18 package:
19 	/**
20 	 * bufに割り当てられているメモリ量 
21 	 */
22 	int len;
23 
24 	char* buf;
25 
26 	/**
27 	 * bufに実際に格納している文字列の長さ 
28 	 */
29 	int last;
30 }
31 
32 debug {
33 	public int n_wordbuf_open = 0;
34 	public int n_wordbuf_close = 0;
35 }
36 
37 pragma(inline, true)
38 pure nothrow @trusted @nogc @live
39 public char* WORDBUF_GET(.wordbuf_p w)
40 
41 	in
42 	{
43 		assert(w != null);
44 	}
45 
46 	do
47 	{
48 		return &(w.buf[0]);
49 	}
50 
51 pragma(inline, true)
52 pure nothrow @trusted @nogc @live
53 public int WORDBUF_LEN(.wordbuf_p w)
54 
55 	in
56 	{
57 		assert(w != null);
58 	}
59 
60 	do
61 	{
62 		return w.last;
63 	}
64 
65 alias wordbuf_len = .wordbuf_last;
66 
67 enum WORDLEN_DEF = 64;
68 
69 extern (C)
70 pure nothrow @trusted @nogc
71 public .wordbuf_p wordbuf_open()
72 
73 	do
74 	{
75 		.wordbuf_p p = cast(.wordbuf_p)(core.memory.pureMalloc(.wordbuf_t.sizeof));
76 
77 		if (p != null) {
78 			debug {
79 				++.n_wordbuf_open;
80 			}
81 
82 			p.len = .WORDLEN_DEF;
83 			p.buf = cast(char*)(core.memory.pureMalloc(p.len));
84 			p.last = 0;
85 			p.buf[0] = '\0';
86 		}
87 
88 		return p;
89 	}
90 
91 extern (C)
92 pure nothrow @trusted @nogc
93 public void wordbuf_close(.wordbuf_p p)
94 
95 	in
96 	{
97 	}
98 
99 	do
100 	{
101 		if (p != null) {
102 			debug {
103 				++.n_wordbuf_close;
104 			}
105 
106 			if (p.buf != null) {
107 				core.memory.pureFree(p.buf);
108 			}
109 
110 			core.memory.pureFree(p);
111 		}
112 	}
113 
114 extern (C)
115 pure nothrow @trusted @nogc @live
116 public void wordbuf_reset(.wordbuf_p p)
117 
118 	in
119 	{
120 		assert(p != null);
121 	}
122 
123 	do
124 	{
125 		p.last = 0;
126 		p.buf[0] = '\0';
127 	}
128 
129 /**
130  * wordbuf_extend(.wordbuf_p p, int req_len);
131  *	バッファの伸長。エラー時には0が帰る。
132  *	高速化のために伸ばすべきかは呼出側で判断する。
133  */
134 pure nothrow @trusted @nogc
135 package int wordbuf_extend(.wordbuf_p p, int req_len)
136 
137 	in
138 	{
139 		assert(p != null);
140 	}
141 
142 	do
143 	{
144 		int newlen = p.len * 2;
145 
146 		while (req_len > newlen) {
147 			newlen *= 2;
148 		}
149 
150 		char* newbuf = cast(char*)(core.memory.pureRealloc(p.buf, newlen));
151 
152 		if (newbuf == null) {
153 			/*core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "wordbuf_add(): failed to extend buffer\n");*/
154 			return 0;
155 		} else {
156 			p.len = newlen;
157 			p.buf = newbuf;
158 
159 			return req_len;
160 		}
161 	}
162 
163 extern (C)
164 pure nothrow @trusted @nogc @live
165 public int wordbuf_last(.wordbuf_p p)
166 
167 	in
168 	{
169 		assert(p != null);
170 	}
171 
172 	do
173 	{
174 		return p.last;
175 	}
176 
177 extern (C)
178 pure nothrow @trusted @nogc @live
179 public int wordbuf_add(.wordbuf_p p, char ch)
180 
181 	in
182 	{
183 		assert(p != null);
184 	}
185 
186 	do
187 	{
188 		int newlen = p.last + 2;
189 
190 		if ((newlen > p.len) && (!.wordbuf_extend(p, newlen))) {
191 			return 0;
192 		} else {
193 			version (LittleEndian) {
194 				/* リトルエンディアンを仮定するなら使えるが… */
195 				*(cast(ushort*)(&p.buf[p.last])) = cast(ushort)(ch);
196 			} else {
197 				char* buf = p.buf + p.last;
198 
199 				buf[0] = ch;
200 				buf[1] = '\0';
201 			}
202 
203 			return ++p.last;
204 		}
205 	}
206 
207 extern (C)
208 pure nothrow @nogc
209 public int wordbuf_cat(.wordbuf_p p, const (char)* sz)
210 
211 	in
212 	{
213 		assert(p != null);
214 	}
215 
216 	do
217 	{
218 		int len = 0;
219 
220 		if (sz != null) {
221 			size_t l = core.stdc..string.strlen(sz);
222 			len = (l < int.max) ? (cast(int)(l)) : (int.max);
223 		}
224 
225 		if (len > 0) {
226 			int newlen = p.last + len + 1;
227 
228 			if ((newlen > p.len) && (!.wordbuf_extend(p, newlen))) {
229 				return 0;
230 			}
231 
232 			core.stdc..string.memcpy(&p.buf[p.last], sz, len + 1);
233 			p.last = p.last + len;
234 		}
235 
236 		return p.last;
237 	}
238 
239 extern (C)
240 pure nothrow @trusted @nogc @live
241 public char* wordbuf_get(.wordbuf_p p)
242 
243 	in
244 	{
245 		assert(p != null);
246 	}
247 
248 	do
249 	{
250 		return p.buf;
251 	}