Skip to content

Commit bdbd172

Browse files
committed
path: add path.glob
1 parent 284e6ac commit bdbd172

File tree

5 files changed

+144
-0
lines changed

5 files changed

+144
-0
lines changed

lib/path.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ const {
3131
StringPrototypeToLowerCase,
3232
} = primordials;
3333

34+
const { glob } = internalBinding('path');
35+
3436
const {
3537
CHAR_UPPERCASE_A,
3638
CHAR_LOWERCASE_A,
@@ -1064,6 +1066,7 @@ const win32 = {
10641066

10651067
return ret;
10661068
},
1069+
glob,
10671070

10681071
sep: '\\',
10691072
delimiter: ';',
@@ -1530,6 +1533,7 @@ const posix = {
15301533

15311534
return ret;
15321535
},
1536+
glob,
15331537

15341538
sep: '/',
15351539
delimiter: ':',

node.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
'src/node_metadata.cc',
107107
'src/node_options.cc',
108108
'src/node_os.cc',
109+
'src/node_path.cc',
109110
'src/node_perf.cc',
110111
'src/node_platform.cc',
111112
'src/node_postmortem_metadata.cc',
@@ -225,6 +226,7 @@
225226
'src/node_object_wrap.h',
226227
'src/node_options.h',
227228
'src/node_options-inl.h',
229+
'src/node_path.h',
228230
'src/node_perf.h',
229231
'src/node_perf_common.h',
230232
'src/node_platform.h',

src/node_binding.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
V(mksnapshot) \
5353
V(options) \
5454
V(os) \
55+
V(path) \
5556
V(performance) \
5657
V(permission) \
5758
V(pipe_wrap) \

src/node_path.cc

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#include "node_path.h"
2+
#include "env-inl.h"
3+
#include "node_errors.h"
4+
#include "node_external_reference.h"
5+
6+
namespace node {
7+
8+
namespace path {
9+
using v8::Context;
10+
using v8::FunctionCallbackInfo;
11+
using v8::Local;
12+
using v8::Object;
13+
using v8::Value;
14+
15+
// extracted from
16+
// https://github.com/torvalds/linux/blob/cdc9718d5e590d6905361800b938b93f2b66818e/lib/glob.c
17+
bool glob(char const* pat, char const* str) {
18+
/*
19+
* Backtrack to previous * on mismatch and retry starting one
20+
* character later in the string. Because * matches all characters
21+
* (no exception for /), it can be easily proved that there's
22+
* never a need to backtrack multiple levels.
23+
*/
24+
char const* back_pat = nullptr;
25+
char const* back_str;
26+
27+
/*
28+
* Loop over each token (character or class) in pat, matching
29+
* it against the remaining unmatched tail of str. Return false
30+
* on mismatch, or true after matching the trailing nul bytes.
31+
*/
32+
for (;;) {
33+
unsigned char c = *str++;
34+
unsigned char d = *pat++;
35+
36+
switch (d) {
37+
case '?': /* Wildcard: anything but nul */
38+
if (c == '\0') return false;
39+
break;
40+
case '*': /* Any-length wildcard */
41+
if (*pat == '\0') /* Optimize trailing * case */
42+
return true;
43+
back_pat = pat;
44+
back_str = --str; /* Allow zero-length match */
45+
break;
46+
case '[': { /* Character class */
47+
bool match = false, inverted = (*pat == '!');
48+
char const* cls = pat + inverted;
49+
unsigned char a = *cls++;
50+
51+
/*
52+
* Iterate over each span in the character class.
53+
* A span is either a single character a, or a
54+
* range a-b. The first span may begin with ']'.
55+
*/
56+
do {
57+
unsigned char b = a;
58+
59+
if (a == '\0') /* Malformed */
60+
goto literal;
61+
62+
if (cls[0] == '-' && cls[1] != ']') {
63+
b = cls[1];
64+
65+
if (b == '\0') goto literal;
66+
67+
cls += 2;
68+
/* Any special action if a > b? */
69+
}
70+
match |= (a <= c && c <= b);
71+
} while ((a = *cls++) != ']');
72+
73+
if (match == inverted) goto backtrack;
74+
pat = cls;
75+
} break;
76+
case '\\':
77+
d = *pat++;
78+
[[fallthrough]];
79+
default: /* Literal character */
80+
literal:
81+
if (c == d) {
82+
if (d == '\0') return true;
83+
break;
84+
}
85+
backtrack:
86+
if (c == '\0' || !back_pat) return false; /* No point continuing */
87+
/* Try again from last *, one character later in str. */
88+
pat = back_pat;
89+
str = ++back_str;
90+
break;
91+
}
92+
}
93+
}
94+
void glob(const FunctionCallbackInfo<Value>& args) {
95+
Environment* env = Environment::GetCurrent(args);
96+
CHECK_GE(args.Length(), 2);
97+
CHECK(args[0]->IsString());
98+
CHECK(args[1]->IsString());
99+
100+
std::string pattern = Utf8Value(env->isolate(), args[0]).ToString();
101+
std::string str = Utf8Value(env->isolate(), args[1]).ToString();
102+
args.GetReturnValue().Set(glob(pattern.c_str(), str.c_str()));
103+
}
104+
105+
void Initialize(Local<Object> target,
106+
Local<Value> unused,
107+
Local<Context> context,
108+
void* priv) {
109+
SetMethod(context, target, "glob", glob);
110+
}
111+
112+
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
113+
registry->Register(glob);
114+
}
115+
} // namespace path
116+
117+
} // namespace node
118+
119+
NODE_BINDING_CONTEXT_AWARE_INTERNAL(path, node::path::Initialize)
120+
NODE_BINDING_EXTERNAL_REFERENCE(path, node::path::RegisterExternalReferences)

src/node_path.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef SRC_NODE_PATH_H_
2+
#define SRC_NODE_PATH_H_
3+
4+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5+
6+
#include "base_object.h"
7+
#include "node_snapshotable.h"
8+
#include "v8.h"
9+
10+
namespace node {
11+
12+
namespace path {} // namespace path
13+
} // namespace node
14+
15+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
16+
17+
#endif // SRC_NODE_PATH_H_

0 commit comments

Comments
 (0)