~ubuntu-branches/ubuntu/wily/ruby-ferret/wily

« back to all changes in this revision

Viewing changes to ext/ferret.c

  • Committer: Bazaar Package Importer
  • Author(s): Antonio Terceiro
  • Date: 2011-07-28 00:02:49 UTC
  • Revision ID: james.westby@ubuntu.com-20110728000249-v0443y69ftcpxwi6
Tags: upstream-0.11.6
ImportĀ upstreamĀ versionĀ 0.11.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <errno.h>
 
2
#include "ferret.h"
 
3
#include "except.h"
 
4
#include "hash.h"
 
5
#include "hashset.h"
 
6
#include "threading.h"
 
7
 
 
8
/* Object Map */
 
9
static HashTable *object_map;
 
10
 
 
11
/* IDs */
 
12
ID id_new;
 
13
ID id_call;
 
14
ID id_eql;
 
15
ID id_hash;
 
16
ID id_capacity;
 
17
ID id_less_than;
 
18
ID id_lt;
 
19
ID id_is_directory;
 
20
ID id_close;
 
21
ID id_cclass;
 
22
ID id_data;
 
23
 
 
24
static ID id_mkdir_p;
 
25
 
 
26
/* Symbols */
 
27
VALUE sym_yes;
 
28
VALUE sym_no;
 
29
VALUE sym_true;
 
30
VALUE sym_false;
 
31
VALUE sym_path;
 
32
VALUE sym_dir;
 
33
 
 
34
/* Modules */
 
35
VALUE mFerret;
 
36
VALUE mStore;
 
37
VALUE mStringHelper;
 
38
VALUE mSpans;
 
39
 
 
40
/* Classes */
 
41
VALUE cTerm;
 
42
/*
 
43
*/
 
44
 
 
45
unsigned long value_hash(const void *key)
 
46
{
 
47
    return (unsigned long)key;
 
48
}
 
49
 
 
50
int value_eq(const void *key1, const void *key2)
 
51
{
 
52
    return key1 == key2;
 
53
}
 
54
 
 
55
VALUE object_get(void *key)
 
56
{
 
57
    VALUE val = (VALUE)h_get(object_map, key);
 
58
    if (!val) val = Qnil;
 
59
    return val;
 
60
}
 
61
 
 
62
//static int hash_cnt = 0;
 
63
void
 
64
//object_add(void *key, VALUE obj)
 
65
object_add2(void *key, VALUE obj, const char *file, int line)
 
66
{
 
67
    if (h_get(object_map, key))
 
68
        printf("failed adding %lx to %ld; already contains %lx. %s:%d\n",
 
69
               (long)obj, (long)key, (long)h_get(object_map, key), file, line);
 
70
    //printf("adding %ld. now contains %d %s:%d\n", (long)key, ++hash_cnt, file, line);
 
71
    h_set(object_map, key, (void *)obj);
 
72
}
 
73
 
 
74
void
 
75
//object_set(void *key, VALUE obj)
 
76
object_set2(void *key, VALUE obj, const char *file, int line)
 
77
{
 
78
    //if (!h_get(object_map, key))
 
79
      //printf("adding %ld. now contains %d %s:%d\n", (long)key, ++hash_cnt, file, line);
 
80
    h_set(object_map, key, (void *)obj);
 
81
}
 
82
 
 
83
void
 
84
//object_del(void *key)
 
85
object_del2(void *key, const char *file, int line)
 
86
{
 
87
    if (object_get(key) == Qnil) 
 
88
        printf("failed deleting %ld. %s:%d\n", (long)key, file, line);
 
89
    //printf("deleting %ld. now contains %ld, %s:%d\n", (long)key, --hash_cnt, file, line);
 
90
    h_del(object_map, key);
 
91
}
 
92
 
 
93
void frt_gc_mark(void *key)
 
94
{
 
95
    VALUE val = (VALUE)h_get(object_map, key);
 
96
    if (val)
 
97
        rb_gc_mark(val);
 
98
}
 
99
 
 
100
VALUE frt_data_alloc(VALUE klass)
 
101
{
 
102
    return Frt_Make_Struct(klass);
 
103
}
 
104
 
 
105
void frt_deref_free(void *p)
 
106
{
 
107
    object_del(p);
 
108
}
 
109
 
 
110
void frt_thread_once(int *once_control, void (*init_routine) (void))
 
111
{
 
112
    if (*once_control) {
 
113
        init_routine();
 
114
        *once_control = 0;
 
115
    }
 
116
}
 
117
 
 
118
void frt_thread_key_create(thread_key_t *key, void (*destr_function)(void *))
 
119
{
 
120
    *key = h_new(&value_hash, &value_eq, NULL, destr_function);
 
121
}
 
122
 
 
123
void frt_thread_key_delete(thread_key_t key)
 
124
{
 
125
    h_destroy(key);
 
126
}
 
127
 
 
128
void frt_thread_setspecific(thread_key_t key, const void *pointer)
 
129
{
 
130
    h_set(key, (void *)rb_thread_current(), (void *)pointer);
 
131
}
 
132
 
 
133
void *frt_thread_getspecific(thread_key_t key)
 
134
{
 
135
    return h_get(key, (void *)rb_thread_current());
 
136
}
 
137
 
 
138
void frt_create_dir(VALUE rpath)
 
139
{
 
140
    VALUE mFileUtils;
 
141
    rb_require("fileutils");
 
142
    mFileUtils = rb_define_module("FileUtils");
 
143
    rb_funcall(mFileUtils, id_mkdir_p, 1, rpath);
 
144
}
 
145
 
 
146
VALUE frt_hs_to_rb_ary(HashSet *hs)
 
147
{
 
148
    int i;
 
149
    VALUE ary = rb_ary_new();
 
150
    for (i = 0; i < hs->size; i++) {
 
151
        rb_ary_push(ary, rb_str_new2(hs->elems[i]));
 
152
    }
 
153
    return ary;
 
154
}
 
155
 
 
156
void *frt_rb_data_ptr(VALUE val)
 
157
{
 
158
    Check_Type(val, T_DATA);
 
159
    return DATA_PTR(val);
 
160
}
 
161
 
 
162
char *
 
163
rs2s(VALUE rstr)
 
164
{
 
165
    return (char *)(RSTRING(rstr)->ptr ? RSTRING(rstr)->ptr : EMPTY_STRING);
 
166
}
 
167
 
 
168
char *
 
169
nstrdup(VALUE rstr)
 
170
{
 
171
    char *old = rs2s(rstr);
 
172
    int len = RSTRING(rstr)->len;
 
173
    char *new = ALLOC_N(char, len + 1);
 
174
    memcpy(new, old, len + 1);
 
175
    return new;
 
176
}
 
177
 
 
178
char *
 
179
frt_field(VALUE rfield)
 
180
{
 
181
    switch (TYPE(rfield)) {
 
182
        case T_SYMBOL:
 
183
            return rb_id2name(SYM2ID(rfield));
 
184
        case T_STRING:
 
185
            return rs2s(rfield);
 
186
        default:
 
187
            rb_raise(rb_eArgError, "field name must be a symbol");
 
188
    }
 
189
    return NULL;
 
190
}
 
191
 
 
192
/*
 
193
 * Json Exportation - Loading each LazyDoc and formatting them into json
 
194
 * This code is designed to get a VERY FAST json string, the goal was speed,
 
195
 * not sexiness.
 
196
 * Jeremie 'ahFeel' BORDIER
 
197
 * ahFeel@rift.Fr
 
198
 */
 
199
char *
 
200
json_concat_string(char *s, char *field)
 
201
{
 
202
    *(s++) = '"';
 
203
        while (*field) {
 
204
                if (*field == '"') {
 
205
            *(s++) = '\'';
 
206
            *(s++) = *(field++);
 
207
            *(s++) = '\'';
 
208
        }
 
209
        else {
 
210
            *(s++) = *(field++);
 
211
        }
 
212
    }
 
213
    *(s++) = '"';
 
214
    return s;
 
215
}
 
216
 
 
217
static VALUE error_map;
 
218
 
 
219
VALUE frt_get_error(const char *err_type)
 
220
{
 
221
    VALUE error_class;
 
222
    if (Qnil != (error_class = rb_hash_aref(error_map, rb_intern(err_type)))) {
 
223
        return error_class;
 
224
    }
 
225
    return rb_eStandardError;
 
226
}
 
227
 
 
228
#define FRT_BUF_SIZ 2046
 
229
#ifdef FRT_HAS_VARARGS
 
230
void vfrt_rb_raise(const char *file, int line_num, const char *func,
 
231
                   const char *err_type, const char *fmt, va_list args)
 
232
#else
 
233
void V_FRT_EXIT(const char *err_type, const char *fmt, va_list args)
 
234
#endif
 
235
{
 
236
    char buf[FRT_BUF_SIZ];
 
237
    size_t so_far = 0;
 
238
#ifdef FRT_HAS_VARARGS
 
239
    snprintf(buf, FRT_BUF_SIZ, "%s occured at <%s>:%d in %s\n",
 
240
            err_type, file, line_num, func);
 
241
#else
 
242
    snprintf(buf, FRT_BUF_SIZ, "%s occured:\n", err_type);
 
243
#endif
 
244
    so_far = strlen(buf);
 
245
    vsnprintf(buf + so_far, FRT_BUF_SIZ - so_far, fmt, args);
 
246
 
 
247
    so_far = strlen(buf);
 
248
    if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') {
 
249
        snprintf(buf + so_far, FRT_BUF_SIZ - so_far, " %s", strerror(errno));
 
250
        so_far = strlen(buf);
 
251
    }
 
252
 
 
253
    snprintf(buf + so_far, FRT_BUF_SIZ - so_far, "\n");
 
254
    rb_raise(frt_get_error(err_type), buf);
 
255
}
 
256
 
 
257
#ifdef FRT_HAS_VARARGS
 
258
void frt_rb_raise(const char *file, int line_num, const char *func,
 
259
                  const char *err_type, const char *fmt, ...)
 
260
#else
 
261
void FRT_EXIT(const char *err_type, const char *fmt, ...)
 
262
#endif
 
263
{
 
264
    va_list args;
 
265
    va_start(args, fmt);
 
266
#ifdef FRT_HAS_VARARGS
 
267
    vfrt_rb_raise(file, line_num, func, err_type, fmt, args);
 
268
#else
 
269
    V_FRT_EXIT(err_type, fmt, args);
 
270
#endif
 
271
    va_end(args);
 
272
}
 
273
 
 
274
/****************************************************************************
 
275
 *
 
276
 * Term Methods
 
277
 *
 
278
 ****************************************************************************/
 
279
static ID id_field;
 
280
static ID id_text;
 
281
 
 
282
VALUE frt_get_term(const char *field, const char *text)
 
283
{
 
284
    return rb_struct_new(cTerm,
 
285
                         ID2SYM(rb_intern(field)),
 
286
                         rb_str_new2(text),
 
287
                         NULL);
 
288
}
 
289
 
 
290
static VALUE frt_term_to_s(VALUE self)
 
291
{
 
292
    VALUE rstr;
 
293
    VALUE rfield = rb_funcall(self, id_field, 0); 
 
294
    VALUE rtext = rb_funcall(self, id_text, 0); 
 
295
    char *field = StringValuePtr(rfield);
 
296
    char *text = StringValuePtr(rtext);
 
297
    char *term_str = ALLOC_N(char,
 
298
                             5 + RSTRING(rfield)->len + RSTRING(rtext)->len);
 
299
    sprintf(term_str, "%s:%s", field, text);
 
300
    rstr = rb_str_new2(term_str);
 
301
    free(term_str);
 
302
    return rstr;
 
303
}
 
304
/*
 
305
 *  Document-class: Ferret::Term
 
306
 *
 
307
 *  == Summary
 
308
 *
 
309
 *  A Term holds a term from a document and its field name (as a Symbol).
 
310
 */
 
311
void Init_Term(void)
 
312
{
 
313
    const char *term_class = "Term";
 
314
    cTerm = rb_struct_define(term_class, "field", "text", NULL);
 
315
    rb_set_class_path(cTerm, mFerret, term_class);
 
316
    rb_const_set(mFerret, rb_intern(term_class), cTerm);
 
317
    rb_define_method(cTerm, "to_s", frt_term_to_s, 0);
 
318
    id_field = rb_intern("field");
 
319
    id_text = rb_intern("text");
 
320
}
 
321
 
 
322
/*
 
323
 *  Document-module: Ferret
 
324
 *
 
325
 *  See the README
 
326
 */
 
327
void Init_Ferret(void)
 
328
{
 
329
    mFerret = rb_define_module("Ferret");
 
330
    Init_Term();
 
331
}
 
332
 
 
333
void Init_ferret_ext(void)
 
334
{
 
335
    VALUE cParseError;
 
336
    VALUE cStateError;
 
337
    VALUE cFileNotFoundError;
 
338
 
 
339
    /* initialize object map */
 
340
    object_map = h_new(&value_hash, &value_eq, NULL, NULL);
 
341
 
 
342
    /* IDs */
 
343
    id_new = rb_intern("new");
 
344
    id_call = rb_intern("call");
 
345
    id_eql = rb_intern("eql?");
 
346
    id_hash = rb_intern("hash");
 
347
 
 
348
    id_capacity = rb_intern("capacity");
 
349
    id_less_than = rb_intern("less_than");
 
350
    id_lt = rb_intern("<");
 
351
 
 
352
    id_mkdir_p = rb_intern("mkdir_p");
 
353
    id_is_directory = rb_intern("directory?");
 
354
    id_close = rb_intern("close");
 
355
 
 
356
    id_cclass = rb_intern("cclass");
 
357
 
 
358
    id_data = rb_intern("@data");
 
359
 
 
360
    /* Symbols */
 
361
    sym_yes = ID2SYM(rb_intern("yes"));;
 
362
    sym_no = ID2SYM(rb_intern("no"));;
 
363
    sym_true = ID2SYM(rb_intern("true"));;
 
364
    sym_false = ID2SYM(rb_intern("false"));;
 
365
    sym_path = ID2SYM(rb_intern("path"));;
 
366
    sym_dir = ID2SYM(rb_intern("dir"));;
 
367
 
 
368
    /* Inits */
 
369
    Init_Ferret();
 
370
    Init_Utils();
 
371
    Init_Analysis();
 
372
    Init_Store();
 
373
    Init_Index();
 
374
    Init_Search();
 
375
    Init_QueryParser();
 
376
 
 
377
    /* Error Classes */
 
378
    cParseError =
 
379
        rb_define_class_under(mFerret, "ParseError", rb_eStandardError);
 
380
    cStateError =
 
381
        rb_define_class_under(mFerret, "StateError", rb_eStandardError);
 
382
    cFileNotFoundError =
 
383
        rb_define_class_under(mFerret, "FileNotFoundError", rb_eIOError);
 
384
 
 
385
    error_map = rb_hash_new();
 
386
    rb_hash_aset(error_map, rb_intern("Exception"),         rb_eStandardError);
 
387
    rb_hash_aset(error_map, rb_intern("IO Error"),          rb_eIOError);
 
388
    rb_hash_aset(error_map, rb_intern("File Not Found Error"),
 
389
                                                            cFileNotFoundError);
 
390
    rb_hash_aset(error_map, rb_intern("Argument Error"),    rb_eArgError);
 
391
    rb_hash_aset(error_map, rb_intern("End-of-File Error"), rb_eEOFError);
 
392
    rb_hash_aset(error_map, rb_intern("Unsupported Function Error"),
 
393
                                                            rb_eNotImpError);
 
394
    rb_hash_aset(error_map, rb_intern("State Error"),       cStateError);
 
395
    rb_hash_aset(error_map, rb_intern("ParseError"),        cParseError);
 
396
    rb_hash_aset(error_map, rb_intern("Memory Error"),      rb_eNoMemError);
 
397
    rb_hash_aset(error_map, rb_intern("Index Error"),       rb_eIndexError);
 
398
    rb_hash_aset(error_map, rb_intern("Lock Error"),        cLockError);
 
399
 
 
400
    rb_define_const(mFerret, "EXCEPTION_MAP", error_map);
 
401
    rb_define_const(mFerret, "FIX_INT_MAX", INT2FIX(INT_MAX >> 1));
 
402
}