slang-netlist  0.11.0
Loading...
Searching...
No Matches
Wildcard.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <string_view>
4
5namespace slang::netlist {
6
28inline auto wildcardMatch(const char *text, const char *pattern) -> bool {
29 while (*pattern != '\0') {
30 // Detect a recursive wildcard token at the current pattern
31 // position, optionally preceded by a `.` we can absorb as part
32 // of a segment-boundary match.
33 bool hasLead = false;
34 const char *p = pattern;
35 if (*p == '.') {
36 const char *q = p + 1;
37 bool isRecur = (q[0] == '*' && q[1] == '*') ||
38 (q[0] == '.' && q[1] == '.' && q[2] == '.');
39 if (isRecur) {
40 hasLead = true;
41 p = q;
42 }
43 }
44
45 int recurLen = 0;
46 if (p[0] == '*' && p[1] == '*') {
47 recurLen = 2;
48 } else if (p[0] == '.' && p[1] == '.' && p[2] == '.') {
49 recurLen = 3;
50 }
51
52 if (recurLen != 0) {
53 const char *afterRecur = p + recurLen;
54 bool hasTrail = (*afterRecur == '.');
55 const char *rest = hasTrail ? afterRecur + 1 : afterRecur;
56
57 if (hasLead && hasTrail) {
58 // `.**.` — match a segment boundary `.` plus zero or more
59 // additional `<chars>.` segments before the boundary.
60 if (*text != '.') {
61 return false;
62 }
63 ++text;
64 if (wildcardMatch(text, rest)) {
65 return true;
66 }
67 while (*text != '\0') {
68 if (*text == '.' && wildcardMatch(text + 1, rest)) {
69 return true;
70 }
71 ++text;
72 }
73 return false;
74 }
75
76 if (hasLead) {
77 // `.**` with no trailing dot: match nothing, or `.` plus any
78 // suffix (including further `.`s).
79 if (wildcardMatch(text, rest)) {
80 return true;
81 }
82 if (*text != '.') {
83 return false;
84 }
85 ++text;
86 while (true) {
87 if (wildcardMatch(text, rest)) {
88 return true;
89 }
90 if (*text == '\0') {
91 return false;
92 }
93 ++text;
94 }
95 }
96
97 if (hasTrail) {
98 // `**.` with no leading dot: match nothing, or any prefix
99 // ending at a `.` (which the trailing `.` absorbs).
100 if (wildcardMatch(text, rest)) {
101 return true;
102 }
103 while (*text != '\0') {
104 if (*text == '.' && wildcardMatch(text + 1, rest)) {
105 return true;
106 }
107 ++text;
108 }
109 return false;
110 }
111
112 // Standalone `**` / `...`: match any (possibly empty) chars.
113 while (true) {
114 if (wildcardMatch(text, rest)) {
115 return true;
116 }
117 if (*text == '\0') {
118 return false;
119 }
120 ++text;
121 }
122 }
123
124 if (*pattern == '*') {
125 // Single-segment wildcard: matches zero or more non-`.` chars.
126 const char *rest = pattern + 1;
127 while (true) {
128 if (wildcardMatch(text, rest)) {
129 return true;
130 }
131 if (*text == '\0' || *text == '.') {
132 return false;
133 }
134 ++text;
135 }
136 }
137
138 if (*pattern == '?') {
139 // Single character within a segment; does not match `.` or end.
140 if (*text == '\0' || *text == '.') {
141 return false;
142 }
143 ++pattern;
144 ++text;
145 continue;
146 }
147
148 if (*pattern != *text) {
149 return false;
150 }
151 ++pattern;
152 ++text;
153 }
154 return *text == '\0';
155}
156
161inline auto pathInScope(std::string_view path, std::string_view scope) -> bool {
162 if (path.size() < scope.size() || path.substr(0, scope.size()) != scope) {
163 return false;
164 }
165 return path.size() == scope.size() || path[scope.size()] == '.';
166}
167
168} // namespace slang::netlist
Definition FormatBuffer.hpp:9
auto wildcardMatch(const char *text, const char *pattern) -> bool
Definition Wildcard.hpp:28
auto pathInScope(std::string_view path, std::string_view scope) -> bool
Definition Wildcard.hpp:161