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