isomorfeus-ferret 0.13.11 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,705 @@
1
+ #include "frt_index.h"
2
+ #include "isomorfeus_ferret.h"
3
+
4
+ extern VALUE rb_hash_update(int argc, VALUE *argv, VALUE self);
5
+
6
+ extern VALUE sym_each;
7
+ extern ID id_eql;
8
+
9
+ static VALUE sym_each_key;
10
+ static VALUE sym_each_value;
11
+ static ID id_compact;
12
+ static ID id_equal;
13
+ static ID id_except;
14
+ static ID id_fields;
15
+ static ID id_flatten;
16
+ static ID id_ge;
17
+ static ID id_get;
18
+ static ID id_gt;
19
+ static ID id_inspect;
20
+ static ID id_invert;
21
+ static ID id_le;
22
+ static ID id_merge_bang;
23
+ static ID id_reject;
24
+ static ID id_select;
25
+ static ID id_size;
26
+ static ID id_slice;
27
+ static ID id_to_h;
28
+ static ID id_to_proc;
29
+ static ID id_transform_keys;
30
+ static ID id_transform_values;
31
+
32
+ FrtLazyDoc empty_lazy_doc = {0};
33
+ VALUE cLazyDoc;
34
+
35
+ typedef struct rLazyDoc {
36
+ FrtHash *hash;
37
+ FrtLazyDoc *doc;
38
+ } rLazyDoc;
39
+
40
+ /****************************************************************************
41
+ *
42
+ * LazyDoc Methods
43
+ *
44
+ ****************************************************************************/
45
+
46
+ static void frb_ld_free(void *p) {
47
+ rLazyDoc *rld = (rLazyDoc *)p;
48
+ if (rld->doc != &empty_lazy_doc) {
49
+ frt_lazy_doc_close(rld->doc);
50
+ }
51
+ frt_h_destroy(rld->hash);
52
+ free(rld);
53
+ }
54
+
55
+ static size_t frb_ld_size(const void *p) {
56
+ return sizeof(rLazyDoc);
57
+ (void)p;
58
+ }
59
+
60
+ void rld_mark(void *key, void *value, void *arg) {
61
+ rb_gc_mark((VALUE)value);
62
+ }
63
+
64
+ static void frb_ld_mark(void *p) {
65
+ frt_h_each(((rLazyDoc *)p)->hash, rld_mark, NULL);
66
+ }
67
+
68
+ const rb_data_type_t frb_ld_t = {
69
+ .wrap_struct_name = "FrbLazyDoc",
70
+ .function = {
71
+ .dmark = frb_ld_mark,
72
+ .dfree = frb_ld_free,
73
+ .dsize = frb_ld_size,
74
+ .dcompact = NULL,
75
+ .reserved = {0},
76
+ },
77
+ .parent = NULL,
78
+ .data = NULL,
79
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
80
+ };
81
+
82
+ VALUE frb_get_lazy_doc(FrtLazyDoc *lazy_doc) {
83
+ rLazyDoc *rld = FRT_ALLOC(rLazyDoc);
84
+ rld->hash = frt_h_new_ptr(NULL);
85
+ rld->doc = lazy_doc;
86
+ return TypedData_Wrap_Struct(cLazyDoc, &frb_ld_t, rld);
87
+ }
88
+
89
+ static VALUE frb_ld_alloc(VALUE rclass) {
90
+ rLazyDoc *rld = FRT_ALLOC(rLazyDoc);
91
+ rld->hash = frt_h_new_ptr(NULL);
92
+ rld->doc = &empty_lazy_doc;
93
+ return TypedData_Wrap_Struct(rclass, &frb_ld_t, rld);
94
+ }
95
+
96
+ static VALUE frb_ld_df_load(VALUE self, VALUE rkey, FrtLazyDocField *lazy_df) {
97
+ rLazyDoc *rld = DATA_PTR(self);
98
+ VALUE rdata;
99
+ if (lazy_df->size == 1) {
100
+ char *data = frt_lazy_df_get_data(lazy_df, 0);
101
+ rdata = rb_str_new(data, lazy_df->data[0].length);
102
+ rb_enc_associate(rdata, lazy_df->data[0].encoding);
103
+ } else {
104
+ int i;
105
+ VALUE rstr;
106
+ rdata = rb_ary_new2(lazy_df->size);
107
+ for (i = 0; i < lazy_df->size; i++) {
108
+ char *data = frt_lazy_df_get_data(lazy_df, i);
109
+ rstr = rb_str_new(data, lazy_df->data[i].length);
110
+ rb_enc_associate(rstr, lazy_df->data[i].encoding);
111
+ rb_ary_store(rdata, i, rstr);
112
+ }
113
+ }
114
+ frt_h_set(rld->hash, (void *)rkey, (void *)rdata);
115
+ return rdata;
116
+ }
117
+
118
+ /*
119
+ * call-seq:
120
+ * lazy_doc.load -> lazy_doc
121
+ *
122
+ * Load all unloaded fields in the document from the index.
123
+ */
124
+ static VALUE frb_ld_load(VALUE self) {
125
+ rLazyDoc *rld = DATA_PTR(self);
126
+ FrtLazyDoc *ld = rld->doc;
127
+ if (ld->loaded) return self;
128
+ int i;
129
+ FrtLazyDocField *lazy_df;
130
+ for (i = 0; i < ld->size; i++) {
131
+ lazy_df = ld->fields[i];
132
+ if (!(lazy_df->loaded)) frb_ld_df_load(self, ID2SYM(lazy_df->name), lazy_df);
133
+ }
134
+ ld->loaded = true;
135
+ return self;
136
+ }
137
+
138
+ /*
139
+ * call-seq:
140
+ * lazy_doc.fields -> array of available fields
141
+ *
142
+ * Returns the list of fields stored for this particular document. If you try
143
+ * to access any of these fields in the document the field will be loaded.
144
+ * Try to access any other field an nil will be returned.
145
+ */
146
+ static VALUE frb_ld_fields(VALUE self) {
147
+ FrtLazyDoc *ld = ((rLazyDoc *)DATA_PTR(self))->doc;
148
+ VALUE rfields = rb_ivar_get(self, id_fields);
149
+ if (rfields == Qnil) {
150
+ int i;
151
+ rfields = rb_ary_new2(ld->size);
152
+ for (i = 0; i < ld->size; i++) {
153
+ rb_ary_store(rfields, i, ID2SYM(ld->fields[i]->name));
154
+ }
155
+ rb_ivar_set(self, id_fields, rfields);
156
+ }
157
+ return rfields;
158
+ }
159
+
160
+ void rld_to_hash(void *key, void *value, void *arg) {
161
+ rb_hash_aset((VALUE)arg, (VALUE)key, (VALUE)value);
162
+ }
163
+
164
+ static VALUE frb_ld_to_h(VALUE self) {
165
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
166
+ if (!rld->doc->loaded) frb_ld_load(self);
167
+ VALUE hash = rb_hash_new();
168
+ frt_h_each(rld->hash, rld_to_hash, (void *)hash);
169
+ return hash;
170
+ }
171
+
172
+ static VALUE frb_ld_lt(VALUE self, VALUE other) {
173
+ VALUE other_h;
174
+ if (TYPE(other) == T_HASH) {
175
+ other_h = other;
176
+ } else {
177
+ rLazyDoc *other_rld;
178
+ TypedData_Get_Struct(other, rLazyDoc, &frb_ld_t, other_rld);
179
+ other_h = frb_ld_to_h(other);
180
+ }
181
+ VALUE self_h = frb_ld_to_h(self);
182
+ return rb_funcall(self_h, id_lt, 1, other_h);
183
+ }
184
+
185
+ static VALUE frb_ld_le(VALUE self, VALUE other) {
186
+ VALUE other_h;
187
+ if (TYPE(other) == T_HASH) {
188
+ other_h = other;
189
+ } else {
190
+ rLazyDoc *other_rld;
191
+ TypedData_Get_Struct(other, rLazyDoc, &frb_ld_t, other_rld);
192
+ other_h = frb_ld_to_h(other);
193
+ }
194
+ VALUE self_h = frb_ld_to_h(self);
195
+ return rb_funcall(self_h, id_le, 1, other_h);
196
+ }
197
+
198
+ static VALUE frb_ld_equal(VALUE self, VALUE other) {
199
+ FrtLazyDoc *ld = ((rLazyDoc *)DATA_PTR(self))->doc;
200
+ int other_size;
201
+ VALUE other_h;
202
+ if (TYPE(other) == T_HASH) {
203
+ other_h = other;
204
+ other_size = FIX2INT(rb_funcall(other_h, id_size, 0));
205
+ } else {
206
+ rLazyDoc *other_rld;
207
+ TypedData_Get_Struct(other, rLazyDoc, &frb_ld_t, other_rld);
208
+ other_h = frb_ld_to_h(other);
209
+ other_size = other_rld->doc->size;
210
+ }
211
+ if (ld->size == other_size) {
212
+ VALUE self_h = frb_ld_to_h(self);
213
+ return rb_funcall(self_h, id_equal, 1, other_h);
214
+ }
215
+ return Qfalse;
216
+ }
217
+
218
+ static VALUE frb_ld_gt(VALUE self, VALUE other) {
219
+ VALUE other_h;
220
+ if (TYPE(other) == T_HASH) {
221
+ other_h = other;
222
+ } else {
223
+ rLazyDoc *other_rld;
224
+ TypedData_Get_Struct(other, rLazyDoc, &frb_ld_t, other_rld);
225
+ other_h = frb_ld_to_h(other);
226
+ }
227
+ VALUE self_h = frb_ld_to_h(self);
228
+ return rb_funcall(self_h, id_gt, 1, other_h);
229
+ }
230
+
231
+ static VALUE frb_ld_ge(VALUE self, VALUE other) {
232
+ VALUE other_h;
233
+ if (TYPE(other) == T_HASH) {
234
+ other_h = other;
235
+ } else {
236
+ rLazyDoc *other_rld;
237
+ TypedData_Get_Struct(other, rLazyDoc, &frb_ld_t, other_rld);
238
+ other_h = frb_ld_to_h(other);
239
+ }
240
+ VALUE self_h = frb_ld_to_h(self);
241
+ return rb_funcall(self_h, id_ge, 1, other_h);
242
+ }
243
+
244
+ static VALUE frb_ld_get(VALUE self, VALUE key) {
245
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
246
+ VALUE rval = (VALUE)frt_h_get(rld->hash, (void *)key);
247
+ if (rval) return rval;
248
+ if (TYPE(key) != T_SYMBOL) rb_raise(rb_eArgError, "key, must be a symbol");
249
+ FrtLazyDocField *df = frt_h_get(rld->doc->field_dictionary, (void *)SYM2ID(key));
250
+ if (df) return frb_ld_df_load(self, key, df);
251
+ return Qnil;
252
+ }
253
+
254
+ void rld_any(void *key, void *value, void *arg) {
255
+ VALUE *v = arg;
256
+ *v = rb_yield_values(2, (VALUE)key, (VALUE)value);
257
+ }
258
+
259
+ static VALUE frb_ld_assoc(VALUE self, VALUE key) {
260
+ rLazyDoc *rld = DATA_PTR(self);
261
+ VALUE value = (VALUE)frt_h_get(rld->hash, (void *)key);
262
+ if (!value) {
263
+ FrtLazyDoc *ld = rld->doc;
264
+ FrtLazyDocField *df = frt_h_get(ld->field_dictionary, (void *)SYM2ID(key));
265
+ if (!df) return Qnil;
266
+ if (df && !df->loaded) value = frb_ld_df_load(self, key, df);
267
+ }
268
+ VALUE a[2] = {key, value};
269
+ return rb_ary_new_from_values(2, a);
270
+ }
271
+
272
+ static VALUE frb_ld_any(int argc, VALUE *argv, VALUE self) {
273
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
274
+ FrtLazyDoc *ld = rld->doc;
275
+ if (argc == 0) {
276
+ if (!rb_block_given_p()) {
277
+ return (ld->size > 0) ? Qtrue : Qfalse;
278
+ } else {
279
+ if (!ld->loaded) frb_ld_load(self);
280
+ VALUE res = Qnil;
281
+ frt_h_each(rld->hash, rld_any, &res);
282
+ if (RTEST(res)) return Qtrue;
283
+ else return Qfalse;
284
+ }
285
+ } else if (argc == 1) {
286
+ VALUE obj = argv[0];
287
+ VALUE key = rb_funcall(obj, id_get, 1, 0);
288
+ VALUE a = frb_ld_assoc(self, key);
289
+ return rb_funcall(a, id_equal, 1, obj);
290
+ }
291
+ rb_raise(rb_eArgError, "at most one arg may be given");
292
+ return Qfalse;
293
+ }
294
+
295
+ static VALUE frb_ld_compact(VALUE self) {
296
+ VALUE hash = frb_ld_to_h(self);
297
+ return rb_funcall(hash, id_compact, 0);
298
+ }
299
+
300
+ static VALUE frb_ld_dig(int argc, VALUE *argv, VALUE self) {
301
+ if (argc == 0) rb_raise(rb_eArgError, "at least a key must be given");
302
+ VALUE key = argv[0];
303
+ if (TYPE(key) != T_SYMBOL) rb_raise(rb_eArgError, "first arg, key, must be a symbol");
304
+ VALUE value = frb_ld_get(self, key);
305
+ if (argc == 1) return value;
306
+ if (TYPE(value) == T_ARRAY && argc == 2) {
307
+ return rb_ary_entry(value, NUM2LONG(argv[1]));
308
+ }
309
+ return Qnil;
310
+ }
311
+
312
+ static VALUE frb_ld_to_enum(VALUE self) {
313
+ return rb_enumeratorize(self, sym_each, 0, NULL);
314
+ }
315
+
316
+ static VALUE frb_ld_to_key_enum(VALUE self) {
317
+ return rb_enumeratorize(self, sym_each_key, 0, NULL);
318
+ }
319
+
320
+ static VALUE frb_ld_to_value_enum(VALUE self) {
321
+ return rb_enumeratorize(self, sym_each_value, 0, NULL);
322
+ }
323
+
324
+ void rld_each(void *key, void *value, void *arg) {
325
+ rb_yield_values(2, (VALUE)key, (VALUE)value);
326
+ }
327
+
328
+ static VALUE frb_ld_each(VALUE self) {
329
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
330
+ FrtLazyDoc *ld = rld->doc;
331
+ if (!ld->loaded) frb_ld_load(self);
332
+ if (rb_block_given_p()) {
333
+ frt_h_each(rld->hash, rld_each, NULL);
334
+ return self;
335
+ } else {
336
+ return frb_ld_to_enum(self);
337
+ }
338
+ }
339
+
340
+ void rld_each_key(void *key, void *value, void *arg) {
341
+ rb_yield((VALUE)key);
342
+ }
343
+
344
+ static VALUE frb_ld_each_key(VALUE self) {
345
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
346
+ FrtLazyDoc *ld = rld->doc;
347
+ if (!ld->loaded) frb_ld_load(self);
348
+ if (rb_block_given_p()) {
349
+ frt_h_each(rld->hash, rld_each_key, NULL);
350
+ return self;
351
+ } else {
352
+ return frb_ld_to_key_enum(self);
353
+ }
354
+ }
355
+
356
+ void rld_each_value(void *key, void *value, void *arg) {
357
+ rb_yield((VALUE)value);
358
+ }
359
+
360
+ static VALUE frb_ld_each_value(VALUE self) {
361
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
362
+ FrtLazyDoc *ld = rld->doc;
363
+ if (!ld->loaded) frb_ld_load(self);
364
+ if (rb_block_given_p()) {
365
+ frt_h_each(rld->hash, rld_each_value, NULL);
366
+ return self;
367
+ } else {
368
+ return frb_ld_to_value_enum(self);
369
+ }
370
+ }
371
+
372
+ static VALUE frb_ld_empty(VALUE self) {
373
+ FrtLazyDoc *ld = ((rLazyDoc *)DATA_PTR(self))->doc;
374
+ return (ld->size == 0) ? Qtrue : Qfalse;
375
+ }
376
+
377
+ static VALUE frb_ld_eql(VALUE self, VALUE other) {
378
+ FrtLazyDoc *ld = ((rLazyDoc *)DATA_PTR(self))->doc;
379
+ rLazyDoc *other_rld;
380
+ int other_size;
381
+ VALUE other_h;
382
+ if (TYPE(other) == T_HASH) {
383
+ other_h = other;
384
+ other_size = FIX2INT(rb_funcall(other_h, id_size, 0));
385
+ } else {
386
+ TypedData_Get_Struct(other, rLazyDoc, &frb_ld_t, other_rld);
387
+ other_h = frb_ld_to_h(other);
388
+ other_size = other_rld->doc->size;
389
+ }
390
+ if (ld->size == other_size) {
391
+ VALUE self_h = frb_ld_to_h(self);
392
+ return rb_funcall(self_h, id_eql, 1, other_h);
393
+ }
394
+ return Qfalse;
395
+ }
396
+
397
+ static VALUE frb_ld_except(int argc, VALUE *argv, VALUE self) {
398
+ VALUE hash = frb_ld_to_h(self);
399
+ return rb_funcallv(hash, id_except, argc, argv);
400
+ }
401
+
402
+ static VALUE frb_ld_fetch(int argc, VALUE *argv, VALUE self) {
403
+ VALUE key = argv[0];
404
+ if (TYPE(key) != T_SYMBOL) rb_raise(rb_eArgError, "first arg must be a symbol");
405
+ VALUE res = frb_ld_get(self, key);
406
+ if (argc == 1) {
407
+ if (res == Qnil && rb_block_given_p()) return rb_yield(key);
408
+ return res;
409
+ }
410
+ if (argc == 2) {
411
+ if (res == Qnil) return argv[1];
412
+ return res;
413
+ }
414
+ rb_raise(rb_eArgError, "too many args, only two allowed: key, default_value");
415
+ }
416
+
417
+ static VALUE frb_ld_fetch_values(int argc, VALUE *argv, VALUE self) {
418
+ rLazyDoc *rld = DATA_PTR(self);
419
+ if (!rld->doc->loaded) frb_ld_load(self);
420
+ VALUE ary = rb_ary_new();
421
+ int i;
422
+ VALUE value;
423
+ for (i=0; i<argc; i++) {
424
+ value = (VALUE)frt_h_get(rld->hash, (void *)argv[i]);
425
+ if (value) rb_ary_push(ary, value);
426
+ else if (rb_block_given_p()) {
427
+ value = rb_yield(argv[i]);
428
+ rb_ary_push(ary, value);
429
+ }
430
+ }
431
+ if (FIX2INT(rb_funcall(ary, id_size, 0)) == 0) rb_raise(rb_eException, "nothing found for given keys");
432
+ return ary;
433
+ }
434
+
435
+ static VALUE frb_ld_filter(VALUE self) {
436
+ VALUE hash = frb_ld_to_h(self);
437
+ return rb_funcall_passing_block(hash, id_select, 0, NULL);
438
+ }
439
+
440
+ void rld_flatten(void *key, void *value, void *arg) {
441
+ rb_ary_push((VALUE)arg, (VALUE)key);
442
+ rb_ary_push((VALUE)arg, (VALUE)value);
443
+ }
444
+
445
+ static VALUE frb_ld_flatten(int argc, VALUE *argv, VALUE self) {
446
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
447
+ if (!rld->doc->loaded) frb_ld_load(self);
448
+ VALUE ary = rb_ary_new();
449
+ frt_h_each(rld->hash, rld_flatten, (void *)ary);
450
+ if (argc == 1) {
451
+ int level = FIX2INT(argv[0]) - 1;
452
+ VALUE rlevel = INT2FIX(level);
453
+ rb_funcall(ary, id_flatten, 1, rlevel);
454
+ }
455
+ return ary;
456
+ }
457
+
458
+ static VALUE frb_ld_has_key(VALUE self, VALUE key) {
459
+ if (TYPE(key) != T_SYMBOL) rb_raise(rb_eArgError, "arg must be a symbol");
460
+ VALUE hk = Qfalse;
461
+ FrtLazyDoc *ld = ((rLazyDoc *)DATA_PTR(self))->doc;
462
+ ID dfkey = SYM2ID(key);
463
+ FrtLazyDocField *df = frt_h_get(ld->field_dictionary, (void *)dfkey);
464
+ if (df) hk = Qtrue;
465
+ return hk;
466
+ }
467
+
468
+ static VALUE frb_ld_has_value(VALUE self, VALUE value) {
469
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
470
+ FrtLazyDoc *ld = rld->doc;
471
+ if (!ld->loaded) frb_ld_load(self);
472
+ int i;
473
+ VALUE hvalue;
474
+ for (i=0; i<ld->size; i++) {
475
+ hvalue = (VALUE)frt_h_get(rld->hash, (void *)ID2SYM(ld->fields[i]->name));
476
+ hvalue = rb_funcall(hvalue, id_equal, 1, value);
477
+ if (hvalue == Qtrue) return Qtrue;
478
+ }
479
+ return Qfalse;
480
+ }
481
+
482
+ static VALUE frb_ld_inspect(VALUE self) {
483
+ VALUE hash = frb_ld_to_h(self);
484
+ return rb_funcall(hash, id_inspect, 0);
485
+ }
486
+
487
+ static VALUE frb_ld_invert(VALUE self) {
488
+ VALUE hash = frb_ld_to_h(self);
489
+ return rb_funcall(hash, id_invert, 0);
490
+ }
491
+
492
+ static VALUE frb_ld_key(VALUE self, VALUE value) {
493
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
494
+ FrtLazyDoc *ld = rld->doc;
495
+ if (!ld->loaded) frb_ld_load(self);
496
+ int i;
497
+ VALUE hvalue;
498
+ for (i=0; i<ld->size; i++) {
499
+ hvalue = (VALUE)frt_h_get(rld->hash, (void *)ID2SYM(ld->fields[i]->name));
500
+ hvalue = rb_funcall(hvalue, id_equal, 1, value);
501
+ if (hvalue == Qtrue) return ID2SYM(ld->fields[i]->name);
502
+ }
503
+ return Qnil;
504
+ }
505
+
506
+ static VALUE frb_ld_length(VALUE self) {
507
+ FrtLazyDoc *ld = ((rLazyDoc *)DATA_PTR(self))->doc;
508
+ return INT2FIX(ld->size);
509
+ }
510
+
511
+ static VALUE frb_ld_merge(int argc, VALUE *argv, VALUE self) {
512
+ rLazyDoc *rld = (rLazyDoc *)DATA_PTR(self);
513
+ if (!rld->doc->loaded) frb_ld_load(self);
514
+ VALUE hash = frb_ld_to_h(self);
515
+ return rb_funcall_passing_block(hash, id_merge_bang, argc, argv);
516
+ }
517
+
518
+ static VALUE frb_ld_rassoc(VALUE self, VALUE value) {
519
+ VALUE key = frb_ld_key(self, value);
520
+ if (key == Qnil) return Qnil;
521
+ VALUE a[2] = {key, value};
522
+ return rb_ary_new_from_values(2, a);
523
+ }
524
+
525
+ static VALUE frb_ld_reject(VALUE self) {
526
+ VALUE hash = frb_ld_to_h(self);
527
+ return rb_funcall_passing_block(hash, id_reject, 0, NULL);
528
+ }
529
+
530
+ static VALUE frb_ld_slice(int argc, VALUE *argv, VALUE self) {
531
+ VALUE hash = frb_ld_to_h(self);
532
+ return rb_funcallv(hash, id_slice, argc, argv);
533
+ }
534
+
535
+ void rld_to_a(void *key, void *value, void *arg) {
536
+ VALUE ary = rb_ary_new();
537
+ rb_ary_push(ary, (VALUE)key);
538
+ rb_ary_push(ary, (VALUE)value);
539
+ rb_ary_push((VALUE)arg, ary);
540
+ }
541
+
542
+ static VALUE frb_ld_to_a(VALUE self) {
543
+ rLazyDoc *rld = DATA_PTR(self);
544
+ if (!rld->doc->loaded) frb_ld_load(self);
545
+ VALUE ary = rb_ary_new();
546
+ frt_h_each(rld->hash, rld_to_a, (void *)ary);
547
+ return ary;
548
+ }
549
+
550
+ static VALUE frb_ld_to_ha(VALUE self) {
551
+ VALUE hash = frb_ld_to_h(self);
552
+ if (!rb_block_given_p()) return hash;
553
+ return rb_funcall_passing_block(hash, id_to_h, 0, NULL);
554
+ }
555
+
556
+ static VALUE frb_ld_to_proc(VALUE self) {
557
+ VALUE hash = frb_ld_to_h(self);
558
+ return rb_funcall(hash, id_to_proc, 0);
559
+ }
560
+
561
+ static VALUE frb_ld_transform_keys(int argc, VALUE *argv, VALUE self) {
562
+ VALUE hash = frb_ld_to_h(self);
563
+ return rb_funcall_passing_block(hash, id_transform_keys, argc, argv);
564
+ }
565
+
566
+ static VALUE frb_ld_transform_values(VALUE self) {
567
+ VALUE hash = frb_ld_to_h(self);
568
+ return rb_funcall_passing_block(hash, id_transform_values, 0, NULL);
569
+ }
570
+
571
+ void rld_values(void *key, void *value, void *arg) {
572
+ rb_ary_push((VALUE)arg, (VALUE)value);
573
+ }
574
+
575
+ static VALUE frb_ld_values(VALUE self) {
576
+ rLazyDoc *rld = DATA_PTR(self);
577
+ if (!rld->doc->loaded) frb_ld_load(self);
578
+ VALUE ary = rb_ary_new();
579
+ frt_h_each(rld->hash, rld_values, (void *)ary);
580
+ return ary;
581
+ }
582
+
583
+ static VALUE frb_ld_values_at(int argc, VALUE *argv, VALUE self) {
584
+ rLazyDoc *rld = DATA_PTR(self);
585
+ if (!rld->doc->loaded) frb_ld_load(self);
586
+ VALUE ary = rb_ary_new();
587
+ int i;
588
+ VALUE value;
589
+ for (i=0; i<argc; i++) {
590
+ value = (VALUE)frt_h_get(rld->hash, (void *)argv[i]);
591
+ if (value) rb_ary_push(ary, value);
592
+ else rb_ary_push(ary, Qnil);
593
+ }
594
+ return ary;
595
+ }
596
+
597
+ /*
598
+ * Document-class: Ferret::Index::LazyDoc
599
+ *
600
+ * == Summary
601
+ *
602
+ * When a document is retrieved from the index a LazyDoc is returned.
603
+ * It inherits from rubys Hash class, however it is read only.
604
+ * LazyDoc lazily adds fields to itself when they are accessed or
605
+ * automatically loads all fields if needed.
606
+ * To load all fields use the LazyDoc#load method.
607
+ * Methods from the Hash class, that would modify the LazyDoc itself,
608
+ * are not supported, .
609
+ *
610
+ * == Example
611
+ *
612
+ * doc = index_reader[0]
613
+ *
614
+ * doc.keys #=> []
615
+ * doc.values #=> []
616
+ * doc.fields #=> [:title, :content]
617
+ *
618
+ * title = doc[:title] #=> "the title"
619
+ * doc.keys #=> [:title]
620
+ * doc.values #=> ["the title"]
621
+ * doc.fields #=> [:title, :content]
622
+ *
623
+ * doc.load
624
+ * doc.keys #=> [:title, :content]
625
+ * doc.values #=> ["the title", "the content"]
626
+ * doc.fields #=> [:title, :content]
627
+ */
628
+ void Init_LazyDoc(void) {
629
+ sym_each_key = ID2SYM(rb_intern("each_key"));
630
+ sym_each_value = ID2SYM(rb_intern("each_value"));
631
+ id_compact = rb_intern("compact");
632
+ id_equal = rb_intern("==");
633
+ id_except = rb_intern("except");
634
+ id_fields = rb_intern("@fields");
635
+ id_flatten = rb_intern("flatten");
636
+ id_ge = rb_intern(">=");
637
+ id_get = rb_intern("[]");
638
+ id_gt = rb_intern(">");
639
+ id_inspect = rb_intern("inspect");
640
+ id_invert = rb_intern("invert");
641
+ id_le = rb_intern("<=");
642
+ id_merge_bang = rb_intern("merge!");
643
+ id_reject = rb_intern("reject");
644
+ id_select = rb_intern("select");
645
+ id_size = rb_intern("size");
646
+ id_slice = rb_intern("slice");
647
+ id_to_h = rb_intern("to_h");
648
+ id_to_proc = rb_intern("to_proc");
649
+ id_transform_keys = rb_intern("transform_keys");
650
+ id_transform_values = rb_intern("transform_values");
651
+
652
+ cLazyDoc = rb_define_class_under(mIndex, "LazyDoc", rb_cObject);
653
+ rb_include_module(cLazyDoc, rb_mEnumerable);
654
+ rb_define_alloc_func(cLazyDoc, frb_ld_alloc);
655
+ rb_define_method(cLazyDoc, "load", frb_ld_load, 0);
656
+ rb_define_method(cLazyDoc, "fields", frb_ld_fields, 0);
657
+ rb_define_method(cLazyDoc, "keys", frb_ld_fields, 0);
658
+ rb_define_method(cLazyDoc, "<", frb_ld_lt, 1);
659
+ rb_define_method(cLazyDoc, "<=", frb_ld_le, 1);
660
+ rb_define_method(cLazyDoc, "==", frb_ld_equal, 1);
661
+ rb_define_method(cLazyDoc, ">", frb_ld_gt, 1);
662
+ rb_define_method(cLazyDoc, ">=", frb_ld_ge, 1);
663
+ rb_define_method(cLazyDoc, "[]", frb_ld_get, 1);
664
+ rb_define_method(cLazyDoc, "any?", frb_ld_any, -1);
665
+ rb_define_method(cLazyDoc, "assoc", frb_ld_assoc, 1);
666
+ rb_define_method(cLazyDoc, "compact", frb_ld_compact, 0);
667
+ rb_define_method(cLazyDoc, "dig", frb_ld_dig, -1);
668
+ rb_define_method(cLazyDoc, "each", frb_ld_each, 0);
669
+ rb_define_method(cLazyDoc, "each_key", frb_ld_each_key, 0);
670
+ rb_define_method(cLazyDoc, "each_pair", frb_ld_each, 0);
671
+ rb_define_method(cLazyDoc, "each_value", frb_ld_each_value, 0);
672
+ rb_define_method(cLazyDoc, "empty?", frb_ld_empty, 0);
673
+ rb_define_method(cLazyDoc, "eql?", frb_ld_eql, 1);
674
+ rb_define_method(cLazyDoc, "except", frb_ld_except, -1);
675
+ rb_define_method(cLazyDoc, "fetch", frb_ld_fetch, -1);
676
+ rb_define_method(cLazyDoc, "fetch_values", frb_ld_fetch_values, -1);
677
+ rb_define_method(cLazyDoc, "filter", frb_ld_filter, 0);
678
+ rb_define_method(cLazyDoc, "flatten", frb_ld_flatten, -1);
679
+ rb_define_method(cLazyDoc, "has_key?", frb_ld_has_key, 1);
680
+ rb_define_method(cLazyDoc, "has_value?", frb_ld_has_value, 1);
681
+ rb_define_method(cLazyDoc, "include?", frb_ld_has_key, 1);
682
+ rb_define_method(cLazyDoc, "inspect", frb_ld_inspect, 0);
683
+ rb_define_method(cLazyDoc, "invert", frb_ld_invert, 0);
684
+ rb_define_method(cLazyDoc, "key", frb_ld_key, 1);
685
+ rb_define_method(cLazyDoc, "key?", frb_ld_has_key, 1);
686
+ rb_define_method(cLazyDoc, "length", frb_ld_length, 0);
687
+ rb_define_method(cLazyDoc, "member?", frb_ld_has_key, 1);
688
+ rb_define_method(cLazyDoc, "merge", frb_ld_merge, -1);
689
+ rb_define_method(cLazyDoc, "rassoc", frb_ld_rassoc, 1);
690
+ rb_define_method(cLazyDoc, "reject", frb_ld_reject, 0);
691
+ rb_define_method(cLazyDoc, "select", frb_ld_filter, 0);
692
+ rb_define_method(cLazyDoc, "size", frb_ld_length, 0);
693
+ rb_define_method(cLazyDoc, "slice", frb_ld_slice, -1);
694
+ rb_define_method(cLazyDoc, "to_a", frb_ld_to_a, 0);
695
+ rb_define_method(cLazyDoc, "to_enum", frb_ld_to_enum, 0);
696
+ rb_define_method(cLazyDoc, "to_h", frb_ld_to_ha, 0);
697
+ rb_define_method(cLazyDoc, "to_hash", frb_ld_to_h, 0);
698
+ rb_define_method(cLazyDoc, "to_proc", frb_ld_to_proc, 0);
699
+ rb_define_method(cLazyDoc, "to_s", frb_ld_inspect, 0);
700
+ rb_define_method(cLazyDoc, "transform_keys", frb_ld_transform_keys, -1);
701
+ rb_define_method(cLazyDoc, "transform_values", frb_ld_transform_values, 0);
702
+ rb_define_method(cLazyDoc, "value?", frb_ld_has_value, 1);
703
+ rb_define_method(cLazyDoc, "values", frb_ld_values, 0);
704
+ rb_define_method(cLazyDoc, "values_at", frb_ld_values_at, -1);
705
+ }
@@ -2,7 +2,7 @@
2
2
  #include "isomorfeus_ferret.h"
3
3
 
4
4
  static VALUE cQueryParser;
5
- VALUE cQueryParseException;
5
+ static VALUE cQueryParseException;
6
6
 
7
7
  extern VALUE sym_analyzer;
8
8
  static VALUE sym_wild_card_downcase;