Line data Source code
1 : #include "Name.h"
2 :
3 : #include <ostream>
4 :
5 : namespace RtpsRelay {
6 :
7 22 : static void output_character(std::ostream& out, char c) {
8 22 : switch (c) {
9 6 : case '[':
10 : case ']':
11 : case '!':
12 : case '\\':
13 : case '?':
14 : case '*':
15 6 : out << '\\';
16 : }
17 22 : out << c;
18 22 : }
19 :
20 18 : std::ostream& operator<<(std::ostream& out, const Atom& atom)
21 : {
22 18 : switch (atom.kind()) {
23 8 : case Atom::CHARACTER:
24 8 : output_character(out, atom.character());
25 8 : break;
26 3 : case Atom::CHARACTER_CLASS:
27 3 : out << '[';
28 10 : for (char c : atom.characters()) {
29 7 : output_character(out, c);
30 : }
31 3 : out << ']';
32 3 : break;
33 3 : case Atom::NEGATED_CHARACTER_CLASS:
34 3 : out << "[!";
35 10 : for (char c : atom.characters()) {
36 7 : output_character(out, c);
37 : }
38 3 : out << ']';
39 3 : break;
40 2 : case Atom::WILDCARD:
41 2 : out << '?';
42 2 : break;
43 2 : case Atom::GLOB:
44 2 : out << '*';
45 2 : break;
46 : }
47 :
48 18 : return out;
49 : }
50 :
51 256 : void Name::parse(Name& name, const std::string& buffer, size_t& idx)
52 : {
53 256 : if (!name.is_valid_ || idx == buffer.size()) {
54 60 : return;
55 : }
56 :
57 196 : char c = buffer[idx];
58 196 : if (c == '?') {
59 8 : name.push_back(Atom(Atom::WILDCARD));
60 8 : ++idx;
61 188 : } else if (c == '*') {
62 38 : name.push_back(Atom(Atom::GLOB));
63 38 : ++idx;
64 150 : } else if (c == '[') {
65 25 : name.push_back(parse_character_class(name, buffer, idx));
66 : } else {
67 125 : name.push_back(Atom(parse_character(name, buffer, idx)));
68 : }
69 :
70 196 : parse(name, buffer, idx);
71 : }
72 :
73 174 : char Name::parse_character(Name& name, const std::string& buffer, size_t& idx)
74 : {
75 174 : char c = buffer[idx++];
76 174 : if (c == '\\') {
77 4 : if (idx == buffer.size()) {
78 1 : name.is_valid_ = false;
79 1 : return 0;
80 : }
81 3 : return buffer[idx++];
82 : } else {
83 170 : return c;
84 : }
85 : }
86 :
87 25 : Atom Name::parse_character_class(Name& name, const std::string& buffer, size_t& idx)
88 : {
89 25 : name.is_pattern_ = true;
90 :
91 : // Skip '[']
92 25 : ++idx;
93 :
94 25 : bool negated = false;
95 :
96 25 : if (idx == buffer.size()) {
97 1 : name.is_valid_ = false;
98 1 : return Atom(0);
99 : }
100 :
101 24 : if (buffer[idx] == '!') {
102 9 : negated = true;
103 9 : ++idx;
104 : }
105 :
106 : // One character is required.
107 24 : if (idx == buffer.size()) {
108 1 : name.is_valid_ = false;
109 1 : return Atom(0);
110 : }
111 :
112 23 : std::set<char> characters;
113 23 : parse_character_or_range(name, buffer, idx, characters);
114 23 : parse_character_class_tail(name, buffer, idx, characters);
115 :
116 23 : return Atom(negated, characters);
117 23 : }
118 :
119 42 : void Name::parse_character_class_tail(Name& name, const std::string& buffer, size_t& idx, std::set<char>& characters)
120 : {
121 42 : if (idx == buffer.size()) {
122 4 : name.is_valid_ = false;
123 4 : return;
124 : }
125 :
126 38 : char c = buffer[idx];
127 38 : if (c == ']') {
128 19 : ++idx;
129 19 : return;
130 : }
131 :
132 19 : parse_character_or_range(name, buffer, idx, characters);
133 19 : parse_character_class_tail(name, buffer, idx, characters);
134 : }
135 :
136 42 : void Name::parse_character_or_range(Name& name, const std::string& buffer, size_t& idx, std::set<char>& characters)
137 : {
138 42 : char first = parse_character(name, buffer, idx);
139 :
140 42 : if (idx == buffer.size()) {
141 2 : name.is_valid_ = false;
142 37 : return;
143 : }
144 :
145 40 : if (buffer[idx] != '-') {
146 32 : characters.insert(first);
147 32 : return;
148 : }
149 :
150 8 : ++idx;
151 :
152 8 : if (idx == buffer.size()) {
153 1 : name.is_valid_ = false;
154 1 : return;
155 : }
156 :
157 7 : char last = parse_character(name, buffer, idx);
158 7 : if (first > last) {
159 2 : name.is_valid_ = false;
160 2 : return;
161 : }
162 :
163 37 : for (; first <= last; ++first) {
164 32 : characters.insert(first);
165 : }
166 : }
167 :
168 1 : std::ostream& operator<<(std::ostream& out, const Name& name) {
169 8 : for (const auto& atom : name) {
170 7 : out << atom;
171 : }
172 1 : return out;
173 : }
174 :
175 : }
|