| 481 | |
| 482 | template <typename CharType> |
| 483 | bool LikeEvaluator<CharType>::processNextChunk(const CharType* data, SLONG data_len) |
| 484 | { |
| 485 | fb_assert(patternItems.getCount()); |
| 486 | |
| 487 | // If called with empty buffer just return if more data can change the result of evaluation |
| 488 | if (!data_len) { |
| 489 | return branches.getCount() != 0 || match_type == MATCH_FIXED; |
| 490 | } |
| 491 | |
| 492 | if (match_type == MATCH_FIXED) |
| 493 | match_type = MATCH_NONE; |
| 494 | |
| 495 | if (branches.getCount() == 0) |
| 496 | return false; |
| 497 | |
| 498 | SLONG data_pos = 0; |
| 499 | SLONG finishCandidate = -1; |
| 500 | |
| 501 | while (data_pos < data_len) |
| 502 | { |
| 503 | FB_SIZE_T branch_number = 0; |
| 504 | while (branch_number < branches.getCount()) |
| 505 | { |
| 506 | BranchItem *current_branch = &branches[branch_number]; |
| 507 | PatternItem *current_pattern = current_branch->pattern; |
| 508 | switch (current_pattern->type) |
| 509 | { |
| 510 | case piDirectMatch: |
| 511 | if (data[data_pos] != current_pattern->str.data[current_branch->offset]) |
| 512 | { |
| 513 | // Terminate matching branch |
| 514 | branches.remove(branch_number); |
| 515 | if (branches.getCount() == 0) |
| 516 | return false; |
| 517 | continue; |
| 518 | } |
| 519 | // Note: fall into |
| 520 | case piSkipFixed: |
| 521 | current_branch->offset++; |
| 522 | if (current_branch->offset >= current_pattern->str.length) |
| 523 | { |
| 524 | // Switch to next subpattern or finish matching |
| 525 | if (current_pattern->match_any) |
| 526 | { |
| 527 | current_pattern++; |
| 528 | if (current_pattern >= patternItems.end()) { |
| 529 | branches.shrink(0); |
| 530 | match_type = MATCH_ANY; |
| 531 | return false; |
| 532 | } |
| 533 | branches.shrink(1); |
| 534 | branches[0].pattern = current_pattern; |
| 535 | branches[0].offset = 0; |
| 536 | branch_number = 0; |
| 537 | break; |
| 538 | } |
| 539 | current_pattern++; |
| 540 | if (current_pattern >= patternItems.end()) |