1 #include "./wrapped_re2.h"
2 #include "./util.h"
3
4 #include <algorithm>
5 #include <limits>
6 #include <vector>
7
NAN_METHOD(WrappedRE2::Split)8 NAN_METHOD(WrappedRE2::Split)
9 {
10
11 auto result = Nan::New<v8::Array>();
12
13 // unpack arguments
14
15 auto re2 = Nan::ObjectWrap::Unwrap<WrappedRE2>(info.This());
16 if (!re2)
17 {
18 Nan::Set(result, 0, info[0]);
19 info.GetReturnValue().Set(result);
20 return;
21 }
22
23 StrVal a = info[0];
24 if (!a.data)
25 {
26 return;
27 }
28
29 re2::StringPiece str = a;
30
31 size_t limit = std::numeric_limits<size_t>::max();
32 if (info.Length() > 1 && info[1]->IsNumber())
33 {
34 size_t lim = info[1]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0);
35 if (lim > 0)
36 {
37 limit = lim;
38 }
39 }
40
41 // actual work
42
43 std::vector<re2::StringPiece> groups(re2->regexp.NumberOfCapturingGroups() + 1), pieces;
44 const auto &match = groups[0];
45 size_t lastIndex = 0;
46
47 while (lastIndex < a.size && re2->regexp.Match(str, lastIndex, a.size, RE2::UNANCHORED, &groups[0], groups.size()))
48 {
49 if (match.size())
50 {
51 pieces.push_back(re2::StringPiece(a.data + lastIndex, match.data() - a.data - lastIndex));
52 lastIndex = match.data() - a.data + match.size();
53 pieces.insert(pieces.end(), groups.begin() + 1, groups.end());
54 }
55 else
56 {
57 size_t sym_size = getUtf8CharSize(a.data[lastIndex]);
58 pieces.push_back(re2::StringPiece(a.data + lastIndex, sym_size));
59 lastIndex += sym_size;
60 }
61 if (pieces.size() >= limit)
62 {
63 break;
64 }
65 }
66 if (pieces.size() < limit && (lastIndex < a.size || (lastIndex == a.size && match.size())))
67 {
68 pieces.push_back(re2::StringPiece(a.data + lastIndex, a.size - lastIndex));
69 }
70
71 if (pieces.empty())
72 {
73 Nan::Set(result, 0, info[0]);
74 info.GetReturnValue().Set(result);
75 return;
76 }
77
78 // form a result
79
80 if (a.isBuffer)
81 {
82 for (size_t i = 0, n = std::min(pieces.size(), limit); i < n; ++i)
83 {
84 const auto &item = pieces[i];
85 Nan::Set(result, i, Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked());
86 }
87 }
88 else
89 {
90 for (size_t i = 0, n = std::min(pieces.size(), limit); i < n; ++i)
91 {
92 const auto &item = pieces[i];
93 Nan::Set(result, i, Nan::New(item.data(), item.size()).ToLocalChecked());
94 }
95 }
96
97 info.GetReturnValue().Set(result);
98 }
99