1 // Copyright 2022 The RE2 Authors. All Rights Reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include <memory>
6 #include <string>
7
8 #include <emscripten/bind.h>
9 #include "re2/prog.h"
10 #include "re2/re2.h"
11 #include "re2/regexp.h"
12
13 namespace re2_app {
14
15 struct Info {
16 std::string pattern;
17 std::string error;
18 std::string prefix;
19 bool prefix_foldcase = false;
20 std::string accel_prefix;
21 bool accel_prefix_foldcase = false;
22 int num_captures;
23 bool is_one_pass;
24 bool can_bit_state;
25 std::string bytecode;
26 std::string bytemap;
27 };
28
GetInfo(const std::string & pattern)29 Info GetInfo(const std::string& pattern) {
30 Info info;
31 info.pattern = pattern;
32
33 RE2::Options options;
34 re2::RegexpStatus status;
35 re2::Regexp* regexp = re2::Regexp::Parse(
36 pattern, static_cast<re2::Regexp::ParseFlags>(options.ParseFlags()),
37 &status);
38 if (regexp == nullptr) {
39 info.error = "failed to parse pattern: " + status.Text();
40 return info;
41 }
42
43 std::string prefix;
44 bool prefix_foldcase;
45 re2::Regexp* suffix;
46 if (regexp->RequiredPrefix(&prefix, &prefix_foldcase, &suffix)) {
47 info.prefix = prefix;
48 info.prefix_foldcase = prefix_foldcase;
49 } else {
50 suffix = regexp->Incref();
51 }
52
53 std::unique_ptr<re2::Prog> prog(suffix->CompileToProg(options.max_mem()));
54 if (prog == nullptr) {
55 info.error = "failed to compile forward Prog";
56 suffix->Decref();
57 regexp->Decref();
58 return info;
59 }
60
61 if (regexp->RequiredPrefixForAccel(&prefix, &prefix_foldcase)) {
62 info.accel_prefix = prefix;
63 info.accel_prefix_foldcase = prefix_foldcase;
64 }
65
66 info.num_captures = suffix->NumCaptures();
67 info.is_one_pass = prog->IsOnePass();
68 info.can_bit_state = prog->CanBitState();
69 info.bytecode = prog->Dump();
70 info.bytemap = prog->DumpByteMap();
71
72 suffix->Decref();
73 regexp->Decref();
74 return info;
75 }
76
EMSCRIPTEN_BINDINGS(_re2)77 EMSCRIPTEN_BINDINGS(_re2) {
78 emscripten::value_object<Info>("Info")
79 .field("pattern", &Info::pattern)
80 .field("error", &Info::error)
81 .field("prefix", &Info::prefix)
82 .field("prefix_foldcase", &Info::prefix_foldcase)
83 .field("accel_prefix", &Info::accel_prefix)
84 .field("accel_prefix_foldcase", &Info::accel_prefix_foldcase)
85 .field("num_captures", &Info::num_captures)
86 .field("is_one_pass", &Info::is_one_pass)
87 .field("can_bit_state", &Info::can_bit_state)
88 .field("bytecode", &Info::bytecode)
89 .field("bytemap", &Info::bytemap);
90
91 emscripten::function("getInfo", &GetInfo);
92 }
93
94 } // namespace re2_app
95