annotate base/StringBits.cpp @ 986:e8e6c4e7437b

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