ferret 0.10.4 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -112,7 +112,7 @@ EXT_SRC.each do |fn|
112
112
  mv dest_fn + ".out", dest_fn
113
113
  end
114
114
  end
115
- end
115
+ end if File.exists?("../c")
116
116
 
117
117
  desc "Build the extension"
118
118
  task :ext => ["ext/#{EXT}"] + SRC
@@ -843,9 +843,14 @@ static Token *std_next(TokenStream *ts)
843
843
  /* strip possesive */
844
844
  if ((t[-1] == 's' || t[-1] == 'S') && t[-2] == '\'') {
845
845
  t -= 2;
846
+ tk_set_ts(&(CTS(ts)->token), start, t, ts->text, 1);
847
+ CTS(ts)->token.end += 2;
848
+ }
849
+ else {
850
+ tk_set_ts(&(CTS(ts)->token), start, t, ts->text, 1);
846
851
  }
847
852
 
848
- return tk_set_ts(&(CTS(ts)->token), start, t, ts->text, 1);
853
+ return &(CTS(ts)->token);
849
854
  }
850
855
 
851
856
  if (*t == '&') { /* apostrophe case. */
@@ -1434,6 +1439,7 @@ Analyzer *per_field_analyzer_new(Analyzer *default_a)
1434
1439
 
1435
1440
  a->destroy_i = &pfa_destroy_i;
1436
1441
  a->get_ts = pfa_get_ts;
1442
+ a->ref_cnt = 1;
1437
1443
 
1438
1444
  return a;
1439
1445
  }
@@ -14,6 +14,7 @@ BitVector *bv_new_capa(int capa)
14
14
  bv->count = 0;
15
15
  bv->curr_bit = -1;
16
16
  bv->extends_as_ones = 0;
17
+ bv->ref_cnt = 1;
17
18
  return bv;
18
19
  }
19
20
 
@@ -24,8 +25,10 @@ BitVector *bv_new()
24
25
 
25
26
  void bv_destroy(BitVector * bv)
26
27
  {
27
- free(bv->bits);
28
- free(bv);
28
+ if (--(bv->ref_cnt) == 0) {
29
+ free(bv->bits);
30
+ free(bv);
31
+ }
29
32
  }
30
33
 
31
34
  void bv_set(BitVector * bv, int bit)
@@ -23,6 +23,7 @@ typedef struct BitVector
23
23
  int curr_bit;
24
24
 
25
25
  bool extends_as_ones : 1;
26
+ int ref_cnt;
26
27
  } BitVector;
27
28
 
28
29
  /**
@@ -10,10 +10,12 @@ static HashTable *object_map;
10
10
 
11
11
  /* IDs */
12
12
  ID id_new;
13
+ ID id_call;
14
+ ID id_eql;
15
+ ID id_hash;
13
16
  ID id_capacity;
14
17
  ID id_less_than;
15
18
  ID id_lt;
16
- ID id_call;
17
19
  ID id_is_directory;
18
20
  ID id_close;
19
21
  ID id_cclass;
@@ -36,6 +38,7 @@ VALUE mStringHelper;
36
38
  VALUE mSpans;
37
39
 
38
40
  /* Classes */
41
+ VALUE cTerm;
39
42
  /*
40
43
  */
41
44
 
@@ -98,13 +101,6 @@ VALUE frt_data_alloc(VALUE klass)
98
101
  return Frt_Make_Struct(klass);
99
102
  }
100
103
 
101
- VALUE frt_define_class_under(VALUE module, char *name, VALUE super)
102
- {
103
- VALUE klass = rb_define_class_under(module, name, super);
104
- rb_ivar_set(klass, id_cclass, Qtrue);
105
- return klass;
106
- }
107
-
108
104
  void frt_deref_free(void *p)
109
105
  {
110
106
  object_del(p);
@@ -233,6 +229,54 @@ void FRT_EXIT(const char *err_type, const char *fmt, ...)
233
229
  va_end(args);
234
230
  }
235
231
 
232
+ /****************************************************************************
233
+ *
234
+ * Term Methods
235
+ *
236
+ ****************************************************************************/
237
+ static ID id_field;
238
+ static ID id_text;
239
+
240
+ VALUE frt_get_term(const char *field, const char *text)
241
+ {
242
+ return rb_struct_new(cTerm,
243
+ ID2SYM(rb_intern(field)),
244
+ rb_str_new2(text),
245
+ NULL);
246
+ }
247
+
248
+ static VALUE frt_term_to_s(VALUE self)
249
+ {
250
+ VALUE rstr;
251
+ VALUE rfield = rb_funcall(self, id_field, 0);
252
+ VALUE rtext = rb_funcall(self, id_text, 0);
253
+ char *field = StringValuePtr(rfield);
254
+ char *text = StringValuePtr(rtext);
255
+ char *term_str = ALLOC_N(char,
256
+ 5 + RSTRING(rfield)->len + RSTRING(rtext)->len);
257
+ sprintf(term_str, "%s:%s", field, text);
258
+ rstr = rb_str_new2(term_str);
259
+ free(term_str);
260
+ return rstr;
261
+ }
262
+ /*
263
+ * Document-class: Ferret::Term
264
+ *
265
+ * == Summary
266
+ *
267
+ * A Term holds a term from a document and its field name (as a Symbol).
268
+ */
269
+ void Init_Term(void)
270
+ {
271
+ const char *term_class = "Term";
272
+ cTerm = rb_struct_define(term_class, "field", "text", NULL);
273
+ rb_set_class_path(cTerm, mFerret, term_class);
274
+ rb_const_set(mFerret, rb_intern(term_class), cTerm);
275
+ rb_define_method(cTerm, "to_s", frt_term_to_s, 0);
276
+ id_field = rb_intern("field");
277
+ id_text = rb_intern("text");
278
+ }
279
+
236
280
  /*
237
281
  * Document-module: Ferret
238
282
  *
@@ -241,6 +285,7 @@ void FRT_EXIT(const char *err_type, const char *fmt, ...)
241
285
  void Init_Ferret(void)
242
286
  {
243
287
  mFerret = rb_define_module("Ferret");
288
+ Init_Term();
244
289
  }
245
290
 
246
291
  void Init_ferret_ext(void)
@@ -254,6 +299,8 @@ void Init_ferret_ext(void)
254
299
  /* IDs */
255
300
  id_new = rb_intern("new");
256
301
  id_call = rb_intern("call");
302
+ id_eql = rb_intern("eql?");
303
+ id_hash = rb_intern("hash");
257
304
 
258
305
  id_capacity = rb_intern("capacity");
259
306
  id_less_than = rb_intern("less_than");
@@ -7,10 +7,12 @@
7
7
 
8
8
  /* IDs */
9
9
  extern ID id_new;
10
+ extern ID id_call;
11
+ extern ID id_hash;
12
+ extern ID id_eql;
10
13
  extern ID id_capacity;
11
14
  extern ID id_less_than;
12
15
  extern ID id_lt;
13
- extern ID id_call;
14
16
  extern ID id_is_directory;
15
17
  extern ID id_close;
16
18
  extern ID id_cclass;
@@ -35,6 +37,7 @@ extern VALUE mSpans;
35
37
  /* Classes */
36
38
  extern VALUE cDirectory;
37
39
  extern VALUE cLockError;
40
+ extern VALUE cTerm;
38
41
 
39
42
  /* Ferret Inits */
40
43
  extern void Init_Utils();
@@ -61,7 +64,7 @@ extern void frt_create_dir(VALUE rpath);
61
64
  extern VALUE frt_hs_to_rb_ary(HashSet *hs);
62
65
  extern void *frt_rb_data_ptr(VALUE val);
63
66
  extern char * frt_field(VALUE rfield);
64
- extern VALUE frt_define_class_under(VALUE module, char *name, VALUE super);
67
+ extern VALUE frt_get_term(const char *field, const char *term);
65
68
 
66
69
  #define Frt_Make_Struct(klass)\
67
70
  rb_data_object_alloc(klass,NULL,(RUBY_DATA_FUNC)NULL,(RUBY_DATA_FUNC)NULL)
@@ -81,3 +84,6 @@ extern VALUE frt_define_class_under(VALUE module, char *name, VALUE super);
81
84
  } while (0)
82
85
 
83
86
  #endif
87
+
88
+ #define frt_mark_cclass(klass) rb_ivar_set(klass, id_cclass, Qtrue)
89
+ #define frt_is_cclass(obj) (rb_ivar_get(CLASS_OF(obj), id_cclass) == Qtrue)
@@ -2899,10 +2899,9 @@ void ir_set_norm(IndexReader *ir, int doc_num, const char *field, uchar val)
2899
2899
  }
2900
2900
  }
2901
2901
 
2902
- uchar *ir_get_norms(IndexReader *ir, const char *field)
2902
+ uchar *ir_get_norms_i(IndexReader *ir, int field_num)
2903
2903
  {
2904
2904
  uchar *norms = NULL;
2905
- int field_num = fis_get_field_num(ir->fis, field);
2906
2905
  if (field_num >= 0) {
2907
2906
  norms = ir->get_norms(ir, field_num);
2908
2907
  }
@@ -2915,6 +2914,12 @@ uchar *ir_get_norms(IndexReader *ir, const char *field)
2915
2914
  return norms;
2916
2915
  }
2917
2916
 
2917
+ uchar *ir_get_norms(IndexReader *ir, const char *field)
2918
+ {
2919
+ int field_num = fis_get_field_num(ir->fis, field);
2920
+ return ir_get_norms_i(ir, field_num);
2921
+ }
2922
+
2918
2923
  uchar *ir_get_norms_into(IndexReader *ir, const char *field, uchar *buf)
2919
2924
  {
2920
2925
  int field_num = fis_get_field_num(ir->fis, field);
@@ -3286,6 +3291,7 @@ static BitVector *bv_read(Store *store, char *name)
3286
3291
  bv->size = (int)is_read_vint(is);
3287
3292
  bv->capa = (bv->size >> 5) + 1;
3288
3293
  bv->bits = ALLOC_AND_ZERO_N(f_u32, bv->capa);
3294
+ bv->ref_cnt = 1;
3289
3295
  for (i = (bv->size >> 5); i >= 0; i--) {
3290
3296
  bv->bits[i] = is_read_u32(is);
3291
3297
  }
@@ -5022,17 +5028,6 @@ int iw_doc_count(IndexWriter *iw)
5022
5028
  return doc_cnt;
5023
5029
  }
5024
5030
 
5025
- void iw_delete_term(IndexWriter *iw, const char *field, const char *term)
5026
- {
5027
- int field_num = fis_get_field_num(iw->fis, field);
5028
- if (field_num >= 0) {
5029
- DelTerm *dt = ALLOC(DelTerm);
5030
- dt->field_num = field_num;
5031
- dt->term = estrdup(term);
5032
- ary_push(iw->del_terms, dt);
5033
- }
5034
- }
5035
-
5036
5031
  static void delete_files(char **file_names, Store *store)
5037
5032
  {
5038
5033
  int i;
@@ -5277,37 +5272,9 @@ void iw_add_doc(IndexWriter *iw, Document *doc)
5277
5272
 
5278
5273
  static void iw_commit_i(IndexWriter *iw)
5279
5274
  {
5280
- /* optimized term deletion method */
5281
- const int del_term_cnt = ary_size(iw->del_terms);
5282
5275
  if (iw->dw && iw->dw->doc_num > 0) {
5283
5276
  iw_flush_ram_segment(iw);
5284
5277
  }
5285
- if (del_term_cnt) {
5286
- DelTerm **del_terms = iw->del_terms;
5287
- int i;
5288
- SegmentInfos *sis = iw->sis;
5289
- const int seg_cnt = sis->size;
5290
- for (i = 0; i < seg_cnt; i++) {
5291
- int j;
5292
- IndexReader *ir = sr_open(sis, iw->fis, i, false);
5293
- TermDocEnum *tde = ir->term_docs(ir);
5294
- for (j = 0; j < del_term_cnt; j++) {
5295
- DelTerm *del_term = del_terms[j];
5296
- stde_seek(tde, del_term->field_num, del_term->term);
5297
- while (tde->next(tde)) {
5298
- sr_delete_doc_i(ir, STDE(tde)->doc_num);
5299
- }
5300
- }
5301
- tde_destroy(tde);
5302
- sr_commit_i(ir);
5303
- ir_close(ir);
5304
- }
5305
- ary_each_rev(del_terms, i) {
5306
- free(del_terms[i]->term);
5307
- free(del_terms[i]);
5308
- }
5309
- ary_size(del_terms) = 0;
5310
- }
5311
5278
  }
5312
5279
 
5313
5280
  void iw_commit(IndexWriter *iw)
@@ -5317,6 +5284,32 @@ void iw_commit(IndexWriter *iw)
5317
5284
  mutex_unlock(&iw->mutex);
5318
5285
  }
5319
5286
 
5287
+ void iw_delete_term(IndexWriter *iw, const char *field, const char *term)
5288
+ {
5289
+ int field_num = fis_get_field_num(iw->fis, field);
5290
+ if (field_num >= 0) {
5291
+ int i;
5292
+ mutex_lock(&iw->mutex);
5293
+ iw_commit_i(iw);
5294
+ do {
5295
+ SegmentInfos *sis = iw->sis;
5296
+ const int seg_cnt = sis->size;
5297
+ for (i = 0; i < seg_cnt; i++) {
5298
+ IndexReader *ir = sr_open(sis, iw->fis, i, false);
5299
+ TermDocEnum *tde = ir->term_docs(ir);
5300
+ stde_seek(tde, field_num, term);
5301
+ while (tde->next(tde)) {
5302
+ sr_delete_doc_i(ir, STDE(tde)->doc_num);
5303
+ }
5304
+ tde_destroy(tde);
5305
+ sr_commit_i(ir);
5306
+ ir_close(ir);
5307
+ }
5308
+ } while (0);
5309
+ mutex_unlock(&iw->mutex);
5310
+ }
5311
+ }
5312
+
5320
5313
  static void iw_optimize_i(IndexWriter *iw)
5321
5314
  {
5322
5315
  int min_segment;
@@ -5351,7 +5344,6 @@ void iw_close(IndexWriter *iw)
5351
5344
  sis_destroy(iw->sis);
5352
5345
  fis_deref(iw->fis);
5353
5346
  sim_destroy(iw->similarity);
5354
- ary_free(iw->del_terms);
5355
5347
 
5356
5348
  iw->write_lock->release(iw->write_lock);
5357
5349
  iw->store->close_lock(iw->write_lock);
@@ -5392,7 +5384,6 @@ IndexWriter *iw_open(Store *store, Analyzer *analyzer, const Config *config)
5392
5384
  XENDTRY
5393
5385
 
5394
5386
  iw->similarity = sim_create_default();
5395
- iw->del_terms = ary_new_type(DelTerm *);
5396
5387
  iw->analyzer = analyzer ? analyzer : mb_standard_analyzer_new(true);
5397
5388
 
5398
5389
  REF(store);
@@ -744,6 +744,7 @@ extern void ir_undelete_all(IndexReader *ir);
744
744
  extern int ir_doc_freq(IndexReader *ir, const char *field, const char *term);
745
745
  extern void ir_set_norm(IndexReader *ir, int doc_num, const char *field,
746
746
  uchar val);
747
+ extern uchar *ir_get_norms_i(IndexReader *ir, int field_num);
747
748
  extern uchar *ir_get_norms(IndexReader *ir, const char *field);
748
749
  extern uchar *ir_get_norms_into(IndexReader *ir, const char *field, uchar *buf);
749
750
  extern void ir_destroy(IndexReader *self);
@@ -868,7 +869,6 @@ struct IndexWriter
868
869
  FieldInfos *fis;
869
870
  DocWriter *dw;
870
871
  Similarity *similarity;
871
- DelTerm **del_terms;
872
872
  Lock *write_lock;
873
873
  };
874
874
 
@@ -388,7 +388,7 @@ static bool csc_skip_to(Scorer *self, int doc_num)
388
388
  csc_sort_scorers(csc);
389
389
  }
390
390
 
391
- more = csc->more;
391
+ csc->more = more;
392
392
  return csc_do_next(self);
393
393
  }
394
394
 
@@ -357,7 +357,7 @@ static Scorer *multi_tw_scorer(Weight *self, IndexReader *ir)
357
357
  te->close(te);
358
358
  if (tdew_cnt) {
359
359
  multi_tsc = multi_tsc_new(self, MTQ(self->query)->field, tdew_a,
360
- tdew_cnt, ir->get_norms(ir, field_num));
360
+ tdew_cnt, ir_get_norms_i(ir, field_num));
361
361
  }
362
362
  else {
363
363
  free(tdew_a);
@@ -559,6 +559,17 @@ static void multi_tq_destroy_i(Query *self)
559
559
  q_destroy_i(self);
560
560
  }
561
561
 
562
+ static void multi_tq_extract_terms(Query *self, HashSet *terms)
563
+ {
564
+ int i;
565
+ char *field = MTQ(self)->field;
566
+ PriorityQueue *boosted_terms = MTQ(self)->boosted_terms;
567
+ for (i = boosted_terms->size; i > 0; i--) {
568
+ BoostedTerm *bt = (BoostedTerm *)boosted_terms->heap[i];
569
+ hs_add(terms, term_new(field, bt->term));
570
+ }
571
+ }
572
+
562
573
  static ulong multi_tq_hash(Query *self)
563
574
  {
564
575
  int i;
@@ -631,6 +642,7 @@ Query *multi_tq_new_conf(const char *field, int max_terms, float min_boost)
631
642
 
632
643
  self->type = MULTI_TERM_QUERY;
633
644
  self->to_s = &multi_tq_to_s;
645
+ self->extract_terms = &multi_tq_extract_terms;
634
646
  self->hash = &multi_tq_hash;
635
647
  self->eq = &multi_tq_eq;
636
648
  self->destroy_i = &multi_tq_destroy_i;
@@ -170,8 +170,8 @@ static Phrase *ph_first_word(char *word);
170
170
  static Phrase *ph_add_word(Phrase *self, char *word);
171
171
  static Phrase *ph_add_multi_word(Phrase *self, char *word);
172
172
 
173
- static Query *get_range_q(const char *field, const char *from, const char *to,
174
- bool inc_lower, bool inc_upper);
173
+ static Query *get_r_q(QParser *qp, char *field, char *from, char *to,
174
+ bool inc_lower, bool inc_upper);
175
175
 
176
176
  #define FLDS(q, func) do {\
177
177
  char *field;\
@@ -1405,62 +1405,62 @@ yyreduce:
1405
1405
 
1406
1406
  case 39:
1407
1407
  #line 146 "src/q_parser.y"
1408
- { FLDS((yyval.query), get_range_q(field, (yyvsp[-2].str), (yyvsp[-1].str), true, true)); }
1408
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[-2].str), (yyvsp[-1].str), true, true)); }
1409
1409
  break;
1410
1410
 
1411
1411
  case 40:
1412
1412
  #line 147 "src/q_parser.y"
1413
- { FLDS((yyval.query), get_range_q(field, (yyvsp[-2].str), (yyvsp[-1].str), true, false)); }
1413
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[-2].str), (yyvsp[-1].str), true, false)); }
1414
1414
  break;
1415
1415
 
1416
1416
  case 41:
1417
1417
  #line 148 "src/q_parser.y"
1418
- { FLDS((yyval.query), get_range_q(field, (yyvsp[-2].str), (yyvsp[-1].str), false, true)); }
1418
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[-2].str), (yyvsp[-1].str), false, true)); }
1419
1419
  break;
1420
1420
 
1421
1421
  case 42:
1422
1422
  #line 149 "src/q_parser.y"
1423
- { FLDS((yyval.query), get_range_q(field, (yyvsp[-2].str), (yyvsp[-1].str), false, false)); }
1423
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[-2].str), (yyvsp[-1].str), false, false)); }
1424
1424
  break;
1425
1425
 
1426
1426
  case 43:
1427
1427
  #line 150 "src/q_parser.y"
1428
- { FLDS((yyval.query), get_range_q(field, NULL,(yyvsp[-1].str), false, false)); }
1428
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[-1].str), false, false)); }
1429
1429
  break;
1430
1430
 
1431
1431
  case 44:
1432
1432
  #line 151 "src/q_parser.y"
1433
- { FLDS((yyval.query), get_range_q(field, NULL,(yyvsp[-1].str), false, true)); }
1433
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[-1].str), false, true)); }
1434
1434
  break;
1435
1435
 
1436
1436
  case 45:
1437
1437
  #line 152 "src/q_parser.y"
1438
- { FLDS((yyval.query), get_range_q(field, (yyvsp[-1].str), NULL,true, false)); }
1438
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[-1].str), NULL,true, false)); }
1439
1439
  break;
1440
1440
 
1441
1441
  case 46:
1442
1442
  #line 153 "src/q_parser.y"
1443
- { FLDS((yyval.query), get_range_q(field, (yyvsp[-1].str), NULL,false, false)); }
1443
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[-1].str), NULL,false, false)); }
1444
1444
  break;
1445
1445
 
1446
1446
  case 47:
1447
1447
  #line 154 "src/q_parser.y"
1448
- { FLDS((yyval.query), get_range_q(field, NULL,(yyvsp[0].str), false, false)); }
1448
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[0].str), false, false)); }
1449
1449
  break;
1450
1450
 
1451
1451
  case 48:
1452
1452
  #line 155 "src/q_parser.y"
1453
- { FLDS((yyval.query), get_range_q(field, NULL,(yyvsp[0].str), false, true)); }
1453
+ { FLDS((yyval.query), get_r_q(qp, field, NULL,(yyvsp[0].str), false, true)); }
1454
1454
  break;
1455
1455
 
1456
1456
  case 49:
1457
1457
  #line 156 "src/q_parser.y"
1458
- { FLDS((yyval.query), get_range_q(field, (yyvsp[0].str), NULL,true, false)); }
1458
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[0].str), NULL,true, false)); }
1459
1459
  break;
1460
1460
 
1461
1461
  case 50:
1462
1462
  #line 157 "src/q_parser.y"
1463
- { FLDS((yyval.query), get_range_q(field, (yyvsp[0].str), NULL,false, false)); }
1463
+ { FLDS((yyval.query), get_r_q(qp, field, (yyvsp[0].str), NULL,false, false)); }
1464
1464
  break;
1465
1465
 
1466
1466
 
@@ -1756,7 +1756,7 @@ static int get_word(YYSTYPE *lvalp, QParser *qp)
1756
1756
  while (!strchr(not_word, (c=*qp->qstrp++))) {
1757
1757
  switch (c) {
1758
1758
  case '\\':
1759
- if ((c=*qp->qstrp) == ' ' && c != '\t' && c != '\0') {
1759
+ if ((c=*qp->qstrp) == '\0') {
1760
1760
  *bufp++ = '\\';
1761
1761
  }
1762
1762
  else {
@@ -2248,10 +2248,25 @@ static Query *get_phrase_q(QParser *qp, Phrase *phrase, char *slop_str)
2248
2248
  return q;
2249
2249
  }
2250
2250
 
2251
- static Query *get_range_q(const char *field, const char *from, const char *to,
2252
- bool inc_lower, bool inc_upper)
2251
+ static Query *get_r_q(QParser *qp, char *field, char *from, char *to,
2252
+ bool inc_lower, bool inc_upper)
2253
2253
  {
2254
- return rq_new(field, from, to, inc_lower, inc_upper);
2254
+ Query *rq;
2255
+ if (from) {
2256
+ TokenStream *stream = get_cached_ts(qp, field, from);
2257
+ Token *token = ts_next(stream);
2258
+ from = token ? estrdup(token->text) : NULL;
2259
+ }
2260
+ if (to) {
2261
+ TokenStream *stream = get_cached_ts(qp, field, to);
2262
+ Token *token = ts_next(stream);
2263
+ to = token ? estrdup(token->text) : NULL;
2264
+ }
2265
+
2266
+ rq = rq_new(field, from, to, inc_lower, inc_upper);
2267
+ if (from) free(from);
2268
+ if (to) free(to);
2269
+ return rq;
2255
2270
  }
2256
2271
 
2257
2272
  void qp_destroy(QParser *self)