Merge lp:~linaro-graphics-wg/libmatrix/split-refactor into lp:~jesse-barker/libmatrix/trunk
- split-refactor
- Merge into trunk
Proposed by
Alexandros Frantzis
Status: | Merged |
---|---|
Merged at revision: | 39 |
Proposed branch: | lp:~linaro-graphics-wg/libmatrix/split-refactor |
Merge into: | lp:~jesse-barker/libmatrix/trunk |
Diff against target: |
523 lines (+396/-26) 7 files modified
Makefile (+2/-0) shader-source.cc (+1/-1) test/libmatrix_test.cc (+4/-0) test/util_split_test.cc (+180/-0) test/util_split_test.h (+31/-0) util.cc (+160/-19) util.h (+18/-6) |
To merge this branch: | bzr merge lp:~linaro-graphics-wg/libmatrix/split-refactor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jesse Barker | Approve | ||
Review via email: mp+118059@code.launchpad.net |
Commit message
Description of the change
Refactor Util::split() interface and and support for splitting quoted strings using bash-like rules.
Note that I didn't add tests for SplitModeFuzzy as I haven't understood it's purpose and mechanism completely.
To post a comment you must log in.
- 42. By Alexandros Frantzis
-
Correct contributors section for util split test files.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Makefile' | |||
2 | --- Makefile 2012-05-02 21:36:04 +0000 | |||
3 | +++ Makefile 2012-08-06 15:06:24 +0000 | |||
4 | @@ -9,6 +9,7 @@ | |||
5 | 9 | $(TESTDIR)/inverse_test.cc \ | 9 | $(TESTDIR)/inverse_test.cc \ |
6 | 10 | $(TESTDIR)/transpose_test.cc \ | 10 | $(TESTDIR)/transpose_test.cc \ |
7 | 11 | $(TESTDIR)/shader_source_test.cc \ | 11 | $(TESTDIR)/shader_source_test.cc \ |
8 | 12 | $(TESTDIR)/util_split_test.cc \ | ||
9 | 12 | $(TESTDIR)/libmatrix_test.cc | 13 | $(TESTDIR)/libmatrix_test.cc |
10 | 13 | TESTOBJS = $(TESTSRCS:.cc=.o) | 14 | TESTOBJS = $(TESTSRCS:.cc=.o) |
11 | 14 | 15 | ||
12 | @@ -32,6 +33,7 @@ | |||
13 | 32 | $(TESTDIR)/inverse_test.o: $(TESTDIR)/inverse_test.cc $(TESTDIR)/inverse_test.h $(TESTDIR)/libmatrix_test.h mat.h | 33 | $(TESTDIR)/inverse_test.o: $(TESTDIR)/inverse_test.cc $(TESTDIR)/inverse_test.h $(TESTDIR)/libmatrix_test.h mat.h |
14 | 33 | $(TESTDIR)/transpose_test.o: $(TESTDIR)/transpose_test.cc $(TESTDIR)/transpose_test.h $(TESTDIR)/libmatrix_test.h mat.h | 34 | $(TESTDIR)/transpose_test.o: $(TESTDIR)/transpose_test.cc $(TESTDIR)/transpose_test.h $(TESTDIR)/libmatrix_test.h mat.h |
15 | 34 | $(TESTDIR)/shader_source_test.o: $(TESTDIR)/shader_source_test.cc $(TESTDIR)/shader_source_test.h $(TESTDIR)/libmatrix_test.h shader-source.h | 35 | $(TESTDIR)/shader_source_test.o: $(TESTDIR)/shader_source_test.cc $(TESTDIR)/shader_source_test.h $(TESTDIR)/libmatrix_test.h shader-source.h |
16 | 36 | $(TESTDIR)/util_split_test.o: $(TESTDIR)/util_split_test.cc $(TESTDIR)/util_split_test.h $(TESTDIR)/libmatrix_test.h util.h | ||
17 | 35 | $(TESTDIR)/libmatrix_test: $(TESTOBJS) libmatrix.a | 37 | $(TESTDIR)/libmatrix_test: $(TESTOBJS) libmatrix.a |
18 | 36 | $(CXX) -o $@ $^ | 38 | $(CXX) -o $@ $^ |
19 | 37 | run_tests: $(LIBMATRIX_TESTS) | 39 | run_tests: $(LIBMATRIX_TESTS) |
20 | 38 | 40 | ||
21 | === modified file 'shader-source.cc' | |||
22 | --- shader-source.cc 2012-01-26 16:12:35 +0000 | |||
23 | +++ shader-source.cc 2012-08-06 15:06:24 +0000 | |||
24 | @@ -589,7 +589,7 @@ | |||
25 | 589 | { | 589 | { |
26 | 590 | std::vector<std::string> elems; | 590 | std::vector<std::string> elems; |
27 | 591 | 591 | ||
29 | 592 | Util::split(precision_values, ',', elems); | 592 | Util::split(precision_values, ',', elems, Util::SplitModeNormal); |
30 | 593 | 593 | ||
31 | 594 | for (size_t i = 0; i < elems.size() && i < 4; i++) { | 594 | for (size_t i = 0; i < elems.size() && i < 4; i++) { |
32 | 595 | const std::string& pstr(elems[i]); | 595 | const std::string& pstr(elems[i]); |
33 | 596 | 596 | ||
34 | === modified file 'test/libmatrix_test.cc' | |||
35 | --- test/libmatrix_test.cc 2012-01-23 19:18:34 +0000 | |||
36 | +++ test/libmatrix_test.cc 2012-08-06 15:06:24 +0000 | |||
37 | @@ -8,6 +8,7 @@ | |||
38 | 8 | // | 8 | // |
39 | 9 | // Contributors: | 9 | // Contributors: |
40 | 10 | // Jesse Barker - original implementation. | 10 | // Jesse Barker - original implementation. |
41 | 11 | // Alexandros Frantzis - Util::split tests | ||
42 | 11 | // | 12 | // |
43 | 12 | #include <iostream> | 13 | #include <iostream> |
44 | 13 | #include <string> | 14 | #include <string> |
45 | @@ -17,6 +18,7 @@ | |||
46 | 17 | #include "transpose_test.h" | 18 | #include "transpose_test.h" |
47 | 18 | #include "const_vec_test.h" | 19 | #include "const_vec_test.h" |
48 | 19 | #include "shader_source_test.h" | 20 | #include "shader_source_test.h" |
49 | 21 | #include "util_split_test.h" | ||
50 | 20 | 22 | ||
51 | 21 | using std::cerr; | 23 | using std::cerr; |
52 | 22 | using std::cout; | 24 | using std::cout; |
53 | @@ -42,6 +44,8 @@ | |||
54 | 42 | testVec.push_back(new MatrixTest3x3Transpose()); | 44 | testVec.push_back(new MatrixTest3x3Transpose()); |
55 | 43 | testVec.push_back(new MatrixTest4x4Transpose()); | 45 | testVec.push_back(new MatrixTest4x4Transpose()); |
56 | 44 | testVec.push_back(new ShaderSourceBasic()); | 46 | testVec.push_back(new ShaderSourceBasic()); |
57 | 47 | testVec.push_back(new UtilSplitTestNormal()); | ||
58 | 48 | testVec.push_back(new UtilSplitTestQuoted()); | ||
59 | 45 | 49 | ||
60 | 46 | for (vector<MatrixTest*>::iterator testIt = testVec.begin(); | 50 | for (vector<MatrixTest*>::iterator testIt = testVec.begin(); |
61 | 47 | testIt != testVec.end(); | 51 | testIt != testVec.end(); |
62 | 48 | 52 | ||
63 | === added file 'test/util_split_test.cc' | |||
64 | --- test/util_split_test.cc 1970-01-01 00:00:00 +0000 | |||
65 | +++ test/util_split_test.cc 2012-08-06 15:06:24 +0000 | |||
66 | @@ -0,0 +1,180 @@ | |||
67 | 1 | // | ||
68 | 2 | // Copyright (c) 2012 Linaro Limited | ||
69 | 3 | // | ||
70 | 4 | // All rights reserved. This program and the accompanying materials | ||
71 | 5 | // are made available under the terms of the MIT License which accompanies | ||
72 | 6 | // this distribution, and is available at | ||
73 | 7 | // http://www.opensource.org/licenses/mit-license.php | ||
74 | 8 | // | ||
75 | 9 | // Contributors: | ||
76 | 10 | // Alexandros Frantzis - original implementation. | ||
77 | 11 | // | ||
78 | 12 | #include <iostream> | ||
79 | 13 | #include <string> | ||
80 | 14 | #include <vector> | ||
81 | 15 | #include "libmatrix_test.h" | ||
82 | 16 | #include "util_split_test.h" | ||
83 | 17 | #include "../util.h" | ||
84 | 18 | |||
85 | 19 | using std::cout; | ||
86 | 20 | using std::endl; | ||
87 | 21 | using std::string; | ||
88 | 22 | using std::vector; | ||
89 | 23 | |||
90 | 24 | template <typename T> static bool | ||
91 | 25 | areVectorsEqual(vector<T>& vec1, vector<T>& vec2) | ||
92 | 26 | { | ||
93 | 27 | if (vec1.size() != vec2.size()) | ||
94 | 28 | return false; | ||
95 | 29 | |||
96 | 30 | for (unsigned int i = 0; i < vec1.size(); i++) | ||
97 | 31 | { | ||
98 | 32 | if (vec1[i] != vec2[i]) | ||
99 | 33 | return false; | ||
100 | 34 | } | ||
101 | 35 | |||
102 | 36 | return true; | ||
103 | 37 | } | ||
104 | 38 | |||
105 | 39 | template <typename T> static void | ||
106 | 40 | printVector(vector<T>& vec) | ||
107 | 41 | { | ||
108 | 42 | cout << "["; | ||
109 | 43 | for (unsigned int i = 0; i < vec.size(); i++) | ||
110 | 44 | { | ||
111 | 45 | cout << '"' << vec[i] << '"'; | ||
112 | 46 | if (i < vec.size() - 1) | ||
113 | 47 | cout << ", "; | ||
114 | 48 | } | ||
115 | 49 | cout << "]"; | ||
116 | 50 | } | ||
117 | 51 | |||
118 | 52 | void | ||
119 | 53 | UtilSplitTestNormal::run(const Options& options) | ||
120 | 54 | { | ||
121 | 55 | const string test1("abc def ghi"); | ||
122 | 56 | const string test2(" abc: def :ghi "); | ||
123 | 57 | vector<string> expected1; | ||
124 | 58 | vector<string> expected2; | ||
125 | 59 | vector<string> results; | ||
126 | 60 | |||
127 | 61 | expected1.push_back("abc"); | ||
128 | 62 | expected1.push_back("def"); | ||
129 | 63 | expected1.push_back("ghi"); | ||
130 | 64 | |||
131 | 65 | expected2.push_back(" abc"); | ||
132 | 66 | expected2.push_back(" def "); | ||
133 | 67 | expected2.push_back("ghi "); | ||
134 | 68 | |||
135 | 69 | if (options.beVerbose()) | ||
136 | 70 | { | ||
137 | 71 | cout << "Testing string \"" << test1 << "\"" << endl; | ||
138 | 72 | } | ||
139 | 73 | |||
140 | 74 | Util::split(test1, ' ', results, Util::SplitModeNormal); | ||
141 | 75 | |||
142 | 76 | if (options.beVerbose()) | ||
143 | 77 | { | ||
144 | 78 | cout << "Split result: "; | ||
145 | 79 | printVector(results); | ||
146 | 80 | cout << endl << "Expected: "; | ||
147 | 81 | printVector(expected1); | ||
148 | 82 | cout << endl; | ||
149 | 83 | } | ||
150 | 84 | |||
151 | 85 | if (!areVectorsEqual(results, expected1)) | ||
152 | 86 | { | ||
153 | 87 | return; | ||
154 | 88 | } | ||
155 | 89 | |||
156 | 90 | results.clear(); | ||
157 | 91 | |||
158 | 92 | if (options.beVerbose()) | ||
159 | 93 | { | ||
160 | 94 | cout << "Testing string \"" << test2 << "\"" << endl; | ||
161 | 95 | } | ||
162 | 96 | |||
163 | 97 | Util::split(test2, ':', results, Util::SplitModeNormal); | ||
164 | 98 | |||
165 | 99 | if (options.beVerbose()) | ||
166 | 100 | { | ||
167 | 101 | cout << "Split result: "; | ||
168 | 102 | printVector(results); | ||
169 | 103 | cout << endl << "Expected: "; | ||
170 | 104 | printVector(expected2); | ||
171 | 105 | cout << endl; | ||
172 | 106 | } | ||
173 | 107 | |||
174 | 108 | if (!areVectorsEqual(results, expected2)) | ||
175 | 109 | { | ||
176 | 110 | return; | ||
177 | 111 | } | ||
178 | 112 | |||
179 | 113 | pass_ = true; | ||
180 | 114 | } | ||
181 | 115 | |||
182 | 116 | void | ||
183 | 117 | UtilSplitTestQuoted::run(const Options& options) | ||
184 | 118 | { | ||
185 | 119 | const string test1("abc \"def' ghi\" klm\\ nop -b qr:title='123 \"456'"); | ||
186 | 120 | const string test2("abc: def='1:2:3:'ghi : \":jk\""); | ||
187 | 121 | vector<string> expected1; | ||
188 | 122 | vector<string> expected2; | ||
189 | 123 | vector<string> results; | ||
190 | 124 | |||
191 | 125 | expected1.push_back("abc"); | ||
192 | 126 | expected1.push_back("def' ghi"); | ||
193 | 127 | expected1.push_back("klm nop"); | ||
194 | 128 | expected1.push_back("-b"); | ||
195 | 129 | expected1.push_back("qr:title=123 \"456"); | ||
196 | 130 | |||
197 | 131 | expected2.push_back("abc"); | ||
198 | 132 | expected2.push_back(" def=1:2:3:ghi "); | ||
199 | 133 | expected2.push_back(" :jk"); | ||
200 | 134 | |||
201 | 135 | if (options.beVerbose()) | ||
202 | 136 | { | ||
203 | 137 | cout << "Testing string \"" << test1 << "\"" << endl; | ||
204 | 138 | } | ||
205 | 139 | |||
206 | 140 | Util::split(test1, ' ', results, Util::SplitModeQuoted); | ||
207 | 141 | |||
208 | 142 | if (options.beVerbose()) | ||
209 | 143 | { | ||
210 | 144 | cout << "Split result: "; | ||
211 | 145 | printVector(results); | ||
212 | 146 | cout << endl << "Expected: "; | ||
213 | 147 | printVector(expected1); | ||
214 | 148 | cout << endl; | ||
215 | 149 | } | ||
216 | 150 | |||
217 | 151 | if (!areVectorsEqual(results, expected1)) | ||
218 | 152 | { | ||
219 | 153 | return; | ||
220 | 154 | } | ||
221 | 155 | |||
222 | 156 | results.clear(); | ||
223 | 157 | |||
224 | 158 | if (options.beVerbose()) | ||
225 | 159 | { | ||
226 | 160 | cout << "Testing string \"" << test2 << "\"" << endl; | ||
227 | 161 | } | ||
228 | 162 | |||
229 | 163 | Util::split(test2, ':', results, Util::SplitModeQuoted); | ||
230 | 164 | |||
231 | 165 | if (options.beVerbose()) | ||
232 | 166 | { | ||
233 | 167 | cout << "Split result: "; | ||
234 | 168 | printVector(results); | ||
235 | 169 | cout << endl << "Expected: "; | ||
236 | 170 | printVector(expected2); | ||
237 | 171 | cout << endl; | ||
238 | 172 | } | ||
239 | 173 | |||
240 | 174 | if (!areVectorsEqual(results, expected2)) | ||
241 | 175 | { | ||
242 | 176 | return; | ||
243 | 177 | } | ||
244 | 178 | |||
245 | 179 | pass_ = true; | ||
246 | 180 | } | ||
247 | 0 | 181 | ||
248 | === added file 'test/util_split_test.h' | |||
249 | --- test/util_split_test.h 1970-01-01 00:00:00 +0000 | |||
250 | +++ test/util_split_test.h 2012-08-06 15:06:24 +0000 | |||
251 | @@ -0,0 +1,31 @@ | |||
252 | 1 | // | ||
253 | 2 | // Copyright (c) 2012 Linaro Limited | ||
254 | 3 | // | ||
255 | 4 | // All rights reserved. This program and the accompanying materials | ||
256 | 5 | // are made available under the terms of the MIT License which accompanies | ||
257 | 6 | // this distribution, and is available at | ||
258 | 7 | // http://www.opensource.org/licenses/mit-license.php | ||
259 | 8 | // | ||
260 | 9 | // Contributors: | ||
261 | 10 | // Alexandros Frantzis - original implementation. | ||
262 | 11 | // | ||
263 | 12 | #ifndef UTIL_SPLIT_TEST_H_ | ||
264 | 13 | #define UTIL_SPLIT_TEST_H_ | ||
265 | 14 | |||
266 | 15 | class MatrixTest; | ||
267 | 16 | class Options; | ||
268 | 17 | |||
269 | 18 | class UtilSplitTestNormal : public MatrixTest | ||
270 | 19 | { | ||
271 | 20 | public: | ||
272 | 21 | UtilSplitTestNormal() : MatrixTest("Util::split::normal") {} | ||
273 | 22 | virtual void run(const Options& options); | ||
274 | 23 | }; | ||
275 | 24 | |||
276 | 25 | class UtilSplitTestQuoted : public MatrixTest | ||
277 | 26 | { | ||
278 | 27 | public: | ||
279 | 28 | UtilSplitTestQuoted() : MatrixTest("Util::split::quoted") {} | ||
280 | 29 | virtual void run(const Options& options); | ||
281 | 30 | }; | ||
282 | 31 | #endif // UTIL_SPLIT_TEST_H_ | ||
283 | 0 | 32 | ||
284 | === modified file 'util.cc' | |||
285 | --- util.cc 2012-05-02 21:36:04 +0000 | |||
286 | +++ util.cc 2012-08-06 15:06:24 +0000 | |||
287 | @@ -25,25 +25,102 @@ | |||
288 | 25 | using std::string; | 25 | using std::string; |
289 | 26 | using std::vector; | 26 | using std::vector; |
290 | 27 | 27 | ||
310 | 28 | void | 28 | /* |
311 | 29 | Util::split(const string& src, char delim, vector<string>& elementVec, bool fuzzy) | 29 | * State machine for bash-like quoted string escaping: |
312 | 30 | { | 30 | * |
313 | 31 | // Trivial rejection | 31 | * \ |
314 | 32 | if (src.empty()) | 32 | * -----------> +---------+ |
315 | 33 | { | 33 | * | ---------- | Escaped | |
316 | 34 | return; | 34 | * | | *,ESC +---------+ |
317 | 35 | } | 35 | * | | |
318 | 36 | 36 | * | v ' | |
319 | 37 | // Simple case: we want to enforce the value of 'delim' strictly | 37 | * +--------+ ---> +--------------+ ----- |
320 | 38 | if (!fuzzy) | 38 | * | Normal | <--- | SingleQuoted | | *, ESC |
321 | 39 | { | 39 | * +--------+ ' +--------------+ <---- |
322 | 40 | std::stringstream ss(src); | 40 | * | ^ |
323 | 41 | string item; | 41 | * | | |
324 | 42 | while(std::getline(ss, item, delim)) | 42 | * | | " +--------------+ ---- |
325 | 43 | elementVec.push_back(item); | 43 | * | ---------- | DoubleQuoted | | *, ESC |
326 | 44 | return; | 44 | * -----------> +--------------+ <--- |
327 | 45 | } | 45 | * " | ^ |
328 | 46 | 46 | * \ | | *, ESC | |
329 | 47 | * v | | ||
330 | 48 | * +---------------------+ | ||
331 | 49 | * | DoubleQuotedEscaped | | ||
332 | 50 | * +---------------------+ | ||
333 | 51 | * | ||
334 | 52 | * ESC: Mark character as Escaped | ||
335 | 53 | */ | ||
336 | 54 | static void | ||
337 | 55 | fill_escape_vector(const string &str, vector<bool> &esc_vec) | ||
338 | 56 | { | ||
339 | 57 | enum State { | ||
340 | 58 | StateNormal, | ||
341 | 59 | StateEscaped, | ||
342 | 60 | StateDoubleQuoted, | ||
343 | 61 | StateDoubleQuotedEscaped, | ||
344 | 62 | StateSingleQuoted | ||
345 | 63 | }; | ||
346 | 64 | |||
347 | 65 | State state = StateNormal; | ||
348 | 66 | |||
349 | 67 | for (string::const_iterator iter = str.begin(); | ||
350 | 68 | iter != str.end(); | ||
351 | 69 | iter++) | ||
352 | 70 | { | ||
353 | 71 | const char c(*iter); | ||
354 | 72 | bool esc = false; | ||
355 | 73 | |||
356 | 74 | switch (state) { | ||
357 | 75 | case StateNormal: | ||
358 | 76 | if (c == '"') | ||
359 | 77 | state = StateDoubleQuoted; | ||
360 | 78 | else if (c == '\\') | ||
361 | 79 | state = StateEscaped; | ||
362 | 80 | else if (c == '\'') | ||
363 | 81 | state = StateSingleQuoted; | ||
364 | 82 | break; | ||
365 | 83 | case StateEscaped: | ||
366 | 84 | esc = true; | ||
367 | 85 | state = StateNormal; | ||
368 | 86 | break; | ||
369 | 87 | case StateDoubleQuoted: | ||
370 | 88 | if (c == '"') | ||
371 | 89 | state = StateNormal; | ||
372 | 90 | else if (c == '\\') | ||
373 | 91 | state = StateDoubleQuotedEscaped; | ||
374 | 92 | else | ||
375 | 93 | esc = true; | ||
376 | 94 | break; | ||
377 | 95 | case StateDoubleQuotedEscaped: | ||
378 | 96 | esc = true; | ||
379 | 97 | state = StateDoubleQuoted; | ||
380 | 98 | break; | ||
381 | 99 | case StateSingleQuoted: | ||
382 | 100 | if (c == '\'') | ||
383 | 101 | state = StateNormal; | ||
384 | 102 | else | ||
385 | 103 | esc = true; | ||
386 | 104 | default: | ||
387 | 105 | break; | ||
388 | 106 | } | ||
389 | 107 | |||
390 | 108 | esc_vec.push_back(esc); | ||
391 | 109 | } | ||
392 | 110 | } | ||
393 | 111 | |||
394 | 112 | static void | ||
395 | 113 | split_normal(const string& src, char delim, vector<string>& elementVec) | ||
396 | 114 | { | ||
397 | 115 | std::stringstream ss(src); | ||
398 | 116 | string item; | ||
399 | 117 | while(std::getline(ss, item, delim)) | ||
400 | 118 | elementVec.push_back(item); | ||
401 | 119 | } | ||
402 | 120 | |||
403 | 121 | static void | ||
404 | 122 | split_fuzzy(const string& src, char delim, vector<string>& elementVec) | ||
405 | 123 | { | ||
406 | 47 | // Fuzzy case: Initialize our delimiter string based upon the caller's plus | 124 | // Fuzzy case: Initialize our delimiter string based upon the caller's plus |
407 | 48 | // a space to allow for more flexibility. | 125 | // a space to allow for more flexibility. |
408 | 49 | string delimiter(" "); | 126 | string delimiter(" "); |
409 | @@ -76,6 +153,70 @@ | |||
410 | 76 | elementVec.push_back(str); | 153 | elementVec.push_back(str); |
411 | 77 | } | 154 | } |
412 | 78 | 155 | ||
413 | 156 | static void | ||
414 | 157 | split_quoted(const string& src, char delim, vector<string>& elementVec) | ||
415 | 158 | { | ||
416 | 159 | std::stringstream ss; | ||
417 | 160 | vector<bool> escVec; | ||
418 | 161 | |||
419 | 162 | /* Mark characters in the string as escaped or not */ | ||
420 | 163 | fill_escape_vector(src, escVec); | ||
421 | 164 | |||
422 | 165 | /* Sanity check... */ | ||
423 | 166 | if (src.length() != escVec.size()) | ||
424 | 167 | return; | ||
425 | 168 | |||
426 | 169 | for (vector<bool>::const_iterator iter = escVec.begin(); | ||
427 | 170 | iter != escVec.end(); | ||
428 | 171 | iter++) | ||
429 | 172 | { | ||
430 | 173 | bool escaped = static_cast<bool>(*iter); | ||
431 | 174 | char c = src[iter - escVec.begin()]; | ||
432 | 175 | |||
433 | 176 | /* Output all characters, except unescaped ",\,' */ | ||
434 | 177 | if ((c != '"' && c != '\\' && c != '\'') || escaped) { | ||
435 | 178 | /* If we reach an unescaped delimiter character, do a split */ | ||
436 | 179 | if (c == delim && !escaped) { | ||
437 | 180 | elementVec.push_back(ss.str()); | ||
438 | 181 | ss.str(""); | ||
439 | 182 | ss.clear(); | ||
440 | 183 | } | ||
441 | 184 | else { | ||
442 | 185 | ss << c; | ||
443 | 186 | } | ||
444 | 187 | } | ||
445 | 188 | |||
446 | 189 | } | ||
447 | 190 | |||
448 | 191 | /* Handle final element, delimited by end of string */ | ||
449 | 192 | const string &finalElement(ss.str()); | ||
450 | 193 | if (!finalElement.empty()) | ||
451 | 194 | elementVec.push_back(finalElement); | ||
452 | 195 | } | ||
453 | 196 | |||
454 | 197 | void | ||
455 | 198 | Util::split(const string& src, char delim, vector<string>& elementVec, | ||
456 | 199 | Util::SplitMode mode) | ||
457 | 200 | { | ||
458 | 201 | // Trivial rejection | ||
459 | 202 | if (src.empty()) | ||
460 | 203 | { | ||
461 | 204 | return; | ||
462 | 205 | } | ||
463 | 206 | |||
464 | 207 | switch (mode) | ||
465 | 208 | { | ||
466 | 209 | case Util::SplitModeNormal: | ||
467 | 210 | return split_normal(src, delim, elementVec); | ||
468 | 211 | case Util::SplitModeFuzzy: | ||
469 | 212 | return split_fuzzy(src, delim, elementVec); | ||
470 | 213 | case Util::SplitModeQuoted: | ||
471 | 214 | return split_quoted(src, delim, elementVec); | ||
472 | 215 | default: | ||
473 | 216 | break; | ||
474 | 217 | } | ||
475 | 218 | } | ||
476 | 219 | |||
477 | 79 | uint64_t | 220 | uint64_t |
478 | 80 | Util::get_timestamp_us() | 221 | Util::get_timestamp_us() |
479 | 81 | { | 222 | { |
480 | 82 | 223 | ||
481 | === modified file 'util.h' | |||
482 | --- util.h 2012-05-02 21:36:04 +0000 | |||
483 | +++ util.h 2012-08-06 15:06:24 +0000 | |||
484 | @@ -25,21 +25,33 @@ | |||
485 | 25 | 25 | ||
486 | 26 | struct Util { | 26 | struct Util { |
487 | 27 | /** | 27 | /** |
488 | 28 | * How to perform the split() operation | ||
489 | 29 | */ | ||
490 | 30 | enum SplitMode { | ||
491 | 31 | /** Normal split operation */ | ||
492 | 32 | SplitModeNormal, | ||
493 | 33 | /** Allow for spaces and multiple consecutive occurences of the delimiter */ | ||
494 | 34 | SplitModeFuzzy, | ||
495 | 35 | /** Take into account bash-like quoting and escaping rules */ | ||
496 | 36 | SplitModeQuoted | ||
497 | 37 | }; | ||
498 | 38 | |||
499 | 39 | /** | ||
500 | 28 | * split() - Splits a string into elements using a provided delimiter | 40 | * split() - Splits a string into elements using a provided delimiter |
501 | 29 | * | 41 | * |
502 | 30 | * @s: the string to split | 42 | * @s: the string to split |
503 | 31 | * @delim: the delimiter to use | 43 | * @delim: the delimiter to use |
504 | 32 | * @elems: the string vector to populate | 44 | * @elems: the string vector to populate |
506 | 33 | * @fuzzy: (optional) enable/disable strict handling of @delim | 45 | * @mode: the SplitMode to use |
507 | 34 | * | 46 | * |
508 | 35 | * Using @delim to determine field boundaries, splits @s into separate | 47 | * Using @delim to determine field boundaries, splits @s into separate |
509 | 36 | * string elements. These elements are returned in the string vector | 48 | * string elements. These elements are returned in the string vector |
514 | 37 | * @elems. If @fuzzy is true, then the handling of @delim allows for | 49 | * @elems. As long as @s is non-empty, there will be at least one |
515 | 38 | * spaces and multiple consecutive occurences of @delim in determining | 50 | * element in @elems. |
512 | 39 | * field boundaries. As long as @s is non-empty, there will be at least | ||
513 | 40 | * one element in @elems. | ||
516 | 41 | */ | 51 | */ |
518 | 42 | static void split(const std::string &s, char delim, std::vector<std::string> &elems, bool fuzzy = false); | 52 | static void split(const std::string& src, char delim, |
519 | 53 | std::vector<std::string>& elems, | ||
520 | 54 | Util::SplitMode mode); | ||
521 | 43 | /** | 55 | /** |
522 | 44 | * get_timestamp_us() - Returns the current time in microseconds | 56 | * get_timestamp_us() - Returns the current time in microseconds |
523 | 45 | */ | 57 | */ |
With tests and everything, fantastic! You left your name off the author credits on the new stuff. Was that intentional (placing the blame on me ;-)?