The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
19822 hornik 1
/*
2
 
3
Copyright (C) Jarkko Hietaniemi, 1998,1999,2000,2001. All Rights Reserved.
4
 
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of either:
7
 
8
a) the GNU Library General Public License as published by the Free
9
   Software Foundation; either version 2, or (at your option) any
10
   later version, or
11
 
12
b) the "Artistic License" which comes with Perl source code.
13
 
14
Other free software licensing schemes are negotiable.
15
 
16
Furthermore:
17
 
18
(1) This software is provided as-is, without warranties or
19
    obligations of any kind.
20
 
21
(2) You shall include this copyright notice intact in all copies
22
    and derived materials.
23
 
24
*/
25
 
26
/*
27
 
20000 hornik 28
  $Id: apse.c,v 1.2 2002/06/08 10:20:32 hornik Exp $
19822 hornik 29
 
30
*/
31
 
32
#include "apse.h"
33
 
34
#include <stdio.h>
35
#include <string.h>
36
#include <stdlib.h>
37
#include <ctype.h>
38
 
39
#define APSE_BITS_IN_BITVEC	(8*sizeof(apse_vec_t))
40
 
41
#define APSE_CHAR_MAX		256
42
 
43
#ifdef APSE_DEBUGGING
44
#define APSE_DEBUG(x) x
45
#else
46
#define APSE_DEBUG(x)
47
#endif
48
 
49
#define APSE_BIT(i)		((apse_vec_t)1 << ((i)%APSE_BITS_IN_BITVEC))
50
#define APSE_IDX(p, q, i)	((p)*(q)+(i)/APSE_BITS_IN_BITVEC)
51
#define APSE_BIT_SET(bv, p, q, i) (bv[APSE_IDX(p, q, i)] |=  APSE_BIT(i))
52
#define APSE_BIT_CLR(bv, p, q, i) (bv[APSE_IDX(p, q, i)] &= ~APSE_BIT(i))
53
#define APSE_BIT_TST(bv, p, q, i) (bv[APSE_IDX(p, q, i)] &   APSE_BIT(i))
54
 
55
#define APSE_MATCH_STATE_BOT		0
56
#define APSE_MATCH_STATE_SEARCH		1
57
#define APSE_MATCH_STATE_BEGIN		2
58
#define APSE_MATCH_STATE_FAIL		3
59
#define APSE_MATCH_STATE_GREEDY		4
60
#define APSE_MATCH_STATE_END		5
61
#define APSE_MATCH_STATE_EOT		6
62
 
63
#define APSE_TEST_HIGH_BIT(i)	\
64
	(((i) & ((apse_vec_t)1 << (APSE_BITS_IN_BITVEC - 1))) ? 1 : 0)
65
 
66
/* In case you are reading the TR 91-11 of University of Arizona, page 6:
67
 * j+1	state
68
 * j	prev_state
69
 * d	i
70
 * d-1	prev_i
71
 */
72
 
73
#define APSE_NEXT_EXACT(state, prev_state, text, i, carry)		\
74
	(state[i] = ((prev_state[i] << 1 | carry) & text))
75
 
76
#define APSE_NEXT_APPROX(state, prev_state, text, i, prev_i, carry)	\
77
	(state[i]  = (((prev_state[i] << 1) & text)		  |	\
78
			prev_state[prev_i] 			  |	\
79
		      ((state[prev_i] | prev_state[prev_i]) << 1) |	\
80
			carry))
81
 
82
#define APSE_NEXT_COMMON(state, prev_state, text, i)			\
83
	(state[i]  = (prev_state[i] << 1) & text)
84
 
85
#define APSE_NEXT_INSERT(state, prev_state, i, prev_i)			\
86
	(state[i] |= prev_state[prev_i])
87
 
88
#define APSE_NEXT_DELETE(state, i, prev_i)				\
89
	(state[i] |= (state[prev_i] << 1))
90
 
91
#define APSE_NEXT_SUBSTI(state, prev_state, i, prev_i)			\
92
	(state[i] |= (prev_state[prev_i] << 1))
93
 
94
#define APSE_NEXT_CARRY(state, i, carry)				\
95
	(state[i] |= carry)
96
 
97
#define APSE_EXACT_MATCH_BEGIN(ap)	(ap->state[0] & 1)
98
 
99
#define APSE_APPROX_MATCH_BEGIN(ap)	\
100
	(ap->state[ap->largest_distance + ap->match_begin_bitvector] > \
101
	 ap->match_begin_prefix && \
102
	 ap->state[ap->largest_distance + ap->match_begin_bitvector] & \
103
	 ap->match_begin_prefix)
104
 
105
#define APSE_PREFIX_DELETE_MASK(ap)	\
106
	    do { if (ap->edit_deletions < ap->edit_distance &&	\
107
		     ap->text_position  < ap->edit_distance)	\
108
 	             ap->state[h] &= ap->match_begin_bitmask; } while (0)
109
 
110
#define APSE_DEBUG_SINGLE(ap, i)		\
111
	APSE_DEBUG(printf("%c %2ld %2ld %s\n",				\
112
			  isprint(ap->text[ap->text_position])?	\
113
			  ap->text[ap->text_position]:'.',		\
114
			  ap->text_position, i, 			\
115
			  _apse_fbin(ap->state[i],			\
116
				     ap->pattern_size, 1)))
117
 
118
 
119
#define APSE_DEBUG_MULTIPLE_FIRST(ap, i)	\
120
	APSE_DEBUG(printf("%c %2ld %2ld",				\
121
			  isprint(ap->text[ap->text_position])?	\
122
			  ap->text[ap->text_position]:'.',		\
123
			  ap->text_position, i))
124
 
125
#define APSE_DEBUG_MULTIPLE_REST(ap, i, j)	\
126
	APSE_DEBUG(printf(" %s",					\
127
			  _apse_fbin(ap->state[j],			\
128
				     ap->pattern_size, 			\
129
				     i == ap->bitvectors_in_state-1)))
130
 
131
 
132
#ifdef APSE_DEBUGGING
133
static char *_apse_fbin(apse_vec_t v, apse_size_t n, apse_bool_t last);
134
 
135
static char *_apse_fbin(apse_vec_t v, apse_size_t n, apse_bool_t last) {
136
    static char s[APSE_BITS_IN_BITVEC + 1] = { 0 }; /* non-reentrant */
137
 
138
    if (v) {
139
	static const char *b =
140
	    "0000100001001100001010100110111000011001010111010011101101111111";
141
	apse_size_t i;
142
 
143
	for (i = 0; i < APSE_BITS_IN_BITVEC && i < n && v; i += 4) {
144
	    (void)memcpy(s + i, b + ((v & 0x0f) << 2), (size_t)4);
145
	    v >>= 4;
146
	}
147
 
148
	if (i < APSE_BITS_IN_BITVEC)
149
	    memset(s + i, '0', APSE_BITS_IN_BITVEC - i);
150
    } else
151
	memset(s, '0', APSE_BITS_IN_BITVEC);
152
 
153
    if (last)
154
	s[n % APSE_BITS_IN_BITVEC] = 0;
155
 
156
    return s;
157
}
158
#endif
159
 
160
/* The code begins. */
161
 
162
apse_bool_t apse_set_pattern(apse_t*		ap,
163
			     unsigned char*	pattern,
164
			     apse_size_t	pattern_size) {
165
    apse_size_t	i;
166
 
167
    if (ap->case_mask)
168
	free(ap->case_mask);
169
    if (ap->fold_mask)
170
	free(ap->fold_mask);
171
 
172
    ap->pattern_mask = 0;
173
    ap->fold_mask    = 0;
174
    ap->case_mask    = 0;
175
 
176
    ap->is_greedy    = 0;
177
 
178
    ap->prev_equal   = 0;
179
    ap->prev_active  = 0;
180
 
181
    ap->pattern_size = pattern_size;
182
    ap->bitvectors_in_state = (pattern_size - 1)/APSE_BITS_IN_BITVEC + 1;
183
 
184
    if (ap->edit_distance)
185
	ap->largest_distance = ap->edit_distance * ap->bitvectors_in_state;
186
 
187
    ap->bytes_in_state = ap->bitvectors_in_state * sizeof(apse_vec_t);
188
 
189
    ap->case_mask = calloc((apse_size_t)APSE_CHAR_MAX, ap->bytes_in_state);
190
    if (!ap->case_mask)
191
	goto out;
192
 
193
    for (i = 0; i < pattern_size; i++)
194
	APSE_BIT_SET(ap->case_mask,
195
		     (unsigned)pattern[i],
196
		     ap->bitvectors_in_state, i);
197
 
198
    ap->pattern_mask = ap->case_mask;
199
 
200
    ap->match_end_bitmask =
201
	(apse_vec_t)1 << ((pattern_size - 1) % APSE_BITS_IN_BITVEC);
202
 
203
out:
204
    if (ap && ap->case_mask)
205
	return 1;
206
    else {
207
	if (ap->case_mask)
208
	    free(ap->case_mask);
209
	if (ap)
210
	    free(ap);
211
	return 0;
212
    }
213
}
214
 
215
void apse_set_greedy(apse_t *ap, apse_bool_t greedy) {
216
    ap->is_greedy = greedy;
217
}
218
 
219
apse_bool_t apse_get_greedy(apse_t *ap) {
220
    return ap->is_greedy;
221
}
222
 
223
void apse_set_match_bot_callback(apse_t *ap,
224
				 void* (*match_bot_callback)(apse_t* ap)) {
225
    ap->match_bot_callback = match_bot_callback;
226
}
227
 
228
void apse_set_match_begin_callback(apse_t *ap,
229
				   void* (*match_begin_callback)(apse_t* ap)) {
230
    ap->match_begin_callback = match_begin_callback;
231
}
232
 
233
void apse_set_match_fail_callback(apse_t *ap,
234
				  void* (*match_fail_callback)(apse_t* ap)) {
235
    ap->match_fail_callback = match_fail_callback;
236
}
237
 
238
void apse_set_match_end_callback(apse_t *ap,
239
				 void* (*match_end_callback)(apse_t* ap)) {
240
    ap->match_end_callback = match_end_callback;
241
}
242
 
243
void apse_set_match_eot_callback(apse_t *ap,
244
				 void* (*match_eot_callback)(apse_t* ap)) {
245
    ap->match_eot_callback = match_eot_callback;
246
}
247
 
248
void* (*apse_get_match_bot_callback(apse_t * ap))(apse_t *ap) {
249
    return ap->match_bot_callback;
250
}
251
 
252
void* (*apse_get_match_begin_callback(apse_t * ap))(apse_t *ap) {
253
    return ap->match_begin_callback;
254
}
255
 
256
void* (*apse_get_match_fail_callback(apse_t * ap))(apse_t *ap) {
257
    return ap->match_fail_callback;
258
}
259
 
260
void* (*apse_get_match_end_callback(apse_t * ap))(apse_t *ap) {
261
    return ap->match_end_callback;
262
}
263
 
264
void* (*apse_get_match_eot_callback(apse_t * ap))(apse_t *ap) {
265
    return ap->match_eot_callback;
266
}
267
 
268
static int _apse_wrap_slice(apse_t*		ap,
269
			    apse_ssize_t	begin_in,
270
			    apse_ssize_t	size_in,
271
			    apse_ssize_t*	begin_out,
272
			    apse_ssize_t*	size_out) {
273
    if (begin_in < 0) {
274
	if (-begin_in > ap->pattern_size)
275
	    return 0;
276
	begin_in = ap->pattern_size + begin_in;
277
    }
278
 
279
    if (size_in < 0) {
280
	if (-size_in > begin_in)
281
	    return 0;
282
	size_in   = -size_in;
283
	begin_in -=  size_in;
284
    }
285
 
286
    if (begin_in >= ap->pattern_size)
287
	return 0;
288
 
289
    if (begin_in + size_in > ap->pattern_size)
290
	size_in = ap->pattern_size - begin_in;
291
 
292
    if (begin_out)
293
	*begin_out = begin_in;
294
 
295
    if (size_out)
296
	*size_out = size_in;
297
 
298
    return 1;
299
}
300
 
301
apse_bool_t apse_set_anychar(apse_t *ap, apse_ssize_t pattern_index) {
302
    apse_size_t	bitvectors_in_state = ap->bitvectors_in_state;
303
    apse_ssize_t	true_index, i;
304
    apse_bool_t	okay = 0;
305
 
306
    if (!_apse_wrap_slice(ap, pattern_index, (apse_ssize_t)1,
307
			      &true_index, 0))
308
	goto out;
309
 
310
    for (i = 0; i < APSE_CHAR_MAX; i++)
311
	APSE_BIT_SET(ap->case_mask,
312
		      i, bitvectors_in_state, pattern_index);
313
    if (ap->fold_mask)
314
	for (i = 0; i < APSE_CHAR_MAX; i++)
315
	    APSE_BIT_SET(ap->fold_mask,
316
			  i, bitvectors_in_state, pattern_index);
317
 
318
    okay = 1;
319
 
320
  out:
321
 
322
    return okay;
323
}
324
 
325
apse_bool_t apse_set_charset(apse_t*		ap,
326
			     apse_ssize_t	pattern_index,
327
			     unsigned char*	set,
328
			     apse_size_t	set_size,
329
			     apse_bool_t	complement) {
330
    apse_size_t	bitvectors_in_state = ap->bitvectors_in_state;
331
    apse_ssize_t	true_index, i;
332
    apse_bool_t	okay = 0;
333
 
334
    if (!_apse_wrap_slice(ap, pattern_index, (apse_ssize_t)1,
335
			      &true_index, 0))
336
	goto out;
337
 
338
    if (complement) {
339
	for (i = 0; i < set_size; i++)
340
	    APSE_BIT_CLR(ap->case_mask,
341
			  (unsigned)set[i],
342
			  bitvectors_in_state, true_index);
343
    } else {
344
	for (i = 0; i < set_size; i++)
345
	    APSE_BIT_SET(ap->case_mask,
346
			  (unsigned)set[i],
347
			  bitvectors_in_state, true_index);
348
    }
349
    if (ap->fold_mask)
350
	apse_set_caseignore_slice(ap, pattern_index,
351
				   (apse_ssize_t)1, (apse_bool_t)1);
352
 
353
    okay = 1;
354
 
355
 out:
356
 
357
    return okay;
358
}
359
 
360
static void _apse_reset_state(apse_t* ap) {
361
    apse_size_t	i, j;
362
 
363
    (void)memset(ap->state,      0, ap->bytes_in_all_states);
364
    (void)memset(ap->prev_state, 0, ap->bytes_in_all_states);
365
 
366
    ap->prev_equal  = 0;
367
    ap->prev_active = 0;
368
 
369
    for (i = 1; i <= ap->edit_distance; i++) {
370
	for (j = 0; j < i; j++)
371
	    APSE_BIT_SET(ap->prev_state, i, ap->bitvectors_in_state, j);
372
    }
373
}
374
 
375
apse_bool_t apse_set_text_position(apse_t *ap,
376
					 apse_size_t text_position) {
377
    ap->text_position = text_position;
378
 
379
    return 1;
380
}
381
 
382
apse_size_t apse_get_text_position(apse_t *ap) {
383
    return ap->text_position;
384
}
385
 
386
apse_bool_t apse_set_text_initial_position(apse_t *ap,
387
					   apse_size_t text_initial_position) {
388
    ap->text_initial_position = text_initial_position;
389
 
390
    return 1;
391
}
392
 
393
apse_size_t apse_get_text_initial_position(apse_t *ap) {
394
    return ap->text_initial_position;
395
}
396
 
397
apse_bool_t apse_set_text_final_position(apse_t *ap,
398
					 apse_size_t text_final_position) {
399
    ap->text_final_position = text_final_position;
400
 
401
    return 1;
402
}
403
 
404
apse_size_t apse_get_text_final_position(apse_t *ap) {
405
    return ap->text_final_position;
406
}
407
 
408
apse_bool_t apse_set_text_position_range(apse_t *ap,
409
					 apse_size_t text_position_range) {
410
    ap->text_position_range = text_position_range;
411
 
412
    return 1;
413
}
414
 
415
apse_size_t apse_get_text_position_range(apse_t *ap) {
416
    return ap->text_position_range;
417
}
418
 
419
void apse_reset(apse_t *ap) {
420
    _apse_reset_state(ap);
421
 
422
    ap->text_position = ap->text_initial_position;
423
    ap->text_position_range = APSE_MATCH_BAD;
424
 
425
    ap->match_state = APSE_MATCH_STATE_BOT;
426
    ap->match_begin = APSE_MATCH_BAD;
427
    ap->match_end   = APSE_MATCH_BAD;
428
}
429
 
430
apse_bool_t apse_set_edit_distance(apse_t *ap, apse_size_t edit_distance) {
431
    /* TODO: waste not--reuse if possible */
432
 
433
    if (ap->state)
434
	free(ap->state);
435
    if (ap->prev_state)
436
	free(ap->prev_state);
437
 
438
    ap->edit_distance = edit_distance;
439
 
440
    ap->bytes_in_all_states = (edit_distance + 1) * ap->bytes_in_state;
441
 
442
    ap->state = ap->prev_state = 0;
443
 
444
    ap->state = calloc(edit_distance + 1, ap->bytes_in_state);
445
    if (!ap->state)
446
	goto out;
447
 
448
    ap->prev_state = calloc(edit_distance + 1, ap->bytes_in_state);
449
    if (!ap->prev_state)
450
	goto out;
451
 
452
    apse_reset(ap);
453
 
454
    if (!ap->has_different_distances) {
455
	ap->edit_insertions		= edit_distance;
456
	ap->edit_deletions		= edit_distance;
457
	ap->edit_substitutions		= edit_distance;
458
    }
459
 
460
    if (ap->edit_distance && ap->bitvectors_in_state)
461
	ap->largest_distance = ap->edit_distance * ap->bitvectors_in_state;
462
 
463
    ap->match_begin_bitvector	=
464
	(edit_distance + 1) / APSE_BITS_IN_BITVEC;
465
    ap->match_begin_prefix = ((apse_vec_t)1 << edit_distance) - 1;
466
    ap->match_begin_bitmask	=
467
	((apse_vec_t)1 << edit_distance) - 1;
468
 
469
    ap->match_end_bitvector =
470
	(ap->pattern_size - 1) / APSE_BITS_IN_BITVEC;
471
 
472
#ifdef APSE_DEBUGGING
473
    if (ap->has_different_distances) {
474
	printf("(edit distances: ");
475
	printf("insertions = %ld, deletions = %ld, substitutions = %ld)\n",
476
	       ap->edit_insertions,
477
	       ap->edit_deletions,
478
	       ap->edit_substitutions);
479
    } else
480
	printf("(edit_distance = %ld)\n", ap->edit_distance);
481
#endif
482
 
483
out:
484
    return ap->state && ap->prev_state;
485
}
486
 
487
apse_size_t apse_get_edit_distance(apse_t *ap) {
488
    return ap->edit_distance;
489
}
490
 
491
apse_bool_t apse_set_minimal_distance(apse_t* ap, apse_bool_t minimal) {
492
    ap->use_minimal_distance = minimal;
493
    return 1;
494
}
495
 
496
apse_bool_t apse_get_minimal_distance(apse_t *ap) {
497
    return ap->use_minimal_distance;
498
}
499
 
500
apse_bool_t apse_set_exact_slice(apse_t*	ap,
501
				 apse_ssize_t	exact_begin,
502
				 apse_ssize_t	exact_size,
503
				 apse_bool_t	exact) {
504
    apse_ssize_t	i, j, true_begin, true_size;
505
    apse_bool_t	okay = 0;
506
 
507
    if (!ap->exact_mask) {
508
 
509
	ap->exact_mask = calloc((size_t)1, ap->bytes_in_state);
510
	if (!ap->exact_mask)
511
	    goto out;
512
 
513
	ap->exact_positions = 0;
514
    }
515
 
516
    if (!_apse_wrap_slice(ap, exact_begin, exact_size,
517
			      &true_begin, &true_size))
518
	goto out;
519
 
520
    if (exact) {
521
	for (i = true_begin, j = true_begin +  true_size;
522
	     i < j && i < ap->pattern_size; i++) {
523
	    if (!APSE_BIT_TST(ap->exact_mask, 0, 0, i))
524
		ap->exact_positions++;
525
	    APSE_BIT_SET(ap->exact_mask, 0, 0, i);
526
	}
527
    } else {
528
	for (i = true_begin, j = true_begin +  true_size;
529
	     i < j && i < ap->pattern_size; i++) {
530
	    if (APSE_BIT_TST(ap->exact_mask, 0, 0, i))
531
		ap->exact_positions--;
532
	    APSE_BIT_CLR(ap->exact_mask, 0, 0, i);
533
	}
534
    }
535
 
536
    okay = 1;
537
 
538
out:
539
    return okay;
540
}
541
 
542
apse_bool_t apse_set_caseignore_slice(apse_t*		ap,
543
				      apse_ssize_t	caseignore_begin,
544
				      apse_ssize_t	caseignore_size,
545
				      apse_bool_t	caseignore) {
546
    apse_size_t		i, j;
547
    int			k;
548
    apse_ssize_t	true_begin, true_size;
549
    apse_bool_t		okay = 0;
550
 
551
    if (!ap->fold_mask) {
552
 
553
	ap->fold_mask = calloc((apse_size_t)APSE_CHAR_MAX,
554
			       ap->bytes_in_state);
555
	if (!ap->fold_mask)
556
	    goto out;
557
 
558
	memcpy(ap->fold_mask,
559
	       ap->case_mask,
560
	       APSE_CHAR_MAX * ap->bytes_in_state);
561
 
562
	ap->pattern_mask = ap->fold_mask;
563
    }
564
 
565
    if (!_apse_wrap_slice(ap, caseignore_begin, caseignore_size,
566
			      &true_begin, &true_size))
567
	goto out;
568
 
569
    if (caseignore) {
570
	for (i = true_begin, j = true_begin +  true_size;
571
	     i < j && i < ap->pattern_size; i++) {
572
	    for (k = 0; k < APSE_CHAR_MAX; k++) {
573
		if (APSE_BIT_TST(ap->case_mask,
574
				 k, ap->bitvectors_in_state, i)) {
575
		    if (isupper(k))
576
			APSE_BIT_SET(ap->fold_mask,
577
				     tolower(k),
578
				     ap->bitvectors_in_state, i);
579
		    else if (islower(k))
580
			APSE_BIT_SET(ap->fold_mask,
581
				     toupper(k),
582
				     ap->bitvectors_in_state, i);
583
		}
584
	    }
585
	}
586
    } else {
587
	for (i = true_begin, j = true_begin +  true_size;
588
	     i < j && i < ap->pattern_size; i++) {
589
	    for (k = 0; k < APSE_CHAR_MAX; k++) {
590
		if (APSE_BIT_TST(ap->case_mask,
591
				 k, ap->bitvectors_in_state, i)) {
592
		    if (isupper(k))
593
			APSE_BIT_CLR(ap->fold_mask,
594
				     tolower(k),
595
				     ap->bitvectors_in_state, i);
596
		    else
597
			if (islower(k))
598
			    APSE_BIT_CLR(ap->fold_mask,
599
					 toupper(k),
600
					 ap->bitvectors_in_state, i);
601
		}
602
	    }
603
	}
604
    }
605
 
606
    okay = 1;
607
 
608
out:
609
    return okay;
610
}
611
 
612
void apse_destroy(apse_t *ap) {
613
    if (ap->case_mask)		free(ap->case_mask);
614
    if (ap->fold_mask)		free(ap->fold_mask);
615
    if (ap->state)		free(ap->state);
616
    if (ap->prev_state)		free(ap->prev_state);
617
    if (ap->exact_mask)	 	free(ap->exact_mask);
618
    free(ap);
619
}
620
 
621
apse_t *apse_create(unsigned char*	pattern,
622
		    apse_size_t		pattern_size,
623
		    apse_size_t		edit_distance) {
624
    apse_t		*ap;
625
    apse_bool_t	okay = 0;
626
 
627
    APSE_DEBUG(printf("(apse version %u.%u)\n",
628
		      APSE_MAJOR_VERSION, APSE_MINOR_VERSION));
629
 
630
    APSE_DEBUG(
631
	printf("(pattern = \"%s\", pattern_size = %ld)\n",
632
	       pattern, pattern_size));
633
 
634
    ap = calloc((size_t)1, sizeof(*ap));
635
    if (!ap)
636
	return 0;
637
 
638
    ap->pattern_size		= 0;
639
    ap->pattern_mask		= 0;
640
 
641
    ap->edit_distance		= 0;
642
    ap->has_different_distances = 0;
643
    ap->edit_insertions		= 0;
644
    ap->edit_deletions		= 0;
645
    ap->edit_substitutions	= 0;
646
    ap->use_minimal_distance	= 0;
647
 
648
    ap->bitvectors_in_state	= 0;
649
    ap->bytes_in_state		= 0;
650
    ap->bytes_in_all_states	= 0;
651
    ap->largest_distance	= 0;
652
 
653
    ap->text			= 0;
654
    ap->text_size		= 0;
655
    ap->text_position		= 0;
656
    ap->text_initial_position	= 0;
657
    ap->text_final_position	= APSE_MATCH_BAD;
658
    ap->text_position_range	= APSE_MATCH_BAD;
659
 
660
    ap->state			= 0;
661
    ap->prev_state		= 0;
662
    ap->match_begin_bitmask	= 0;
663
    ap->match_begin_prefix	= 0;
664
    ap->match_end_bitvector	= 0;
665
    ap->match_end_bitmask	= 0;
666
    ap->match_state		= APSE_MATCH_STATE_BOT;
667
    ap->match_begin		= APSE_MATCH_BAD;
668
    ap->match_end		= APSE_MATCH_BAD;
669
 
670
    ap->match_bot_callback	= 0;
671
    ap->match_begin_callback	= 0;
672
    ap->match_fail_callback	= 0;
673
    ap->match_end_callback	= 0;
674
    ap->match_eot_callback	= 0;
675
 
676
    ap->exact_positions		= 0;
677
    ap->exact_mask		= 0;
678
 
679
    ap->is_greedy		= 0;
680
 
681
    ap->custom_data		= 0;
682
    ap->custom_data_size	= 0;
683
 
684
    if (!apse_set_pattern(ap, (unsigned char *)pattern, pattern_size))
685
	goto out;
686
 
687
    if (!apse_set_edit_distance(ap, edit_distance))
688
	goto out;
689
 
690
    ap->edit_insertions = ap->edit_deletions =
691
	ap->edit_substitutions = ap->edit_distance;
692
 
693
    ap->largest_distance = edit_distance * ap->bitvectors_in_state;
694
 
695
#ifdef APSE_DEBUGGING
696
    printf("(size of bitvector = %ld, bitvectors_in_state = %ld)\n",
697
	   (long)sizeof(apse_vec_t), ap->bitvectors_in_state);
698
    printf("(bytes_in_state = %ld, states = %ld, bytes_in_all_states = %ld)\n",
699
	   ap->bytes_in_state, ap->edit_distance + 1, ap->bytes_in_all_states);
700
    printf("(match_begin_bitvector = %ld, match_begin_bitmask = %s)\n",
701
	   ap->match_begin_bitvector,
702
	   _apse_fbin(ap->match_begin_bitmask, ap->pattern_size, 1));
703
    printf("(match_end_bitvector = %ld, match_end_bitmask = %s)\n",
704
	   ap->match_end_bitvector,
705
	   _apse_fbin(ap->match_end_bitmask, ap->pattern_size, 1));
706
    printf("(largest_distance = %ld, match_begin_prefix = %s)\n",
707
	   ap->largest_distance,
708
	   _apse_fbin(ap->match_begin_prefix, ap->pattern_size, 1));
709
    if (ap->bitvectors_in_state == 1)
710
	printf("(single bitvector");
711
    else
712
	printf("(multiple bitvectors");
713
    printf(")\n");
714
#endif
715
    okay = 1;
716
 
717
 out:
718
    if (!okay) {
719
	apse_destroy(ap);
720
	ap = 0;
721
    }
722
 
723
    return ap;
724
}
725
 
726
apse_bool_t apse_set_insertions(apse_t *ap, apse_size_t insertions) {
727
    apse_bool_t	okay = 0;
728
 
729
    if (insertions > ap->edit_distance)
730
	insertions = ap->edit_distance;
731
    ap->edit_insertions = insertions;
732
    ap->has_different_distances = 1;
733
 
734
    APSE_DEBUG((printf("(edit distances: insertions = %ld, deletions = %ld, substitutions = %ld)\n",
735
		       ap->edit_insertions,
736
		       ap->edit_deletions,
737
		       ap->edit_substitutions)));
738
 
739
    okay = 1;
740
 
741
    return okay;
742
}
743
 
744
apse_size_t apse_get_insertions(apse_t *ap) {
745
    if (ap->has_different_distances)
746
	return ap->edit_insertions;
747
    else
748
	return ap->edit_distance;
749
}
750
 
751
apse_bool_t apse_set_deletions(apse_t *ap, apse_size_t deletions) {
752
    apse_bool_t	okay = 0;
753
 
754
    if (deletions > ap->edit_distance)
755
	deletions = ap->edit_distance;
756
    ap->edit_deletions = deletions;
757
    ap->has_different_distances = 1;
758
 
759
    APSE_DEBUG((printf("(edit distances: insertions = %ld, deletions = %ld, substitutions = %ld)\n",
760
		       ap->edit_insertions,
761
		       ap->edit_deletions,
762
		       ap->edit_substitutions)));
763
 
764
    okay = 1;
765
 
766
    return okay;
767
}
768
 
769
apse_size_t apse_get_deletions(apse_t *ap) {
770
    if (ap->has_different_distances)
771
	return ap->edit_deletions;
772
    else
773
	return ap->edit_distance;
774
}
775
 
776
apse_bool_t apse_set_substitutions(apse_t *ap, apse_size_t substitutions) {
777
    apse_bool_t	okay = 0;
778
 
779
    if (substitutions > ap->edit_distance)
780
	substitutions = ap->edit_distance;
781
    ap->edit_substitutions = substitutions;
782
    ap->has_different_distances = 1;
783
 
784
    APSE_DEBUG((printf("(edit distances: insertions = %ld, deletions = %ld, substitutions = %ld)\n",
785
		       ap->edit_insertions,
786
		       ap->edit_deletions,
787
		       ap->edit_substitutions)));
788
 
789
    okay = 1;
790
 
791
    return okay;
792
}
793
 
794
apse_size_t apse_get_substitutions(apse_t *ap) {
795
    if (ap->has_different_distances)
796
	return ap->edit_substitutions;
797
    else
798
	return ap->edit_distance;
799
}
800
 
801
#ifdef APSE_DEBUGGING
802
static const char* apse_match_state_name(apse_t* ap) {
803
    switch (ap->match_state) {
804
    case APSE_MATCH_STATE_BOT:		return "BOT";
805
    case APSE_MATCH_STATE_SEARCH:	return "SEARCH";
806
    case APSE_MATCH_STATE_BEGIN:	return "BEGIN";
807
    case APSE_MATCH_STATE_FAIL:		return "FAIL";
808
    case APSE_MATCH_STATE_GREEDY:	return "GREEDY";
809
    case APSE_MATCH_STATE_END:		return "END";
810
    case APSE_MATCH_STATE_EOT:		return "EOT";
811
    default:				return "***UNKNOWN***";
812
    }
813
}
814
#endif
815
 
816
static void _apse_match_bot(apse_t *ap) {
817
    APSE_DEBUG(printf("(text = \"%*.*s\", text_size = %ld)\n",
818
		       (int)ap->text_size, (int)ap->text_size, ap->text,
819
		       ap->text_size));
820
    apse_reset(ap);
821
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
822
    APSE_DEBUG(printf("(text begin %ld)\n", ap->text_position));
823
    if (ap->match_bot_callback)
824
	ap->match_bot_callback(ap);
825
}
826
 
827
static void _apse_match_begin(apse_t *ap) {
828
    ap->match_state = APSE_MATCH_STATE_BEGIN;
829
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
830
    APSE_DEBUG(printf("(match begin %ld)\n", ap->text_position));
831
    ap->match_begin = ap->text_position;
832
    if (ap->match_begin_callback)
833
	ap->match_begin_callback(ap);
834
}
835
 
836
static void _apse_match_fail(apse_t *ap) {
837
    ap->match_state = APSE_MATCH_STATE_FAIL;
838
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
839
    ap->match_begin = APSE_MATCH_BAD;
840
    APSE_DEBUG(printf("(match fail %ld)\n", ap->text_position));
841
    if (ap->match_fail_callback)
842
	ap->match_fail_callback(ap);
843
    ap->match_state = APSE_MATCH_STATE_SEARCH;
844
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
845
}
846
 
847
static void _apse_match_end(apse_t *ap) {
848
    ap->match_state = APSE_MATCH_STATE_END;
849
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
850
#ifdef APSE_DEBUGGING
851
    printf("(match end %ld)\n", ap->match_end);
852
    printf("(match string \"%.*s\")\n",
853
	   (int)(ap->match_end - ap->match_begin + 1),
854
	   ap->text + ap->match_begin);
855
    printf("(match length %ld)\n",
856
	   ap->match_end - ap->match_begin + 1);
857
#endif
858
    if (ap->match_end_callback)
859
	ap->match_end_callback(ap);
860
    ap->match_state = APSE_MATCH_STATE_SEARCH;
861
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
862
}
863
 
864
static void _apse_match_eot(apse_t *ap) {
865
    ap->match_state = APSE_MATCH_STATE_EOT;
866
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
867
    ap->text_position = ap->text_size;
868
    APSE_DEBUG(printf("(text end %ld)\n", ap->text_position));
869
    if (ap->match_eot_callback)
870
	ap->match_eot_callback(ap);
871
}
872
 
873
static apse_bool_t _apse_match_next_state(apse_t *ap) {
874
    apse_size_t	h, i, j, k;
875
    apse_vec_t	match;
876
 
877
    k = ap->edit_distance * ap->bitvectors_in_state;
878
 
879
    switch (ap->match_state) {
880
    case APSE_MATCH_STATE_SEARCH:
881
	if (APSE_EXACT_MATCH_BEGIN(ap) || APSE_APPROX_MATCH_BEGIN(ap))
882
	    _apse_match_begin(ap);
883
	break;
884
    case APSE_MATCH_STATE_BEGIN:
885
	{
886
	    apse_size_t		equal	= 0;
887
	    apse_size_t		active	= 0;
888
 
889
	    for (h = 0;
890
		 h <= k;
891
		 h += ap->bitvectors_in_state) {
892
		for (i = h, j = i + ap->bitvectors_in_state - 1; i < j; j--)
893
		    if (ap->state[j] != ap->prev_state[j])
894
			break;
895
		if (ap->prev_state[j] == ap->state[j])
896
		    equal++;
897
		if (ap->state[j])
898
		    active++;
899
	    }
900
#ifdef APSE_DEBUGGING
901
	    printf("(equal = %d, active = %d)\n", equal, active);
902
#endif
20000 hornik 903
	    if ((equal == ap->edit_distance + 1 && ap->is_greedy == 0) ||
904
		(equal < ap->prev_equal && ap->prev_active &&
905
		 active > ap->prev_active &&
906
		 !APSE_BIT_TST(ap->state,
907
			       ap->edit_distance,
908
			       ap->bitvectors_in_state,
909
			       ap->text_position - ap->match_begin))) {
19822 hornik 910
		ap->match_begin = ap->text_position;
911
#ifdef APSE_DEBUGGING
912
		printf("(slide begin %d)\n", ap->match_begin);
913
#endif
914
	    }
915
	    else if (active == 0)
916
		_apse_match_fail(ap);
917
	    ap->prev_equal  = equal;
918
	    ap->prev_active = active;
919
	}
920
	break;
921
    default:
922
	break;
923
    }
924
 
925
    for (match = 0, h = 0;
926
	 h <= k;
927
	 h += ap->bitvectors_in_state)
928
	match |= ap->state[h + ap->match_end_bitvector];
929
 
930
    if (match & ap->match_end_bitmask) {
931
	if (ap->match_state == APSE_MATCH_STATE_BEGIN) {
932
	    if (ap->is_greedy) {
933
		ap->match_state = APSE_MATCH_STATE_GREEDY;
934
		APSE_DEBUG(printf("(match state %s)\n",
935
				   apse_match_state_name(ap)));
936
		APSE_DEBUG(
937
		    printf("(greedy match continue %ld)\n",
938
			   ap->text_position));
939
	    } else {
940
		ap->match_state = APSE_MATCH_STATE_END;
941
		ap->match_end   = ap->text_position;
942
	    }
943
	}
944
    } else if (ap->match_state == APSE_MATCH_STATE_GREEDY) {
945
	ap->match_state = APSE_MATCH_STATE_END;
946
	APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
947
	ap->match_end	= ap->text_position - 1;
948
	APSE_DEBUG(printf("(match end %ld)\n",  ap->match_end));
949
    }
950
 
951
    return ap->match_state;
952
}
953
 
954
static void _apse_exact_multiple(apse_t* ap) {
955
    apse_size_t	h;
956
    apse_size_t	g = ap->edit_distance * ap->bitvectors_in_state;
957
 
958
    for (h = 0; h < ap->bitvectors_in_state; h++)
959
	ap->state[g + h] &= ~ap->exact_mask[h];
960
} 
961
 
962
static apse_bool_t _apse_match_single_simple(apse_t *ap) {
963
    /* single apse_vec_t, edit_distance */
964
 
965
    APSE_DEBUG(printf("(match single simple)\n"));
966
    for ( ; ap->text_position < ap->text_size; ap->text_position++) {
967
	apse_vec_t	t =
968
      	    ap->pattern_mask[(unsigned)ap->text[ap->text_position] *
969
			    ap->bitvectors_in_state];
970
	apse_size_t	h, g;
971
	APSE_NEXT_EXACT(ap->state, ap->prev_state, t, (apse_size_t)0, 1);
972
	APSE_DEBUG_SINGLE(ap, (apse_size_t)0);
973
 
974
	for (g = 0, h = 1; h <= ap->edit_distance; g = h, h++) {
975
	    APSE_NEXT_APPROX(ap->state, ap->prev_state, t, h, g, 1);
976
	    APSE_DEBUG_SINGLE(ap, h);
977
	}
978
 
979
	if (ap->exact_positions)
980
	    ap->state[ap->edit_distance] &= ~ap->exact_mask[0];
981
 
982
	if (_apse_match_next_state(ap) == APSE_MATCH_STATE_END)
983
	    return 1;
984
 
985
	(void)memcpy(ap->prev_state, ap->state, ap->bytes_in_all_states);
986
    }
987
 
988
    return 0;
989
}
990
 
991
static apse_bool_t _apse_match_multiple_simple(apse_t *ap) {
992
    /* multiple apse_vec_t:s, has_different_distances */
993
    apse_size_t	h, i;
994
 
995
    APSE_DEBUG(printf("(match multiple simple)\n"));
996
    for ( ; ap->text_position < ap->text_size; ap->text_position++) {
997
	apse_vec_t	*t =
998
	    ap->pattern_mask +
999
	    (unsigned)ap->text[ap->text_position] * ap->bitvectors_in_state;
1000
	apse_vec_t	c, d;
1001
 
1002
	APSE_DEBUG_MULTIPLE_FIRST(ap, (apse_size_t)0);
1003
	for (c = 1, i = 0; i < ap->bitvectors_in_state; i++, c = d) {
1004
	    d = APSE_TEST_HIGH_BIT(ap->state[i]);
1005
	    APSE_NEXT_EXACT(ap->state, ap->prev_state, t[i], i, c);
1006
	    APSE_DEBUG_MULTIPLE_REST(ap, i, i);
1007
	}
1008
	APSE_DEBUG(printf("\n"));
1009
 
1010
	for (h = 1; h <= ap->edit_distance; h++) {
1011
	    apse_size_t	kj = h * ap->bitvectors_in_state,
1012
			jj = kj - ap->bitvectors_in_state;
1013
 
1014
	    APSE_DEBUG_MULTIPLE_FIRST(ap, h);
1015
	    for (c = 1, i = 0;
1016
		 i < ap->bitvectors_in_state;
1017
		 i++, kj++, jj++, c = d) {
1018
		d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1019
		APSE_NEXT_APPROX(ap->state, ap->prev_state,
1020
				  t[i], kj, jj, c);
1021
		APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1022
	    }
1023
	    APSE_DEBUG(printf("\n"));
1024
	}
1025
 
1026
	if (ap->exact_positions)
1027
	    _apse_exact_multiple(ap);
1028
 
1029
	if (_apse_match_next_state(ap) == APSE_MATCH_STATE_END)
1030
	    return 1;
1031
 
1032
	(void)memcpy(ap->prev_state, ap->state,
1033
		     ap->bytes_in_all_states);
1034
    }
1035
 
1036
    return 0;
1037
}
1038
 
1039
static apse_bool_t _apse_match_single_complex(apse_t *ap) {
1040
    /* single apse_vec_t, has_different_distances */
1041
    APSE_DEBUG(printf("(match single complex)\n"));
1042
    for ( ; ap->text_position < ap->text_size; ap->text_position++) {
1043
	unsigned char	o = ap->text[ap->text_position];
1044
	apse_vec_t	t =
1045
	    ap->pattern_mask[(unsigned int)o * ap->bitvectors_in_state];
1046
	apse_size_t	h, g;
1047
 
1048
	APSE_NEXT_EXACT(ap->state, ap->prev_state, t, (apse_size_t)0, 1);
1049
	APSE_DEBUG_SINGLE(ap, (apse_size_t)0);
1050
 
1051
	for (g = 0, h = 1; h <= ap->edit_distance; g = h, h++) {
1052
	    apse_bool_t has_insertions    = h <= ap->edit_insertions;
1053
	    apse_bool_t has_deletions     = h <= ap->edit_deletions;
1054
	    apse_bool_t has_substitutions = h <= ap->edit_substitutions;
1055
 
1056
	    APSE_NEXT_COMMON(ap->state, ap->prev_state, t, h);
1057
	    if (has_insertions)
1058
		APSE_NEXT_INSERT(ap->state, ap->prev_state, h, g);
1059
	    if (has_deletions)
1060
		APSE_NEXT_DELETE(ap->state, h, g);
1061
	    if (has_substitutions)
1062
		APSE_NEXT_SUBSTI(ap->state, ap->prev_state, h, g);
1063
	    APSE_NEXT_CARRY(ap->state, h,
1064
			    has_deletions || has_substitutions ? 1 : 0);
1065
	    APSE_PREFIX_DELETE_MASK(ap);
1066
	    APSE_DEBUG_SINGLE(ap, h);
1067
	}
1068
 
1069
	if (ap->exact_positions)
1070
	    ap->state[ap->edit_distance] &= ~ap->exact_mask[0];
1071
 
1072
	if (_apse_match_next_state(ap) == APSE_MATCH_STATE_END)
1073
	    return 1;
1074
 
1075
	(void)memcpy(ap->prev_state, ap->state,
1076
		     ap->bytes_in_all_states);
1077
 
1078
    }
1079
 
1080
    return 0;
1081
}
1082
 
1083
static apse_bool_t _apse_match_multiple_complex(apse_t *ap) {
1084
    /* multiple apse_vec_t:s, has_different_distances */
1085
    apse_size_t	h, i;
1086
 
1087
    APSE_DEBUG(printf("(match multiple complex)\n"));
1088
    for ( ; ap->text_position < ap->text_size; ap->text_position++) {
1089
	unsigned char	o = ap->text[ap->text_position];
1090
	apse_vec_t	*t =
1091
	    ap->pattern_mask + (unsigned)o * ap->bitvectors_in_state;
1092
	apse_vec_t	c, d;
1093
 
1094
	APSE_DEBUG_MULTIPLE_FIRST(ap, (apse_size_t)0);
1095
	for (c = 1, i = 0; i < ap->bitvectors_in_state; i++, c = d) {
1096
	    d = APSE_TEST_HIGH_BIT(ap->state[i]);
1097
	    APSE_NEXT_EXACT(ap->state, ap->prev_state, t[i], i, c);
1098
	    APSE_DEBUG_MULTIPLE_REST(ap, i, i);
1099
	}
1100
	APSE_DEBUG(printf("\n"));
1101
 
1102
	for (h = 1; h <= ap->edit_distance; h++) {
1103
	    apse_size_t
1104
		kj = h * ap->bitvectors_in_state,
1105
		jj = kj - ap->bitvectors_in_state;
1106
 
1107
	    apse_bool_t	has_insertions    = h <= ap->edit_insertions;
1108
	    apse_bool_t	has_deletions     = h <= ap->edit_deletions;
1109
	    apse_bool_t	has_substitutions = h <= ap->edit_substitutions;
1110
 
1111
	    APSE_DEBUG_MULTIPLE_FIRST(ap, h);
1112
	    /* Is there such a thing as too much manual optimization? */
1113
	    if (has_insertions) {
1114
		if (has_deletions && has_substitutions) {
1115
		    for (c = 1, i = 0;
1116
			 i < ap->bitvectors_in_state;
1117
			 i++, kj++, jj++, c = d) {
1118
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1119
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1120
			APSE_NEXT_INSERT(ap->state, ap->prev_state, kj, jj);
1121
			APSE_NEXT_DELETE(ap->state, kj, jj);
1122
			APSE_NEXT_SUBSTI(ap->state, ap->prev_state, kj, jj);
1123
			APSE_NEXT_CARRY(ap->state, kj, c);
1124
			APSE_PREFIX_DELETE_MASK(ap);
1125
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1126
		    }
1127
		} else if (has_deletions) {
1128
		    for (c = 1, i = 0;
1129
			 i < ap->bitvectors_in_state;
1130
			 i++, kj++, jj++, c = d) {
1131
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1132
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1133
			APSE_NEXT_INSERT(ap->state, ap->prev_state, kj, jj);
1134
			APSE_NEXT_DELETE(ap->state, kj, jj);
1135
			APSE_NEXT_CARRY(ap->state, kj, c);
1136
			APSE_PREFIX_DELETE_MASK(ap);
1137
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1138
		    }
1139
		} else if (has_substitutions) {
1140
		    for (c = 1, i = 0;
1141
			 i < ap->bitvectors_in_state;
1142
			 i++, kj++, jj++, c = d) {
1143
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1144
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1145
			APSE_NEXT_INSERT(ap->state, ap->prev_state, kj, jj);
1146
			APSE_NEXT_SUBSTI(ap->state, ap->prev_state, kj, jj);
1147
			APSE_NEXT_CARRY(ap->state, kj, c);
1148
			APSE_PREFIX_DELETE_MASK(ap);
1149
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1150
		    }
1151
		} else {
1152
		    for (c = 1, i = 0;
1153
			 i < ap->bitvectors_in_state;
1154
			 i++, kj++, jj++, c = d) {
1155
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1156
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1157
			APSE_NEXT_INSERT(ap->state, ap->prev_state, kj, jj);
1158
			APSE_NEXT_CARRY(ap->state, kj, c);
1159
			APSE_PREFIX_DELETE_MASK(ap);
1160
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1161
		    }
1162
		}
1163
	    } else {
1164
		if (has_deletions && has_substitutions) {
1165
		    for (c = 1, i = 0;
1166
			 i < ap->bitvectors_in_state;
1167
			 i++, kj++, jj++, c = d) {
1168
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1169
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1170
			APSE_NEXT_DELETE(ap->state, kj, jj);
1171
			APSE_NEXT_SUBSTI(ap->state, ap->prev_state, kj, jj);
1172
			APSE_NEXT_CARRY(ap->state, kj, c);
1173
			APSE_PREFIX_DELETE_MASK(ap);
1174
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1175
		    }
1176
		} else if (has_deletions) {
1177
		    for (c = 1, i = 0;
1178
			 i < ap->bitvectors_in_state;
1179
			 i++, kj++, jj++, c = d) {
1180
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1181
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1182
			APSE_NEXT_DELETE(ap->state, kj, jj);
1183
			APSE_NEXT_CARRY(ap->state, kj, c);
1184
			APSE_PREFIX_DELETE_MASK(ap);
1185
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1186
		    }
1187
		} else if (has_substitutions) {
1188
		    for (c = 1, i = 0;
1189
			 i < ap->bitvectors_in_state;
1190
			 i++, kj++, jj++, c = d) {
1191
			d = APSE_TEST_HIGH_BIT(ap->state[kj]);
1192
			APSE_NEXT_COMMON(ap->state, ap->prev_state, t[i], kj);
1193
			APSE_NEXT_SUBSTI(ap->state, ap->prev_state, kj, jj);
1194
			APSE_NEXT_CARRY(ap->state, kj, c);
1195
			APSE_PREFIX_DELETE_MASK(ap);
1196
			APSE_DEBUG_MULTIPLE_REST(ap, i, kj);
1197
		    }
1198
		}
1199
	    }
1200
	    APSE_DEBUG(printf("\n"));
1201
 
1202
 
1203
	    if (ap->exact_positions)
1204
		_apse_exact_multiple(ap);
1205
 
1206
	    if (_apse_match_next_state(ap) == APSE_MATCH_STATE_END)
1207
		return 1;
1208
 
1209
	    (void)memcpy(ap->prev_state, ap->state,
1210
			 ap->bytes_in_all_states);
1211
	}
1212
    }
1213
 
1214
    return 0;
1215
}
1216
 
1217
static apse_bool_t __apse_match(apse_t		*ap,
1218
				unsigned char	*text,
1219
				apse_size_t	text_size) {
1220
    apse_bool_t	did_match = 0;
1221
 
1222
    APSE_DEBUG(printf("(match enter)\n"));
1223
 
1224
    if (ap->match_state == APSE_MATCH_STATE_BOT) {
1225
	ap->text      = text;
1226
	if (ap->text_final_position == APSE_MATCH_BAD)
1227
	    ap->text_size = text_size;
1228
	else
1229
	    ap->text_size =
1230
		ap->text_final_position > text_size ?
1231
		    text_size : ap->text_final_position + 1;
1232
	_apse_match_bot(ap);
1233
    } else if (ap->match_state == APSE_MATCH_STATE_EOT)
1234
	goto leave;
1235
 
1236
    if (ap->edit_deletions     >= ap->pattern_size ||
1237
	ap->edit_substitutions >= ap->pattern_size) {
1238
	ap->match_state   = APSE_MATCH_STATE_END;
1239
	ap->match_begin   = ap->text_initial_position;
1240
	ap->match_end     = ap->text_size - 1;
1241
	ap->text_position = ap->text_size;
1242
	goto out;
1243
    }
1244
 
1245
    if (ap->pattern_size - ap->edit_deletions >
1246
	ap->text_size - ap->text_initial_position) {
1247
	ap->match_state   = APSE_MATCH_STATE_EOT;
1248
	ap->text_position = ap->text_size;
1249
	goto out;
1250
    }
1251
 
1252
    if (text_size + ap->edit_distance < ap->pattern_size + ap->text_position) {
1253
	ap->text_position = ap->text_size;
1254
	goto eot;
1255
    }
1256
 
1257
    if (ap->match_state == APSE_MATCH_STATE_SEARCH) {
1258
	ap->text_position++;
1259
	_apse_reset_state(ap);
1260
    }
1261
 
1262
    if (ap->text_position_range != APSE_MATCH_BAD &&
1263
	ap->text_position - ap->text_initial_position >
1264
	ap->text_position_range) {
1265
	ap->match_state   = APSE_MATCH_STATE_END;
1266
	goto eot;
1267
    }
1268
 
1269
    ap->match_state = APSE_MATCH_STATE_SEARCH;
1270
    APSE_DEBUG(printf("(match state %s)\n", apse_match_state_name(ap)));
1271
    APSE_DEBUG(printf("(match search %ld)\n", ap->text_position));
1272
 
1273
    if (ap->has_different_distances) {
1274
	if (ap->bitvectors_in_state == 1) {
1275
	    if (_apse_match_single_complex(ap))
1276
		goto out;
1277
	} else {
1278
	    if (_apse_match_multiple_complex(ap))
1279
		goto out;
1280
	}
1281
    } else {
1282
	if (ap->bitvectors_in_state == 1) {
1283
	    if (_apse_match_single_simple(ap))
1284
		goto out;
1285
	} else {
1286
	    if (_apse_match_multiple_simple(ap))
1287
		goto out;
1288
	}
1289
    }
1290
 
1291
 out:
1292
 
1293
    if (ap->match_state == APSE_MATCH_STATE_GREEDY) {
1294
	ap->match_state = APSE_MATCH_STATE_END;
1295
	ap->match_end   = ap->text_position - 1;
1296
	APSE_DEBUG(printf("(greedy match end %ld)\n", ap->match_end));
1297
    }
1298
 
1299
    if (ap->match_state == APSE_MATCH_STATE_END) {
1300
	_apse_match_end(ap);
1301
	did_match = 1;
1302
    }
1303
 
1304
  eot:
1305
 
1306
    if (ap->text_position == ap->text_size)
1307
	_apse_match_eot(ap);
1308
 
1309
  leave:
1310
 
1311
    APSE_DEBUG(printf("(match leave)\n"));
1312
 
1313
    return did_match;
1314
}
1315
 
1316
static apse_bool_t _apse_match(apse_t 		*ap,
1317
			       unsigned char	*text,
1318
			       apse_size_t	text_size) {
1319
    if (ap->use_minimal_distance) {
1320
	apse_set_edit_distance(ap, 0);
1321
	if (__apse_match(ap, text, text_size))
1322
	    return 1;
1323
	else {
1324
	    apse_size_t minimal_edit_distance;
1325
	    apse_size_t previous_edit_distance = 0;
1326
	    apse_size_t next_edit_distance;
1327
 
1328
	    for (next_edit_distance = 1;
1329
		 next_edit_distance <= ap->pattern_size;
1330
		 next_edit_distance *= 2) {
1331
		apse_set_edit_distance(ap, next_edit_distance);
1332
		if (__apse_match(ap, text, text_size))
1333
		    break;
1334
		previous_edit_distance = next_edit_distance;
1335
	    } 
1336
	    minimal_edit_distance = next_edit_distance;
1337
	    if (next_edit_distance > 1) {
1338
		do {
1339
		    minimal_edit_distance =
1340
			(previous_edit_distance + next_edit_distance) / 2;
1341
		    if (minimal_edit_distance == previous_edit_distance)
1342
			break;
1343
		    apse_set_edit_distance(ap, minimal_edit_distance);
1344
		    if (__apse_match(ap, text, text_size))
1345
			next_edit_distance     = minimal_edit_distance;
1346
		    else
1347
			previous_edit_distance = minimal_edit_distance;
1348
		} while (previous_edit_distance <= next_edit_distance);
1349
		if (!__apse_match(ap, text, text_size))
1350
		    minimal_edit_distance++;
1351
	    }
1352
	    apse_set_edit_distance(ap, minimal_edit_distance);
1353
	    __apse_match(ap, text, text_size);
1354
 
1355
	    return 1;
1356
	}
1357
    } else
1358
	return __apse_match(ap, text, text_size);
1359
}
1360
 
1361
apse_bool_t apse_match(apse_t *ap,
1362
		       unsigned char *text, apse_size_t text_size) {
1363
    apse_bool_t did_match = _apse_match(ap, text, text_size);
1364
 
1365
    _apse_match_eot(ap);
1366
    apse_reset(ap);
1367
 
1368
    return did_match;
1369
}
1370
 
1371
apse_bool_t apse_match_next(apse_t *ap,
1372
			    unsigned char *text, apse_size_t text_size) {
1373
    apse_bool_t did_match = _apse_match(ap, text, text_size);
1374
 
1375
    if (!did_match)
1376
	ap->match_state = APSE_MATCH_STATE_BOT;
1377
 
1378
    return did_match;
1379
}
1380
 
1381
apse_ssize_t apse_index(apse_t *ap,
1382
			 unsigned char *text, apse_size_t text_size) {
1383
    apse_size_t did_match = _apse_match(ap, text, text_size);
1384
    _apse_match_eot(ap);
1385
    ap->match_state = APSE_MATCH_STATE_BOT;
1386
 
1387
    return did_match ? ap->match_begin : APSE_MATCH_BAD;
1388
}
1389
 
1390
apse_ssize_t apse_index_next(apse_t *ap,
1391
			     unsigned char *text, apse_size_t text_size) {
1392
    apse_bool_t did_match = _apse_match(ap, text, text_size);
1393
 
1394
    if (!did_match)
1395
	ap->match_state = APSE_MATCH_STATE_BOT;
1396
 
1397
    return did_match ? ap->match_begin : APSE_MATCH_BAD;
1398
}
1399
 
1400
static apse_bool_t _apse_slice(apse_t *ap,
1401
			       unsigned char *text,
1402
			       apse_size_t text_size,
1403
			       apse_size_t *match_begin,
1404
			       apse_size_t *match_size) {
1405
    apse_bool_t did_match = _apse_match(ap, text, text_size);
1406
 
1407
    if (did_match) {
1408
	if (match_begin)
1409
	    *match_begin = ap->match_begin;
1410
	if (match_size)
1411
	    *match_size	 = ap->match_end - ap->match_begin + 1;
1412
    } else {
1413
	if (match_begin)
1414
	    *match_begin = APSE_MATCH_BAD;
1415
	if (match_size)
1416
	    *match_size	 = APSE_MATCH_BAD;
1417
    }
1418
 
1419
    return did_match;
1420
}
1421
 
1422
apse_bool_t apse_slice(apse_t *ap,
1423
		       unsigned char *text,
1424
		       apse_size_t text_size,
1425
		       apse_size_t *match_begin,
1426
		       apse_size_t *match_size) {
1427
    apse_bool_t did_match =
1428
        _apse_slice(ap, text, text_size, match_begin, match_size);
1429
 
1430
    _apse_match_eot(ap);
1431
    ap->match_state = APSE_MATCH_STATE_BOT;
1432
 
1433
    return did_match;
1434
}
1435
 
1436
apse_bool_t apse_slice_next(apse_t*		ap,
1437
			    unsigned char*	text,
1438
			    apse_size_t		text_size,
1439
			    apse_size_t*	match_begin,
1440
			    apse_size_t*	match_size) {
1441
    apse_bool_t did_match =
1442
        _apse_slice(ap, text, text_size, match_begin, match_size);
1443
 
1444
    if (!did_match)
1445
	ap->match_state = APSE_MATCH_STATE_BOT;
1446
 
1447
    return did_match;
1448
}
1449
 
1450
void apse_set_custom_data(apse_t*	ap,
1451
			  void*		custom_data,
1452
			  apse_size_t	custom_data_size) {
1453
    ap->custom_data      = custom_data;
1454
    ap->custom_data_size = custom_data_size;
1455
}
1456
 
1457
void* apse_get_custom_data(apse_t*	ap,
1458
			   apse_size_t*	custom_data_size) {
1459
    if (custom_data_size)
1460
	*custom_data_size = ap->custom_data_size;
1461
    return ap->custom_data;
1462
}