cbm_ac_scan_batch scans multiple NUL-separated names through the automaton. For each name, reports all unique matched pattern IDs. Returns total number of matches written to out_matches. Parameters: ac — automaton names_buf — concatenated names separated by NUL bytes name_offsets — start offset of each name in names_buf name_lengths — length of each name num_names — number of name
| 365 | // out_matches — output buffer for (name_index, pattern_id) pairs |
| 366 | // max_matches — capacity of out_matches |
| 367 | int cbm_ac_scan_batch(const CBMAutomaton *ac, const char *names_buf, const int *name_offsets, |
| 368 | const int *name_lengths, int num_names, CBMMatchResult *out_matches, |
| 369 | int max_matches) { |
| 370 | int total = 0; |
| 371 | const int alpha_size = ac->alpha_size; |
| 372 | const int *go_table = ac->go_table; |
| 373 | |
| 374 | for (int n = 0; n < num_names && total < max_matches; n++) { |
| 375 | const char *text = names_buf + name_offsets[n]; |
| 376 | int text_len = name_lengths[n]; |
| 377 | int state = 0; |
| 378 | |
| 379 | // Track which patterns matched for this name (deduplicate). |
| 380 | uint64_t seen = 0; |
| 381 | |
| 382 | for (int i = 0; i < text_len; i++) { |
| 383 | int c = ac->alpha_map[(unsigned char)text[i]]; |
| 384 | state = go_table[(state * alpha_size) + c]; |
| 385 | |
| 386 | // Walk output chain for >64 patterns. |
| 387 | int s = state; |
| 388 | while (s > 0 && total < max_matches) { |
| 389 | // Bitmask fast path for first 64 patterns. |
| 390 | uint64_t bits = ac->output[s] & ~seen; |
| 391 | while (bits && total < max_matches) { |
| 392 | int pid = __builtin_ctzll(bits); |
| 393 | out_matches[total].name_index = n; |
| 394 | out_matches[total].pattern_id = pid; |
| 395 | total++; |
| 396 | seen |= CBM_AC_PATTERN_BIT(pid); |
| 397 | bits = CBM_AC_CLEAR_LOW_BIT(bits); |
| 398 | } |
| 399 | |
| 400 | // Follow output_next for patterns beyond bitmask range. |
| 401 | int next_state = ac->output_next[s]; |
| 402 | if (next_state == CBM_AC_NO_STATE || next_state == s) { |
| 403 | break; |
| 404 | } |
| 405 | s = next_state; |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | return total; |
| 410 | } |
| 411 | |
| 412 | // ─── Info ────────────────────────────────────────────────────────────────── |
| 413 |