annotate base/StringBits.cpp @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
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