Mercurial > hg > svcore
comparison base/StringBits.cpp @ 629:35499d48a5d1
* Start overhauling CSV parser to associate purposes with columns en route to its guesses; add some string manipulation code
author | Chris Cannam |
---|---|
date | Thu, 15 Jul 2010 15:27:21 +0000 |
parents | |
children | b4a8d8221eaf |
comparison
equal
deleted
inserted
replaced
628:001db550bd48 | 629:35499d48a5d1 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 | |
8 This program is free software; you can redistribute it and/or | |
9 modify it under the terms of the GNU General Public License as | |
10 published by the Free Software Foundation; either version 2 of the | |
11 License, or (at your option) any later version. See the file | |
12 COPYING included with this distribution for more information. | |
13 */ | |
14 | |
15 /* | |
16 This is a modified version of a source file from the | |
17 Rosegarden MIDI and audio sequencer and notation editor. | |
18 This file copyright 2000-2010 Chris Cannam. | |
19 */ | |
20 | |
21 #include "StringBits.h" | |
22 | |
23 double | |
24 StringBits::stringToDoubleLocaleFree(QString s, bool *ok) | |
25 { | |
26 int dp = 0; | |
27 int sign = 1; | |
28 int i = 0; | |
29 double result = 0.0; | |
30 int len = s.length(); | |
31 | |
32 result = 0.0; | |
33 | |
34 if (ok) *ok = true; | |
35 | |
36 while (i < len && s[i].isSpace()) ++i; | |
37 if (i < len && s[i] == '-') sign = -1; | |
38 | |
39 while (i < len) { | |
40 | |
41 QChar c = s[i]; | |
42 | |
43 if (c.isDigit()) { | |
44 | |
45 double d = c.digitValue(); | |
46 | |
47 if (dp > 0) { | |
48 for (int p = dp; p > 0; --p) d /= 10.0; | |
49 ++dp; | |
50 } else { | |
51 result *= 10.0; | |
52 } | |
53 | |
54 result += d; | |
55 | |
56 } else if (c == '.') { | |
57 | |
58 dp = 1; | |
59 | |
60 } else if (ok) { | |
61 *ok = false; | |
62 } | |
63 | |
64 ++i; | |
65 } | |
66 | |
67 return result * sign; | |
68 } | |
69 | |
70 QStringList | |
71 StringBits::splitQuoted(QString s, QChar separator) | |
72 { | |
73 QStringList tokens; | |
74 QString tok; | |
75 | |
76 enum { sep, unq, q1, q2 } mode = sep; | |
77 | |
78 for (int i = 0; i < s.length(); ++i) { | |
79 | |
80 QChar c = s[i]; | |
81 | |
82 if (c == '\'') { | |
83 switch (mode) { | |
84 case sep: mode = q1; break; | |
85 case unq: case q2: tok += c; break; | |
86 case q1: mode = sep; tokens << tok; tok = ""; break; | |
87 } | |
88 | |
89 } else if (c == '"') { | |
90 switch (mode) { | |
91 case sep: mode = q2; break; | |
92 case unq: case q1: tok += c; break; | |
93 case q2: mode = sep; tokens << tok; tok = ""; break; | |
94 } | |
95 | |
96 } else if (c == separator || (separator == ' ' && c.isSpace())) { | |
97 switch (mode) { | |
98 case sep: if (separator != ' ') tokens << ""; break; | |
99 case unq: mode = sep; tokens << tok; tok = ""; break; | |
100 case q1: case q2: tok += c; break; | |
101 } | |
102 | |
103 } else if (c == '\\') { | |
104 if (++i < s.length()) { | |
105 c = s[i]; | |
106 switch (mode) { | |
107 case sep: mode = unq; tok += c; break; | |
108 default: tok += c; break; | |
109 } | |
110 } | |
111 | |
112 } else { | |
113 switch (mode) { | |
114 case sep: mode = unq; tok += c; break; | |
115 default: tok += c; break; | |
116 } | |
117 } | |
118 } | |
119 | |
120 if (tok != "" || mode != sep) tokens << tok; | |
121 return tokens; | |
122 } | |
123 | |
124 /* | |
125 | |
126 void testSplit() | |
127 { | |
128 QStringList tests; | |
129 tests << "a b c d"; | |
130 tests << "a \"b c\" d"; | |
131 tests << "a 'b c' d"; | |
132 tests << "a \"b c\\\" d\""; | |
133 tests << "a 'b c\\' d'"; | |
134 tests << "a \"b c' d\""; | |
135 tests << "a 'b c\" d'"; | |
136 tests << "aa 'bb cc\" dd'"; | |
137 tests << "a'a 'bb' \\\"cc\" dd\\\""; | |
138 tests << " a'a \\\' 'bb' \' \\\"cc\" ' dd\\\" '"; | |
139 | |
140 for (int j = 0; j < tests.size(); ++j) { | |
141 cout << endl; | |
142 cout << tests[j].toStdString() << endl; | |
143 cout << "->" << endl << "("; | |
144 QStringList l = splitQuoted(tests[j], ' '); | |
145 for (int i = 0; i < l.size(); ++i) { | |
146 if (i > 0) cout << ";"; | |
147 cout << l[i].toStdString(); | |
148 } | |
149 cout << ")" << endl; | |
150 } | |
151 } | |
152 | |
153 */ | |
154 | |
155 /* | |
156 Results: | |
157 | |
158 a b c d | |
159 -> | |
160 (a;b;c;d) | |
161 | |
162 a "b c" d | |
163 -> | |
164 (a;b c;d) | |
165 | |
166 a 'b c' d | |
167 -> | |
168 (a;b c;d) | |
169 | |
170 a "b c\" d" | |
171 -> | |
172 (a;b c" d) | |
173 | |
174 a 'b c\' d' | |
175 -> | |
176 (a;b c' d) | |
177 | |
178 a "b c' d" | |
179 -> | |
180 (a;b c' d) | |
181 | |
182 a 'b c" d' | |
183 -> | |
184 (a;b c" d) | |
185 | |
186 aa 'bb cc" dd' | |
187 -> | |
188 (aa;bb cc" dd) | |
189 | |
190 a'a 'bb' \"cc" dd\" | |
191 -> | |
192 (a'a;bb;"cc";dd") | |
193 | |
194 a'a \' 'bb' ' \"cc" ' dd\" ' | |
195 -> | |
196 (a'a;';bb; "cc" ;dd";) | |
197 | |
198 */ | |
199 | |
200 QStringList | |
201 StringBits::split(QString line, QChar separator, bool quoted) | |
202 { | |
203 if (quoted) { | |
204 return splitQuoted(line, separator); | |
205 } else { | |
206 return line.split(separator, | |
207 separator == ' ' ? QString::SkipEmptyParts : | |
208 QString::KeepEmptyParts); | |
209 } | |
210 } | |
211 |