1/*
2 * Copyright (c) 2015-2017, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "nfa_build_util.h"
30
31#include "limex_internal.h"
32#include "mcclellancompile.h"
33#include "mcsheng_compile.h"
34#include "shengcompile.h"
35#include "nfa_internal.h"
36#include "repeat_internal.h"
37#include "ue2common.h"
38
39#include <algorithm>
40#include <cassert>
41#include <cstddef>
42#include <cstdio>
43#include <cstdlib>
44#include <cstring>
45#include <sstream>
46
47using namespace std;
48
49namespace ue2 {
50
51namespace {
52
53template<NFAEngineType t> struct NFATraits { };
54
55template<template<NFAEngineType t> class sfunc, typename rv_t, typename arg_t,
56 NFAEngineType lb>
57struct DISPATCH_BY_NFA_TYPE_INT {
58 static rv_t doOp(NFAEngineType i, const arg_t &arg) {
59 if (i == lb) {
60 return sfunc<lb>::call(arg);
61 } else {
62 return DISPATCH_BY_NFA_TYPE_INT<sfunc, rv_t, arg_t,
63 (NFAEngineType)(lb + 1)>
64 ::doOp(i, arg);
65 }
66 }
67};
68
69template<template<NFAEngineType t> class sfunc, typename rv_t, typename arg_t>
70struct DISPATCH_BY_NFA_TYPE_INT<sfunc, rv_t, arg_t, INVALID_NFA> {
71 // dummy
72 static rv_t doOp(NFAEngineType, const arg_t &) {
73 assert(0);
74 throw std::logic_error("Unreachable");
75 }
76};
77
78#define DISPATCH_BY_NFA_TYPE(i, op, arg) \
79 DISPATCH_BY_NFA_TYPE_INT<op, decltype(op<(NFAEngineType)0>::call(arg)), \
80 decltype(arg), (NFAEngineType)0>::doOp(i, arg)
81}
82
83typedef bool (*nfa_dispatch_fn)(const NFA *nfa);
84
85template<typename T>
86static
87bool has_accel_limex(const NFA *nfa) {
88 const T *limex = (const T *)getImplNfa(nfa);
89 return limex->accelCount;
90}
91
92template<typename T>
93static
94bool has_repeats_limex(const NFA *nfa) {
95 const T *limex = (const T *)getImplNfa(nfa);
96 return limex->repeatCount;
97}
98
99
100template<typename T>
101static
102bool has_repeats_other_than_firsts_limex(const NFA *nfa) {
103 const T *limex = (const T *)getImplNfa(nfa);
104 const char *ptr = (const char *)limex;
105
106 const u32 *repeatOffset = (const u32 *)(ptr + limex->repeatOffset);
107
108 for (u32 i = 0; i < limex->repeatCount; i++) {
109 u32 offset = repeatOffset[i];
110 const NFARepeatInfo *info = (const NFARepeatInfo *)(ptr + offset);
111 const RepeatInfo *repeat =
112 (const RepeatInfo *)((const char *)info + sizeof(*info));
113 if (repeat->type != REPEAT_FIRST) {
114 return true;
115 }
116 }
117
118 return false;
119}
120
121static
122bool dispatch_false(const NFA *) {
123 return false;
124}
125
126#ifdef DUMP_SUPPORT
127namespace {
128template<NFAEngineType t>
129struct getName {
130 static const char *call(void *) {
131 return NFATraits<t>::name;
132 }
133};
134
135// descr helper for LimEx NFAs
136template<NFAEngineType t>
137static
138string getDescriptionLimEx(const NFA *nfa) {
139 const typename NFATraits<t>::implNFA_t *limex =
140 (const typename NFATraits<t>::implNFA_t *)getImplNfa(nfa);
141 ostringstream oss;
142 oss << NFATraits<t>::name << "/" << limex->exceptionCount;
143 if (limex->repeatCount) {
144 oss << " +" << limex->repeatCount << "r";
145 }
146 return oss.str();
147}
148}
149
150// generic description: just return the name
151namespace {
152template<NFAEngineType t>
153struct getDescription {
154 static string call(const void *) {
155 return string(NFATraits<t>::name);
156 }
157};
158}
159#endif
160
161
162/* build-utility Traits */
163
164namespace {
165enum NFACategory {NFA_LIMEX, NFA_OTHER};
166
167// Some of our traits we want around in DUMP_SUPPORT mode only.
168#if defined(DUMP_SUPPORT)
169#define DO_IF_DUMP_SUPPORT(a) a
170#else
171#define DO_IF_DUMP_SUPPORT(a)
172#endif
173
174#define MAKE_LIMEX_TRAITS(mlt_size, mlt_align) \
175 template<> struct NFATraits<LIMEX_NFA_##mlt_size> { \
176 static UNUSED const char *name; \
177 static const NFACategory category = NFA_LIMEX; \
178 typedef LimExNFA##mlt_size implNFA_t; \
179 static const nfa_dispatch_fn has_accel; \
180 static const nfa_dispatch_fn has_repeats; \
181 static const nfa_dispatch_fn has_repeats_other_than_firsts; \
182 static const u32 stateAlign = \
183 MAX(mlt_align, alignof(RepeatControl)); \
184 static const bool fast = mlt_size <= 64; \
185 }; \
186 const nfa_dispatch_fn NFATraits<LIMEX_NFA_##mlt_size>::has_accel \
187 = has_accel_limex<LimExNFA##mlt_size>; \
188 const nfa_dispatch_fn NFATraits<LIMEX_NFA_##mlt_size>::has_repeats \
189 = has_repeats_limex<LimExNFA##mlt_size>; \
190 const nfa_dispatch_fn \
191 NFATraits<LIMEX_NFA_##mlt_size>::has_repeats_other_than_firsts \
192 = has_repeats_other_than_firsts_limex<LimExNFA##mlt_size>; \
193 DO_IF_DUMP_SUPPORT( \
194 const char *NFATraits<LIMEX_NFA_##mlt_size>::name \
195 = "LimEx "#mlt_size; \
196 template<> struct getDescription<LIMEX_NFA_##mlt_size> { \
197 static string call(const void *p) { \
198 return getDescriptionLimEx<LIMEX_NFA_##mlt_size>((const NFA *)p); \
199 } \
200 };)
201
202MAKE_LIMEX_TRAITS(32, alignof(u32))
203MAKE_LIMEX_TRAITS(64, alignof(m128)) /* special, 32bit arch uses m128 */
204MAKE_LIMEX_TRAITS(128, alignof(m128))
205MAKE_LIMEX_TRAITS(256, alignof(m256))
206MAKE_LIMEX_TRAITS(384, alignof(m384))
207MAKE_LIMEX_TRAITS(512, alignof(m512))
208
209template<> struct NFATraits<MCCLELLAN_NFA_8> {
210 UNUSED static const char *name;
211 static const NFACategory category = NFA_OTHER;
212 static const u32 stateAlign = 1;
213 static const bool fast = true;
214 static const nfa_dispatch_fn has_accel;
215 static const nfa_dispatch_fn has_repeats;
216 static const nfa_dispatch_fn has_repeats_other_than_firsts;
217};
218const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_8>::has_accel = has_accel_mcclellan;
219const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_8>::has_repeats = dispatch_false;
220const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
221#if defined(DUMP_SUPPORT)
222const char *NFATraits<MCCLELLAN_NFA_8>::name = "McClellan 8";
223#endif
224
225template<> struct NFATraits<MCCLELLAN_NFA_16> {
226 UNUSED static const char *name;
227 static const NFACategory category = NFA_OTHER;
228 static const u32 stateAlign = 2;
229 static const bool fast = true;
230 static const nfa_dispatch_fn has_accel;
231 static const nfa_dispatch_fn has_repeats;
232 static const nfa_dispatch_fn has_repeats_other_than_firsts;
233};
234const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_16>::has_accel = has_accel_mcclellan;
235const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_16>::has_repeats = dispatch_false;
236const nfa_dispatch_fn NFATraits<MCCLELLAN_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
237#if defined(DUMP_SUPPORT)
238const char *NFATraits<MCCLELLAN_NFA_16>::name = "McClellan 16";
239#endif
240
241template<> struct NFATraits<GOUGH_NFA_8> {
242 UNUSED static const char *name;
243 static const NFACategory category = NFA_OTHER;
244 static const u32 stateAlign = 8;
245 static const bool fast = true;
246 static const nfa_dispatch_fn has_accel;
247 static const nfa_dispatch_fn has_repeats;
248 static const nfa_dispatch_fn has_repeats_other_than_firsts;
249};
250const nfa_dispatch_fn NFATraits<GOUGH_NFA_8>::has_accel = has_accel_mcclellan;
251const nfa_dispatch_fn NFATraits<GOUGH_NFA_8>::has_repeats = dispatch_false;
252const nfa_dispatch_fn NFATraits<GOUGH_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
253#if defined(DUMP_SUPPORT)
254const char *NFATraits<GOUGH_NFA_8>::name = "Goughfish 8";
255#endif
256
257template<> struct NFATraits<GOUGH_NFA_16> {
258 UNUSED static const char *name;
259 static const NFACategory category = NFA_OTHER;
260 static const u32 stateAlign = 8;
261 static const bool fast = true;
262 static const nfa_dispatch_fn has_accel;
263 static const nfa_dispatch_fn has_repeats;
264 static const nfa_dispatch_fn has_repeats_other_than_firsts;
265};
266const nfa_dispatch_fn NFATraits<GOUGH_NFA_16>::has_accel = has_accel_mcclellan;
267const nfa_dispatch_fn NFATraits<GOUGH_NFA_16>::has_repeats = dispatch_false;
268const nfa_dispatch_fn NFATraits<GOUGH_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
269#if defined(DUMP_SUPPORT)
270const char *NFATraits<GOUGH_NFA_16>::name = "Goughfish 16";
271#endif
272
273template<> struct NFATraits<MPV_NFA> {
274 UNUSED static const char *name;
275 static const NFACategory category = NFA_OTHER;
276 static const u32 stateAlign = 8;
277 static const bool fast = true;
278 static const nfa_dispatch_fn has_accel;
279 static const nfa_dispatch_fn has_repeats;
280 static const nfa_dispatch_fn has_repeats_other_than_firsts;
281};
282const nfa_dispatch_fn NFATraits<MPV_NFA>::has_accel = dispatch_false;
283const nfa_dispatch_fn NFATraits<MPV_NFA>::has_repeats = dispatch_false;
284const nfa_dispatch_fn NFATraits<MPV_NFA>::has_repeats_other_than_firsts = dispatch_false;
285#if defined(DUMP_SUPPORT)
286const char *NFATraits<MPV_NFA>::name = "Mega-Puff-Vac";
287#endif
288
289template<> struct NFATraits<CASTLE_NFA> {
290 UNUSED static const char *name;
291 static const NFACategory category = NFA_OTHER;
292 static const u32 stateAlign = 8;
293 static const bool fast = true;
294 static const nfa_dispatch_fn has_accel;
295 static const nfa_dispatch_fn has_repeats;
296 static const nfa_dispatch_fn has_repeats_other_than_firsts;
297};
298const nfa_dispatch_fn NFATraits<CASTLE_NFA>::has_accel = dispatch_false;
299const nfa_dispatch_fn NFATraits<CASTLE_NFA>::has_repeats = dispatch_false;
300const nfa_dispatch_fn NFATraits<CASTLE_NFA>::has_repeats_other_than_firsts = dispatch_false;
301#if defined(DUMP_SUPPORT)
302const char *NFATraits<CASTLE_NFA>::name = "Castle";
303#endif
304
305template<> struct NFATraits<LBR_NFA_DOT> {
306 UNUSED static const char *name;
307 static const NFACategory category = NFA_OTHER;
308 static const u32 stateAlign = 8;
309 static const bool fast = true;
310 static const nfa_dispatch_fn has_accel;
311 static const nfa_dispatch_fn has_repeats;
312 static const nfa_dispatch_fn has_repeats_other_than_firsts;
313};
314const nfa_dispatch_fn NFATraits<LBR_NFA_DOT>::has_accel = dispatch_false;
315const nfa_dispatch_fn NFATraits<LBR_NFA_DOT>::has_repeats = dispatch_false;
316const nfa_dispatch_fn NFATraits<LBR_NFA_DOT>::has_repeats_other_than_firsts = dispatch_false;
317#if defined(DUMP_SUPPORT)
318const char *NFATraits<LBR_NFA_DOT>::name = "Lim Bounded Repeat (D)";
319#endif
320
321template<> struct NFATraits<LBR_NFA_VERM> {
322 UNUSED static const char *name;
323 static const NFACategory category = NFA_OTHER;
324 static const u32 stateAlign = 8;
325 static const bool fast = true;
326 static const nfa_dispatch_fn has_accel;
327 static const nfa_dispatch_fn has_repeats;
328 static const nfa_dispatch_fn has_repeats_other_than_firsts;
329};
330const nfa_dispatch_fn NFATraits<LBR_NFA_VERM>::has_accel = dispatch_false;
331const nfa_dispatch_fn NFATraits<LBR_NFA_VERM>::has_repeats = dispatch_false;
332const nfa_dispatch_fn NFATraits<LBR_NFA_VERM>::has_repeats_other_than_firsts = dispatch_false;
333#if defined(DUMP_SUPPORT)
334const char *NFATraits<LBR_NFA_VERM>::name = "Lim Bounded Repeat (V)";
335#endif
336
337template<> struct NFATraits<LBR_NFA_NVERM> {
338 UNUSED static const char *name;
339 static const NFACategory category = NFA_OTHER;
340 static const u32 stateAlign = 8;
341 static const bool fast = true;
342 static const nfa_dispatch_fn has_accel;
343 static const nfa_dispatch_fn has_repeats;
344 static const nfa_dispatch_fn has_repeats_other_than_firsts;
345};
346const nfa_dispatch_fn NFATraits<LBR_NFA_NVERM>::has_accel = dispatch_false;
347const nfa_dispatch_fn NFATraits<LBR_NFA_NVERM>::has_repeats = dispatch_false;
348const nfa_dispatch_fn NFATraits<LBR_NFA_NVERM>::has_repeats_other_than_firsts = dispatch_false;
349#if defined(DUMP_SUPPORT)
350const char *NFATraits<LBR_NFA_NVERM>::name = "Lim Bounded Repeat (NV)";
351#endif
352
353template<> struct NFATraits<LBR_NFA_SHUF> {
354 UNUSED static const char *name;
355 static const NFACategory category = NFA_OTHER;
356 static const u32 stateAlign = 8;
357 static const bool fast = true;
358 static const nfa_dispatch_fn has_accel;
359 static const nfa_dispatch_fn has_repeats;
360 static const nfa_dispatch_fn has_repeats_other_than_firsts;
361};
362const nfa_dispatch_fn NFATraits<LBR_NFA_SHUF>::has_accel = dispatch_false;
363const nfa_dispatch_fn NFATraits<LBR_NFA_SHUF>::has_repeats = dispatch_false;
364const nfa_dispatch_fn NFATraits<LBR_NFA_SHUF>::has_repeats_other_than_firsts = dispatch_false;
365#if defined(DUMP_SUPPORT)
366const char *NFATraits<LBR_NFA_SHUF>::name = "Lim Bounded Repeat (S)";
367#endif
368
369template<> struct NFATraits<LBR_NFA_TRUF> {
370 UNUSED static const char *name;
371 static const NFACategory category = NFA_OTHER;
372 static const u32 stateAlign = 8;
373 static const bool fast = true;
374 static const nfa_dispatch_fn has_accel;
375 static const nfa_dispatch_fn has_repeats;
376 static const nfa_dispatch_fn has_repeats_other_than_firsts;
377};
378const nfa_dispatch_fn NFATraits<LBR_NFA_TRUF>::has_accel = dispatch_false;
379const nfa_dispatch_fn NFATraits<LBR_NFA_TRUF>::has_repeats = dispatch_false;
380const nfa_dispatch_fn NFATraits<LBR_NFA_TRUF>::has_repeats_other_than_firsts = dispatch_false;
381#if defined(DUMP_SUPPORT)
382const char *NFATraits<LBR_NFA_TRUF>::name = "Lim Bounded Repeat (M)";
383#endif
384
385template<> struct NFATraits<SHENG_NFA> {
386 UNUSED static const char *name;
387 static const NFACategory category = NFA_OTHER;
388 static const u32 stateAlign = 1;
389 static const bool fast = true;
390 static const nfa_dispatch_fn has_accel;
391 static const nfa_dispatch_fn has_repeats;
392 static const nfa_dispatch_fn has_repeats_other_than_firsts;
393};
394const nfa_dispatch_fn NFATraits<SHENG_NFA>::has_accel = has_accel_sheng;
395const nfa_dispatch_fn NFATraits<SHENG_NFA>::has_repeats = dispatch_false;
396const nfa_dispatch_fn NFATraits<SHENG_NFA>::has_repeats_other_than_firsts = dispatch_false;
397#if defined(DUMP_SUPPORT)
398const char *NFATraits<SHENG_NFA>::name = "Sheng";
399#endif
400
401template<> struct NFATraits<TAMARAMA_NFA> {
402 UNUSED static const char *name;
403 static const NFACategory category = NFA_OTHER;
404 static const u32 stateAlign = 64;
405 static const bool fast = true;
406 static const nfa_dispatch_fn has_accel;
407 static const nfa_dispatch_fn has_repeats;
408 static const nfa_dispatch_fn has_repeats_other_than_firsts;
409};
410const nfa_dispatch_fn NFATraits<TAMARAMA_NFA>::has_accel = dispatch_false;
411const nfa_dispatch_fn NFATraits<TAMARAMA_NFA>::has_repeats = dispatch_false;
412const nfa_dispatch_fn NFATraits<TAMARAMA_NFA>::has_repeats_other_than_firsts = dispatch_false;
413#if defined(DUMP_SUPPORT)
414const char *NFATraits<TAMARAMA_NFA>::name = "Tamarama";
415#endif
416
417template<> struct NFATraits<MCSHENG_NFA_8> {
418 UNUSED static const char *name;
419 static const NFACategory category = NFA_OTHER;
420 static const u32 stateAlign = 1;
421 static const bool fast = true;
422 static const nfa_dispatch_fn has_accel;
423 static const nfa_dispatch_fn has_repeats;
424 static const nfa_dispatch_fn has_repeats_other_than_firsts;
425};
426const nfa_dispatch_fn NFATraits<MCSHENG_NFA_8>::has_accel = has_accel_mcsheng;
427const nfa_dispatch_fn NFATraits<MCSHENG_NFA_8>::has_repeats = dispatch_false;
428const nfa_dispatch_fn NFATraits<MCSHENG_NFA_8>::has_repeats_other_than_firsts = dispatch_false;
429#if defined(DUMP_SUPPORT)
430const char *NFATraits<MCSHENG_NFA_8>::name = "Shengy McShengFace 8";
431#endif
432
433template<> struct NFATraits<MCSHENG_NFA_16> {
434 UNUSED static const char *name;
435 static const NFACategory category = NFA_OTHER;
436 static const u32 stateAlign = 2;
437 static const bool fast = true;
438 static const nfa_dispatch_fn has_accel;
439 static const nfa_dispatch_fn has_repeats;
440 static const nfa_dispatch_fn has_repeats_other_than_firsts;
441};
442const nfa_dispatch_fn NFATraits<MCSHENG_NFA_16>::has_accel = has_accel_mcsheng;
443const nfa_dispatch_fn NFATraits<MCSHENG_NFA_16>::has_repeats = dispatch_false;
444const nfa_dispatch_fn NFATraits<MCSHENG_NFA_16>::has_repeats_other_than_firsts = dispatch_false;
445#if defined(DUMP_SUPPORT)
446const char *NFATraits<MCSHENG_NFA_16>::name = "Shengy McShengFace 16";
447#endif
448
449} // namespace
450
451#if defined(DUMP_SUPPORT)
452
453const char *nfa_type_name(NFAEngineType type) {
454 return DISPATCH_BY_NFA_TYPE(type, getName, nullptr);
455}
456
457string describe(const NFA &nfa) {
458 return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, getDescription, &nfa);
459}
460
461#endif /* DUMP_SUPPORT */
462
463namespace {
464template<NFAEngineType t>
465struct getStateAlign {
466 static u32 call(void *) {
467 return NFATraits<t>::stateAlign;
468 }
469};
470}
471
472u32 state_alignment(const NFA &nfa) {
473 return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, getStateAlign, nullptr);
474}
475
476namespace {
477template<NFAEngineType t>
478struct getFastness {
479 static u32 call(void *) {
480 return NFATraits<t>::fast;
481 }
482};
483}
484
485bool is_fast(const NFA &nfa) {
486 NFAEngineType t = (NFAEngineType)nfa.type;
487 return DISPATCH_BY_NFA_TYPE(t, getFastness, nullptr);
488}
489
490namespace {
491template<NFAEngineType t>
492struct is_limex {
493 static bool call(const void *) {
494 return NFATraits<t>::category == NFA_LIMEX;
495 }
496};
497}
498
499namespace {
500template<NFAEngineType t>
501struct has_repeats_other_than_firsts_dispatch {
502 static nfa_dispatch_fn call(const void *) {
503 return NFATraits<t>::has_repeats_other_than_firsts;
504 }
505};
506}
507
508bool has_bounded_repeats_other_than_firsts(const NFA &nfa) {
509 return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type,
510 has_repeats_other_than_firsts_dispatch,
511 &nfa)(&nfa);
512}
513
514namespace {
515template<NFAEngineType t>
516struct has_repeats_dispatch {
517 static nfa_dispatch_fn call(const void *) {
518 return NFATraits<t>::has_repeats;
519 }
520};
521}
522
523bool has_bounded_repeats(const NFA &nfa) {
524 return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, has_repeats_dispatch,
525 &nfa)(&nfa);
526}
527
528namespace {
529template<NFAEngineType t>
530struct has_accel_dispatch {
531 static nfa_dispatch_fn call(const void *) {
532 return NFATraits<t>::has_accel;
533 }
534};
535}
536
537bool has_accel(const NFA &nfa) {
538 return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, has_accel_dispatch,
539 &nfa)(&nfa);
540}
541
542bool requires_decompress_key(const NFA &nfa) {
543 return DISPATCH_BY_NFA_TYPE((NFAEngineType)nfa.type, is_limex, &nfa);
544}
545
546} // namespace ue2
547