scws4r 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +65 -0
- data/LICENSE.txt +21 -0
- data/README.md +56 -0
- data/Rakefile +20 -0
- data/defaults/dict.utf8.xdb +0 -0
- data/defaults/rules.utf8.ini +291 -0
- data/ext/scws4r/Makefile +267 -0
- data/ext/scws4r/Makefile.am +15 -0
- data/ext/scws4r/charset.c +90 -0
- data/ext/scws4r/charset.h +14 -0
- data/ext/scws4r/config_win32.h +22 -0
- data/ext/scws4r/crc32.c +103 -0
- data/ext/scws4r/crc32.h +13 -0
- data/ext/scws4r/darray.c +35 -0
- data/ext/scws4r/darray.h +22 -0
- data/ext/scws4r/extconf.rb +3 -0
- data/ext/scws4r/lock.c +153 -0
- data/ext/scws4r/lock.h +44 -0
- data/ext/scws4r/pool.c +141 -0
- data/ext/scws4r/pool.h +53 -0
- data/ext/scws4r/rule.c +407 -0
- data/ext/scws4r/rule.h +83 -0
- data/ext/scws4r/scws.c +1581 -0
- data/ext/scws4r/scws.h +118 -0
- data/ext/scws4r/scws4r.c +207 -0
- data/ext/scws4r/scws4r.h +4 -0
- data/ext/scws4r/version.h.in +4 -0
- data/ext/scws4r/xdb.c +636 -0
- data/ext/scws4r/xdb.h +88 -0
- data/ext/scws4r/xdict.c +394 -0
- data/ext/scws4r/xdict.h +73 -0
- data/ext/scws4r/xtree.c +337 -0
- data/ext/scws4r/xtree.h +65 -0
- data/lib/scws4r/version.rb +5 -0
- data/lib/scws4r.rb +15 -0
- data/scws4r.gemspec +30 -0
- data/sig/scws.rbs +4 -0
- data/test.rb +16 -0
- metadata +88 -0
data/ext/scws4r/xdb.c
ADDED
@@ -0,0 +1,636 @@
|
|
1
|
+
/**
|
2
|
+
* @file xdb.c (xtree use file storage)
|
3
|
+
* @author Hightman Mar
|
4
|
+
* @editor set number ; syntax on ; set autoindent ; set tabstop=4 (vim)
|
5
|
+
* $Id$
|
6
|
+
*/
|
7
|
+
|
8
|
+
#ifdef HAVE_CONFIG_H
|
9
|
+
# include "config.h"
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifdef WIN32
|
13
|
+
# include "config_win32.h"
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#include "xdb.h"
|
17
|
+
#include "lock.h"
|
18
|
+
#include <stdio.h>
|
19
|
+
#include <stdlib.h>
|
20
|
+
#ifndef WIN32
|
21
|
+
# include <unistd.h>
|
22
|
+
#endif
|
23
|
+
#include <string.h>
|
24
|
+
#include <fcntl.h>
|
25
|
+
#include <sys/stat.h>
|
26
|
+
#include <sys/types.h>
|
27
|
+
|
28
|
+
#ifdef HAVE_FLOCK
|
29
|
+
# include <sys/file.h>
|
30
|
+
#endif
|
31
|
+
|
32
|
+
#ifdef HAVE_MMAP
|
33
|
+
# include <sys/mman.h>
|
34
|
+
#endif
|
35
|
+
|
36
|
+
static int _xdb_hasher(xdb_t x, const char *s, int len)
|
37
|
+
{
|
38
|
+
unsigned int h = x->base;
|
39
|
+
while (len--)
|
40
|
+
{
|
41
|
+
h += (h<<5);
|
42
|
+
h ^= (unsigned char) s[len];
|
43
|
+
h &= 0x7fffffff;
|
44
|
+
}
|
45
|
+
return (h % x->prime);
|
46
|
+
}
|
47
|
+
|
48
|
+
static void _xdb_read_data(xdb_t x, void *buf, unsigned int off, int len)
|
49
|
+
{
|
50
|
+
/* check off & x->fsize? */
|
51
|
+
if (off > x->fsize)
|
52
|
+
return;
|
53
|
+
|
54
|
+
/* fixed the len boundary!! */
|
55
|
+
if ((off + len) > x->fsize)
|
56
|
+
len = x->fsize - off;
|
57
|
+
|
58
|
+
if (x->fd >= 0)
|
59
|
+
{
|
60
|
+
lseek(x->fd, off, SEEK_SET);
|
61
|
+
read(x->fd, buf, len);
|
62
|
+
}
|
63
|
+
else
|
64
|
+
{
|
65
|
+
memcpy(buf, x->fmap + off, len);
|
66
|
+
}
|
67
|
+
/* hightman.101230: fixed overflow, thanks to hovea on bbs */
|
68
|
+
//memset((void *)((char *)buf + len), 0, 1);
|
69
|
+
}
|
70
|
+
|
71
|
+
/* recursive to search the matched record */
|
72
|
+
static void _xdb_rec_get(xdb_t x, xrec_t rec, const char *key, int len)
|
73
|
+
{
|
74
|
+
unsigned char buf[XDB_MAXKLEN + 2]; // greater than: 255
|
75
|
+
int cmp;
|
76
|
+
|
77
|
+
if (rec->me.len == 0)
|
78
|
+
return;
|
79
|
+
|
80
|
+
// [left][right] = 16\0
|
81
|
+
_xdb_read_data(x, buf, rec->me.off + 16, len + 1);
|
82
|
+
cmp = memcmp(key, buf+1, len);
|
83
|
+
if (!cmp)
|
84
|
+
cmp = len - buf[0];
|
85
|
+
if (cmp > 0)
|
86
|
+
{
|
87
|
+
// right
|
88
|
+
rec->poff = rec->me.off + sizeof(xptr_st);
|
89
|
+
_xdb_read_data(x, &rec->me, rec->me.off + sizeof(xptr_st), sizeof(xptr_st));
|
90
|
+
_xdb_rec_get(x, rec, key, len);
|
91
|
+
}
|
92
|
+
else if (cmp < 0)
|
93
|
+
{
|
94
|
+
// left
|
95
|
+
rec->poff = rec->me.off;
|
96
|
+
_xdb_read_data(x, &rec->me, rec->me.off, sizeof(xptr_st));
|
97
|
+
_xdb_rec_get(x, rec, key, len);
|
98
|
+
}
|
99
|
+
else
|
100
|
+
{
|
101
|
+
// found!
|
102
|
+
rec->value.off = rec->me.off + 17 + len;
|
103
|
+
rec->value.len = rec->me.len - 17 - len;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
static xrec_t _xdb_rec_find(xdb_t x, const char *key, int len, xrec_t rec)
|
108
|
+
{
|
109
|
+
int i;
|
110
|
+
|
111
|
+
if (rec == NULL)
|
112
|
+
rec = (xrec_t) malloc(sizeof(xrec_st));
|
113
|
+
|
114
|
+
memset(rec, 0, sizeof(xrec_st));
|
115
|
+
i = (x->prime > 1 ? _xdb_hasher(x, key, len) : 0);
|
116
|
+
rec->poff = i * sizeof(xptr_st) + sizeof(struct xdb_header);
|
117
|
+
|
118
|
+
_xdb_read_data(x, &rec->me, rec->poff, sizeof(xptr_st));
|
119
|
+
_xdb_rec_get(x, rec, key, len);
|
120
|
+
return rec;
|
121
|
+
}
|
122
|
+
|
123
|
+
/* mode = r(readonly) | w(write&read) */
|
124
|
+
xdb_t xdb_open(const char *fpath, int mode)
|
125
|
+
{
|
126
|
+
xdb_t x;
|
127
|
+
struct stat st;
|
128
|
+
struct xdb_header xhdr;
|
129
|
+
|
130
|
+
/* create the new memory */
|
131
|
+
if (!(x = (xdb_t ) malloc(sizeof(xdb_st))))
|
132
|
+
return NULL;
|
133
|
+
|
134
|
+
/* try to open & check the file */
|
135
|
+
if ((x->fd = open(fpath, mode == 'w' ? O_RDWR : O_RDONLY)) < 0)
|
136
|
+
{
|
137
|
+
#ifdef DEBUG
|
138
|
+
perror("Failed to open the XDB file");
|
139
|
+
#endif
|
140
|
+
free(x);
|
141
|
+
return NULL;
|
142
|
+
}
|
143
|
+
|
144
|
+
/* check the file */
|
145
|
+
if (fstat(x->fd, &st) || !S_ISREG(st.st_mode) || (x->fsize = st.st_size) <= 0)
|
146
|
+
{
|
147
|
+
#ifdef DEBUG
|
148
|
+
perror("Invalid XDB file");
|
149
|
+
#endif
|
150
|
+
close(x->fd);
|
151
|
+
free(x);
|
152
|
+
return NULL;
|
153
|
+
}
|
154
|
+
|
155
|
+
/* check the XDB header: XDB+version(1bytes)+base+prime+fsize+<dobule check> = 19bytes */
|
156
|
+
lseek(x->fd, 0, SEEK_SET);
|
157
|
+
if ((read(x->fd, &xhdr, sizeof(xhdr)) != sizeof(xhdr))
|
158
|
+
|| memcmp(xhdr.tag, XDB_TAGNAME, 3) || (xhdr.fsize != x->fsize))
|
159
|
+
{
|
160
|
+
#ifdef DEBUG
|
161
|
+
perror("Invalid XDB file format");
|
162
|
+
#endif
|
163
|
+
close(x->fd);
|
164
|
+
free(x);
|
165
|
+
return NULL;
|
166
|
+
}
|
167
|
+
x->prime = xhdr.prime;
|
168
|
+
x->base = xhdr.base;
|
169
|
+
x->version = (int) xhdr.ver;
|
170
|
+
x->fmap = NULL;
|
171
|
+
x->mode = mode;
|
172
|
+
|
173
|
+
/* lock the file in write mode */
|
174
|
+
if (mode == 'w')
|
175
|
+
_xdb_flock(x->fd, LOCK_EX);
|
176
|
+
/* try mmap if readonly */
|
177
|
+
#ifdef HAVE_MMAP
|
178
|
+
else
|
179
|
+
{
|
180
|
+
x->fmap = (char *) mmap(NULL, x->fsize, PROT_READ, MAP_SHARED, x->fd, 0);
|
181
|
+
close(x->fd);
|
182
|
+
x->fd = -1;
|
183
|
+
|
184
|
+
if (x->fmap == (char *) MAP_FAILED)
|
185
|
+
{
|
186
|
+
#ifdef DEBUG
|
187
|
+
perror("Mmap() failed");
|
188
|
+
#endif
|
189
|
+
free(x);
|
190
|
+
return NULL;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
#endif
|
194
|
+
return x;
|
195
|
+
}
|
196
|
+
|
197
|
+
xdb_t xdb_create(const char *fpath, int base, int prime)
|
198
|
+
{
|
199
|
+
xdb_t x;
|
200
|
+
struct xdb_header xhdr;
|
201
|
+
|
202
|
+
/* create the new memory */
|
203
|
+
if (!(x = (xdb_t ) malloc(sizeof(xdb_st))))
|
204
|
+
return NULL;
|
205
|
+
|
206
|
+
/* try to open & check the file */
|
207
|
+
if ((x->fd = open(fpath, (O_CREAT|O_RDWR|O_TRUNC|O_EXCL), 0600)) < 0)
|
208
|
+
{
|
209
|
+
#ifdef DEBUG
|
210
|
+
perror("Failed to open & create the db file");
|
211
|
+
#endif
|
212
|
+
free(x);
|
213
|
+
return NULL;
|
214
|
+
}
|
215
|
+
|
216
|
+
/* write the header */
|
217
|
+
_xdb_flock(x->fd, LOCK_EX);
|
218
|
+
x->prime = prime ? prime : 2047;
|
219
|
+
x->base = base ? base : 0xf422f;
|
220
|
+
x->fsize = sizeof(xhdr) + x->prime * sizeof(xptr_st);
|
221
|
+
x->fmap = NULL;
|
222
|
+
x->mode = 'w';
|
223
|
+
memset(&xhdr, 0, sizeof(xhdr));
|
224
|
+
memcpy(&xhdr.tag, XDB_TAGNAME, 3);
|
225
|
+
xhdr.ver = XDB_VERSION;
|
226
|
+
xhdr.prime = x->prime;
|
227
|
+
xhdr.base = x->base;
|
228
|
+
xhdr.fsize = x->fsize;
|
229
|
+
xhdr.check = (float)XDB_FLOAT_CHECK;
|
230
|
+
|
231
|
+
/* check the XDB header: XDB+version(1bytes)+base+prime+fsize+<dobule check> = 19bytes */
|
232
|
+
lseek(x->fd, 0, SEEK_SET);
|
233
|
+
write(x->fd, &xhdr, sizeof(xhdr));
|
234
|
+
return x;
|
235
|
+
}
|
236
|
+
|
237
|
+
void xdb_close(xdb_t x)
|
238
|
+
{
|
239
|
+
if (x == NULL)
|
240
|
+
return;
|
241
|
+
|
242
|
+
#ifdef HAVE_MMAP
|
243
|
+
if (x->fmap != NULL)
|
244
|
+
{
|
245
|
+
munmap(x->fmap, x->fsize);
|
246
|
+
x->fmap = NULL;
|
247
|
+
}
|
248
|
+
#endif
|
249
|
+
|
250
|
+
if (x->fd >= 0)
|
251
|
+
{
|
252
|
+
if (x->mode == 'w')
|
253
|
+
{
|
254
|
+
lseek(x->fd, 12, SEEK_SET);
|
255
|
+
write(x->fd, &x->fsize, sizeof(x->fsize));
|
256
|
+
_xdb_flock(x->fd, LOCK_UN);
|
257
|
+
}
|
258
|
+
close(x->fd);
|
259
|
+
x->fd = -1;
|
260
|
+
}
|
261
|
+
free(x);
|
262
|
+
}
|
263
|
+
|
264
|
+
/* read mode (value require free by user) */
|
265
|
+
void *xdb_nget(xdb_t x, const char *key, int len, unsigned int *vlen)
|
266
|
+
{
|
267
|
+
xrec_st rec;
|
268
|
+
void *value = NULL;
|
269
|
+
|
270
|
+
if (x == NULL || key == NULL || len > XDB_MAXKLEN)
|
271
|
+
return NULL;
|
272
|
+
|
273
|
+
/* not found, return the poff(for write) */
|
274
|
+
_xdb_rec_find(x, key, len, &rec);
|
275
|
+
if (rec.value.len > 0)
|
276
|
+
{
|
277
|
+
/* auto append one byte with '\0' */
|
278
|
+
value = malloc(rec.value.len + 1);
|
279
|
+
if (vlen != NULL)
|
280
|
+
*vlen = rec.value.len;
|
281
|
+
_xdb_read_data(x, value, rec.value.off, rec.value.len);
|
282
|
+
*((char *)value + rec.value.len) = '\0';
|
283
|
+
}
|
284
|
+
return value;
|
285
|
+
}
|
286
|
+
|
287
|
+
void *xdb_get(xdb_t x, const char *key, unsigned int *vlen)
|
288
|
+
{
|
289
|
+
if (x == NULL || key == NULL)
|
290
|
+
return NULL;
|
291
|
+
return xdb_nget(x, key, strlen(key), vlen);
|
292
|
+
}
|
293
|
+
|
294
|
+
/* write mode */
|
295
|
+
void xdb_nput(xdb_t x, void *value, unsigned int vlen, const char *key, int len)
|
296
|
+
{
|
297
|
+
xrec_st rec;
|
298
|
+
|
299
|
+
if (x == NULL || x->fd < 0 || key == NULL || len > XDB_MAXKLEN)
|
300
|
+
return;
|
301
|
+
|
302
|
+
/* not found, return the poff(for write) */
|
303
|
+
_xdb_rec_find(x, key, len, &rec);
|
304
|
+
if (rec.value.len > 0 && vlen <= rec.value.len)
|
305
|
+
{
|
306
|
+
/* just replace */
|
307
|
+
if (vlen > 0)
|
308
|
+
{
|
309
|
+
lseek(x->fd, rec.value.off, SEEK_SET);
|
310
|
+
write(x->fd, value, vlen);
|
311
|
+
}
|
312
|
+
if (vlen < rec.value.len)
|
313
|
+
{
|
314
|
+
vlen += rec.me.len - rec.value.len;
|
315
|
+
lseek(x->fd, rec.poff + 4, SEEK_SET);
|
316
|
+
write(x->fd, &vlen, sizeof(vlen));
|
317
|
+
}
|
318
|
+
}
|
319
|
+
else if (vlen > 0)
|
320
|
+
{
|
321
|
+
/* insert for new data */
|
322
|
+
unsigned char buf[512];
|
323
|
+
xptr_st pnew;
|
324
|
+
|
325
|
+
pnew.off = x->fsize;
|
326
|
+
memset(buf, 0, sizeof(buf));
|
327
|
+
pnew.len = rec.me.len - rec.value.len;
|
328
|
+
if (pnew.len > 0)
|
329
|
+
{
|
330
|
+
_xdb_read_data(x, buf, rec.me.off, pnew.len);
|
331
|
+
}
|
332
|
+
else
|
333
|
+
{
|
334
|
+
buf[16] = len; // key len
|
335
|
+
strncpy(buf + 17, key, len);
|
336
|
+
pnew.len = 17 + len;
|
337
|
+
}
|
338
|
+
lseek(x->fd, pnew.off, SEEK_SET);
|
339
|
+
write(x->fd, buf, pnew.len);
|
340
|
+
write(x->fd, value, vlen);
|
341
|
+
pnew.len += vlen;
|
342
|
+
x->fsize += pnew.len;
|
343
|
+
|
344
|
+
/* update noff & vlen -> poff */
|
345
|
+
lseek(x->fd, rec.poff, SEEK_SET);
|
346
|
+
write(x->fd, &pnew, sizeof(pnew));
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
void xdb_put(xdb_t x, const char *value, const char *key)
|
351
|
+
{
|
352
|
+
if (x == NULL || key == NULL)
|
353
|
+
return;
|
354
|
+
xdb_nput(x, (void *) value, value ? strlen(value) : 0, key, strlen(key));
|
355
|
+
}
|
356
|
+
|
357
|
+
#ifdef DEBUG
|
358
|
+
/* draw the xdb to stdout */
|
359
|
+
struct draw_arg
|
360
|
+
{
|
361
|
+
int depth;
|
362
|
+
int count;
|
363
|
+
int flag;
|
364
|
+
};
|
365
|
+
|
366
|
+
static void _xdb_draw_node(xdb_t x, xptr_t ptr, struct draw_arg *arg, int depth, char *icon1)
|
367
|
+
{
|
368
|
+
char *icon2;
|
369
|
+
|
370
|
+
icon2 = malloc(strlen(icon1) + 4);
|
371
|
+
strcpy(icon2, icon1);
|
372
|
+
|
373
|
+
// output the flag & icon
|
374
|
+
if (arg->flag == 'T')
|
375
|
+
printf("(T) ");
|
376
|
+
else
|
377
|
+
{
|
378
|
+
printf("%s", icon2);
|
379
|
+
if (arg->flag == 'L')
|
380
|
+
{
|
381
|
+
strcat(icon2, " ┃");
|
382
|
+
printf(" ┟(L) ");
|
383
|
+
}
|
384
|
+
else
|
385
|
+
{
|
386
|
+
strcat(icon2, " ");
|
387
|
+
printf(" └(R) ");
|
388
|
+
}
|
389
|
+
}
|
390
|
+
|
391
|
+
// draw the node data
|
392
|
+
if (ptr->len == 0)
|
393
|
+
printf("<NULL>\n");
|
394
|
+
else
|
395
|
+
{
|
396
|
+
unsigned char buf[XDB_MAXKLEN + 18]; // greater than 18 = sizeof(xptr_st)*2+1
|
397
|
+
int vlen, voff;
|
398
|
+
|
399
|
+
vlen = sizeof(buf) - 1;
|
400
|
+
if (vlen > ptr->len)
|
401
|
+
vlen = ptr->len;
|
402
|
+
|
403
|
+
_xdb_read_data(x, buf, ptr->off, vlen);
|
404
|
+
vlen = ptr->len - buf[16] - 17;
|
405
|
+
voff = ptr->off + buf[16] + 17;
|
406
|
+
|
407
|
+
printf("%.*s (vlen=%d, voff=%d)\n", buf[16], buf+17, vlen, voff);
|
408
|
+
|
409
|
+
arg->count++;
|
410
|
+
depth++;
|
411
|
+
if (depth > arg->depth)
|
412
|
+
arg->depth = depth;
|
413
|
+
|
414
|
+
// draw the left & right;
|
415
|
+
arg->flag = 'L';
|
416
|
+
memcpy(ptr, buf, sizeof(xptr_st));
|
417
|
+
_xdb_draw_node(x, ptr, arg, depth, icon2);
|
418
|
+
|
419
|
+
arg->flag = 'R';
|
420
|
+
memcpy(ptr, buf + sizeof(xptr_st), sizeof(xptr_st));
|
421
|
+
_xdb_draw_node(x, ptr, arg, depth, icon2);
|
422
|
+
}
|
423
|
+
free(icon2);
|
424
|
+
}
|
425
|
+
|
426
|
+
void xdb_draw(xdb_t x)
|
427
|
+
{
|
428
|
+
int i;
|
429
|
+
struct draw_arg arg;
|
430
|
+
xptr_st ptr;
|
431
|
+
|
432
|
+
if (!x) return;
|
433
|
+
|
434
|
+
xdb_version(x);
|
435
|
+
for (i = 0; i < x->prime; i++)
|
436
|
+
{
|
437
|
+
arg.depth = 0;
|
438
|
+
arg.count = 0;
|
439
|
+
arg.flag = 'T';
|
440
|
+
|
441
|
+
_xdb_read_data(x, &ptr, i * sizeof(xptr_st) + sizeof(struct xdb_header), sizeof(xptr_st));
|
442
|
+
_xdb_draw_node(x, &ptr, &arg, 0, "");
|
443
|
+
|
444
|
+
printf("-----------------------------------------\n");
|
445
|
+
printf("Tree(xdb) [%d] max_depth: %d nodes_num: %d\n", i, arg.depth, arg.count);
|
446
|
+
}
|
447
|
+
}
|
448
|
+
#endif
|
449
|
+
|
450
|
+
/* optimize the xdb */
|
451
|
+
typedef struct xdb_cmper
|
452
|
+
{
|
453
|
+
xptr_st ptr;
|
454
|
+
char *key;
|
455
|
+
} xcmper_st;
|
456
|
+
|
457
|
+
static void _xdb_count_nodes(xdb_t x, xptr_t ptr, int *count)
|
458
|
+
{
|
459
|
+
int off;
|
460
|
+
if (ptr->len == 0)
|
461
|
+
return;
|
462
|
+
|
463
|
+
*count += 1;
|
464
|
+
off = ptr->off;
|
465
|
+
|
466
|
+
/* left & right */
|
467
|
+
_xdb_read_data(x, ptr, off, sizeof(xptr_st));
|
468
|
+
_xdb_count_nodes(x, ptr, count);
|
469
|
+
|
470
|
+
_xdb_read_data(x, ptr, off + sizeof(xptr_st), sizeof(xptr_st));
|
471
|
+
_xdb_count_nodes(x, ptr, count);
|
472
|
+
}
|
473
|
+
|
474
|
+
#ifdef HAVE_STRNDUP
|
475
|
+
#define _mem_ndup strndup
|
476
|
+
#else
|
477
|
+
static inline void *_mem_ndup(const char *src, int len)
|
478
|
+
{
|
479
|
+
char *dst;
|
480
|
+
dst = malloc(len+1);
|
481
|
+
memcpy(dst, src, len);
|
482
|
+
dst[len] = '\0';
|
483
|
+
return dst;
|
484
|
+
}
|
485
|
+
#endif
|
486
|
+
|
487
|
+
static void _xdb_load_nodes(xdb_t x, xptr_t ptr, xcmper_st *nodes, int *count)
|
488
|
+
{
|
489
|
+
int i;
|
490
|
+
unsigned char buf[XDB_MAXKLEN + 18];
|
491
|
+
|
492
|
+
if (ptr->len == 0)
|
493
|
+
return;
|
494
|
+
|
495
|
+
i = sizeof(buf)-1;
|
496
|
+
if (i > (int)ptr->len)
|
497
|
+
i = ptr->len;
|
498
|
+
|
499
|
+
_xdb_read_data(x, buf, ptr->off, i);
|
500
|
+
|
501
|
+
i = *count;
|
502
|
+
nodes[i].ptr.off = ptr->off;
|
503
|
+
nodes[i].ptr.len = ptr->len;
|
504
|
+
nodes[i].key = (char *) _mem_ndup(buf + 17, buf[16]);
|
505
|
+
*count = i+1;
|
506
|
+
|
507
|
+
/* left & right */
|
508
|
+
memcpy(ptr, buf, sizeof(xptr_st));
|
509
|
+
_xdb_load_nodes(x, ptr, nodes, count);
|
510
|
+
|
511
|
+
memcpy(ptr, buf + sizeof(xptr_st), sizeof(xptr_st));
|
512
|
+
_xdb_load_nodes(x, ptr, nodes, count);
|
513
|
+
}
|
514
|
+
|
515
|
+
static void _xdb_reset_nodes(xdb_t x, xcmper_st *nodes, int low, int high, unsigned int poff)
|
516
|
+
{
|
517
|
+
xptr_st ptr = { 0, 0 };
|
518
|
+
|
519
|
+
if (low <= high)
|
520
|
+
{
|
521
|
+
int mid = (low + high)>>1;
|
522
|
+
|
523
|
+
memcpy(&ptr, &nodes[mid].ptr, sizeof(xptr_st));
|
524
|
+
|
525
|
+
_xdb_reset_nodes(x, nodes, low, mid-1, ptr.off);
|
526
|
+
_xdb_reset_nodes(x, nodes, mid+1, high, ptr.off + sizeof(xptr_st));
|
527
|
+
}
|
528
|
+
|
529
|
+
/* save it */
|
530
|
+
lseek(x->fd, poff, SEEK_SET);
|
531
|
+
write(x->fd, &ptr, sizeof(xptr_st));
|
532
|
+
}
|
533
|
+
|
534
|
+
static int _xdb_node_cmp(a, b)
|
535
|
+
xcmper_st *a, *b;
|
536
|
+
{
|
537
|
+
return strcmp(a->key, b->key);
|
538
|
+
}
|
539
|
+
|
540
|
+
void xdb_optimize(xdb_t x)
|
541
|
+
{
|
542
|
+
int i, cnt, poff;
|
543
|
+
xptr_st ptr, head;
|
544
|
+
xcmper_st *nodes;
|
545
|
+
|
546
|
+
if (x == NULL || x->fd < 0)
|
547
|
+
return;
|
548
|
+
|
549
|
+
for (i = 0; i < x->prime; i++)
|
550
|
+
{
|
551
|
+
poff = i * sizeof(xptr_st) + sizeof(struct xdb_header);
|
552
|
+
_xdb_read_data(x, &head, poff, sizeof(xptr_st));
|
553
|
+
|
554
|
+
cnt = 0;
|
555
|
+
ptr = head;
|
556
|
+
_xdb_count_nodes(x, &ptr, &cnt);
|
557
|
+
|
558
|
+
if (cnt > 2)
|
559
|
+
{
|
560
|
+
nodes = (xcmper_st *) malloc(sizeof(xcmper_st) * cnt);
|
561
|
+
|
562
|
+
cnt = 0;
|
563
|
+
ptr = head;
|
564
|
+
_xdb_load_nodes(x, &ptr, nodes, &cnt);
|
565
|
+
|
566
|
+
qsort(nodes, cnt, sizeof(xcmper_st), _xdb_node_cmp);
|
567
|
+
_xdb_reset_nodes(x, nodes, 0, cnt - 1, poff);
|
568
|
+
|
569
|
+
/* free the nodes & key pointer */
|
570
|
+
while (cnt--)
|
571
|
+
free(nodes[cnt].key);
|
572
|
+
free(nodes);
|
573
|
+
}
|
574
|
+
}
|
575
|
+
}
|
576
|
+
|
577
|
+
void xdb_version(xdb_t x)
|
578
|
+
{
|
579
|
+
printf("%s/%d.%d (base=%d, prime=%d)\n", XDB_TAGNAME,
|
580
|
+
(x->version >> 5), (x->version & 0x1f), x->base, x->prime);
|
581
|
+
}
|
582
|
+
|
583
|
+
/* convert xdb file to xtree struct(memory) */
|
584
|
+
static void _xdb_to_xtree_node(xdb_t x, xtree_t xt, xptr_t ptr)
|
585
|
+
{
|
586
|
+
unsigned char *buf;
|
587
|
+
void *value;
|
588
|
+
int voff;
|
589
|
+
|
590
|
+
if (ptr->len == 0)
|
591
|
+
return;
|
592
|
+
|
593
|
+
buf = (unsigned char *) malloc(ptr->len + 1);
|
594
|
+
_xdb_read_data(x, buf, ptr->off, ptr->len);
|
595
|
+
|
596
|
+
/* save the key & value -> xtree */
|
597
|
+
voff = buf[16] + 17;
|
598
|
+
|
599
|
+
/* 2009-09-22, 11:29, Mistruster: posted on bbs */
|
600
|
+
if (voff >= (int)ptr->len)
|
601
|
+
return;
|
602
|
+
value = pmalloc(xt->p, ptr->len - voff);
|
603
|
+
memcpy(value, buf + voff, ptr->len - voff);
|
604
|
+
xtree_nput(xt, value, ptr->len - voff, buf + 17, buf[16]);
|
605
|
+
|
606
|
+
/* left & right */
|
607
|
+
memcpy(ptr, buf, sizeof(xptr_st));
|
608
|
+
_xdb_to_xtree_node(x, xt, ptr);
|
609
|
+
|
610
|
+
memcpy(ptr, buf + sizeof(xptr_st), sizeof(xptr_st));
|
611
|
+
_xdb_to_xtree_node(x, xt, ptr);
|
612
|
+
|
613
|
+
free(buf);
|
614
|
+
}
|
615
|
+
|
616
|
+
xtree_t xdb_to_xtree(xdb_t x, xtree_t xt)
|
617
|
+
{
|
618
|
+
int i = 0;
|
619
|
+
xptr_st ptr;
|
620
|
+
|
621
|
+
if (!x)
|
622
|
+
return NULL;
|
623
|
+
|
624
|
+
if (!xt && !(xt = xtree_new(x->base, x->prime)))
|
625
|
+
return NULL;
|
626
|
+
|
627
|
+
do
|
628
|
+
{
|
629
|
+
_xdb_read_data(x, &ptr, i * sizeof(xptr_st) + sizeof(struct xdb_header), sizeof(xptr_st));
|
630
|
+
_xdb_to_xtree_node(x, xt, &ptr);
|
631
|
+
}
|
632
|
+
while (++i < x->prime);
|
633
|
+
|
634
|
+
return xt;
|
635
|
+
}
|
636
|
+
|
data/ext/scws4r/xdb.h
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
/**
|
2
|
+
* @file xdb.h (read only)
|
3
|
+
* @author Hightman Mar
|
4
|
+
* @editor set number ; syntax on ; set autoindent ; set tabstop=4 (vim)
|
5
|
+
* $Id$
|
6
|
+
*/
|
7
|
+
|
8
|
+
#ifndef _SCWS_XDB_20070525_H_
|
9
|
+
#define _SCWS_XDB_20070525_H_
|
10
|
+
|
11
|
+
#ifdef __cplusplus
|
12
|
+
extern "C" {
|
13
|
+
#endif
|
14
|
+
|
15
|
+
/* constant var define */
|
16
|
+
#define XDB_FLOAT_CHECK (3.14)
|
17
|
+
#define XDB_TAGNAME "XDB"
|
18
|
+
#define XDB_MAXKLEN 0xf0
|
19
|
+
#define XDB_VERSION 34 /* version: 3bit+5bit */
|
20
|
+
|
21
|
+
#include "xtree.h"
|
22
|
+
|
23
|
+
/* data structure for [Record] */
|
24
|
+
typedef struct xdb_pointer
|
25
|
+
{
|
26
|
+
unsigned int off;
|
27
|
+
unsigned int len;
|
28
|
+
} xptr_st, *xptr_t;
|
29
|
+
|
30
|
+
typedef struct xdb_record
|
31
|
+
{
|
32
|
+
unsigned int poff;
|
33
|
+
xptr_st me;
|
34
|
+
xptr_st value;
|
35
|
+
} xrec_st, *xrec_t;
|
36
|
+
|
37
|
+
/* header struct */
|
38
|
+
struct xdb_header
|
39
|
+
{
|
40
|
+
char tag[3];
|
41
|
+
unsigned char ver;
|
42
|
+
int base;
|
43
|
+
int prime;
|
44
|
+
unsigned int fsize;
|
45
|
+
float check;
|
46
|
+
char unused[12];
|
47
|
+
};
|
48
|
+
|
49
|
+
typedef struct
|
50
|
+
{
|
51
|
+
int fd; /* file descriptoin */
|
52
|
+
int base; /* basenum for hash count */
|
53
|
+
int prime; /* base prime for hash mod */
|
54
|
+
unsigned int fsize; /* total filesize */
|
55
|
+
int version; /* version: low 4bytes */
|
56
|
+
char *fmap; /* file content image by mmap (read only) */
|
57
|
+
int mode; /* xdb_open for write or read-only */
|
58
|
+
} xdb_st, *xdb_t;
|
59
|
+
|
60
|
+
/* xdb: open the db, mode = r|w|n */
|
61
|
+
xdb_t xdb_open(const char *fpath, int mode);
|
62
|
+
xdb_t xdb_create(const char *fpath, int base, int prime);
|
63
|
+
|
64
|
+
/* read mode */
|
65
|
+
void *xdb_nget(xdb_t x, const char *key, int len, unsigned int *vlen);
|
66
|
+
void *xdb_get(xdb_t x, const char *key, unsigned int *vlen);
|
67
|
+
|
68
|
+
#ifdef DEBUG
|
69
|
+
void xdb_draw(xdb_t x);
|
70
|
+
#endif
|
71
|
+
|
72
|
+
/* return the xtree pointer */
|
73
|
+
xtree_t xdb_to_xtree(xdb_t x, xtree_t xt);
|
74
|
+
|
75
|
+
/* write mode */
|
76
|
+
void xdb_nput(xdb_t x, void *value, unsigned int vlen, const char *key, int len);
|
77
|
+
void xdb_put(xdb_t x, const char *value, const char *key);
|
78
|
+
void xdb_optimize(xdb_t x);
|
79
|
+
|
80
|
+
/* xdb: close the db */
|
81
|
+
void xdb_close(xdb_t x);
|
82
|
+
void xdb_version(xdb_t x);
|
83
|
+
|
84
|
+
#ifdef __cplusplus
|
85
|
+
}
|
86
|
+
#endif
|
87
|
+
|
88
|
+
#endif
|