Chris@629: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@629: Chris@629: /* Chris@629: Sonic Visualiser Chris@629: An audio file viewer and annotation editor. Chris@629: Centre for Digital Music, Queen Mary, University of London. Chris@629: Chris@629: This program is free software; you can redistribute it and/or Chris@629: modify it under the terms of the GNU General Public License as Chris@629: published by the Free Software Foundation; either version 2 of the Chris@629: License, or (at your option) any later version. See the file Chris@629: COPYING included with this distribution for more information. Chris@629: */ Chris@629: Chris@629: /* Chris@629: This is a modified version of a source file from the Chris@629: Rosegarden MIDI and audio sequencer and notation editor. Chris@629: This file copyright 2000-2010 Chris Cannam. Chris@629: */ Chris@629: Chris@629: #include "StringBits.h" Chris@629: Chris@629: double Chris@629: StringBits::stringToDoubleLocaleFree(QString s, bool *ok) Chris@629: { Chris@629: int dp = 0; Chris@629: int sign = 1; Chris@629: int i = 0; Chris@629: double result = 0.0; Chris@629: int len = s.length(); Chris@629: Chris@629: result = 0.0; Chris@629: Chris@629: if (ok) *ok = true; Chris@629: Chris@629: while (i < len && s[i].isSpace()) ++i; Chris@629: if (i < len && s[i] == '-') sign = -1; Chris@629: Chris@629: while (i < len) { Chris@629: Chris@629: QChar c = s[i]; Chris@629: Chris@629: if (c.isDigit()) { Chris@629: Chris@629: double d = c.digitValue(); Chris@629: Chris@629: if (dp > 0) { Chris@629: for (int p = dp; p > 0; --p) d /= 10.0; Chris@629: ++dp; Chris@629: } else { Chris@629: result *= 10.0; Chris@629: } Chris@629: Chris@629: result += d; Chris@629: Chris@629: } else if (c == '.') { Chris@629: Chris@629: dp = 1; Chris@629: Chris@629: } else if (ok) { Chris@629: *ok = false; Chris@629: } Chris@629: Chris@629: ++i; Chris@629: } Chris@629: Chris@629: return result * sign; Chris@629: } Chris@629: Chris@629: QStringList Chris@629: StringBits::splitQuoted(QString s, QChar separator) Chris@629: { Chris@629: QStringList tokens; Chris@629: QString tok; Chris@629: Chris@629: enum { sep, unq, q1, q2 } mode = sep; Chris@629: Chris@629: for (int i = 0; i < s.length(); ++i) { Chris@629: Chris@629: QChar c = s[i]; Chris@629: Chris@629: if (c == '\'') { Chris@629: switch (mode) { Chris@629: case sep: mode = q1; break; Chris@629: case unq: case q2: tok += c; break; Chris@629: case q1: mode = sep; tokens << tok; tok = ""; break; Chris@629: } Chris@629: Chris@629: } else if (c == '"') { Chris@629: switch (mode) { Chris@629: case sep: mode = q2; break; Chris@629: case unq: case q1: tok += c; break; Chris@629: case q2: mode = sep; tokens << tok; tok = ""; break; Chris@629: } Chris@629: Chris@629: } else if (c == separator || (separator == ' ' && c.isSpace())) { Chris@629: switch (mode) { Chris@629: case sep: if (separator != ' ') tokens << ""; break; Chris@629: case unq: mode = sep; tokens << tok; tok = ""; break; Chris@629: case q1: case q2: tok += c; break; Chris@629: } Chris@629: Chris@629: } else if (c == '\\') { Chris@629: if (++i < s.length()) { Chris@629: c = s[i]; Chris@629: switch (mode) { Chris@629: case sep: mode = unq; tok += c; break; Chris@928: case unq: case q1: case q2: tok += c; break; Chris@629: } Chris@629: } Chris@629: Chris@629: } else { Chris@629: switch (mode) { Chris@629: case sep: mode = unq; tok += c; break; Chris@928: case unq: case q1: case q2: tok += c; break; Chris@629: } Chris@629: } Chris@629: } Chris@629: Chris@629: if (tok != "" || mode != sep) tokens << tok; Chris@629: return tokens; Chris@629: } Chris@629: Chris@629: /* Chris@629: Chris@629: void testSplit() Chris@629: { Chris@629: QStringList tests; Chris@629: tests << "a b c d"; Chris@629: tests << "a \"b c\" d"; Chris@629: tests << "a 'b c' d"; Chris@629: tests << "a \"b c\\\" d\""; Chris@629: tests << "a 'b c\\' d'"; Chris@629: tests << "a \"b c' d\""; Chris@629: tests << "a 'b c\" d'"; Chris@629: tests << "aa 'bb cc\" dd'"; Chris@629: tests << "a'a 'bb' \\\"cc\" dd\\\""; Chris@629: tests << " a'a \\\' 'bb' \' \\\"cc\" ' dd\\\" '"; Chris@629: Chris@629: for (int j = 0; j < tests.size(); ++j) { Chris@629: cout << endl; Chris@686: cout << tests[j] << endl; Chris@629: cout << "->" << endl << "("; Chris@629: QStringList l = splitQuoted(tests[j], ' '); Chris@629: for (int i = 0; i < l.size(); ++i) { Chris@629: if (i > 0) cout << ";"; Chris@844: cout << l[i]; Chris@629: } Chris@629: cout << ")" << endl; Chris@629: } Chris@629: } Chris@629: Chris@629: */ Chris@629: Chris@629: /* Chris@629: Results: Chris@629: Chris@629: a b c d Chris@629: -> Chris@629: (a;b;c;d) Chris@629: Chris@629: a "b c" d Chris@629: -> Chris@629: (a;b c;d) Chris@629: Chris@629: a 'b c' d Chris@629: -> Chris@629: (a;b c;d) Chris@629: Chris@629: a "b c\" d" Chris@629: -> Chris@629: (a;b c" d) Chris@629: Chris@629: a 'b c\' d' Chris@629: -> Chris@629: (a;b c' d) Chris@629: Chris@629: a "b c' d" Chris@629: -> Chris@629: (a;b c' d) Chris@629: Chris@629: a 'b c" d' Chris@629: -> Chris@629: (a;b c" d) Chris@629: Chris@629: aa 'bb cc" dd' Chris@629: -> Chris@629: (aa;bb cc" dd) Chris@629: Chris@629: a'a 'bb' \"cc" dd\" Chris@629: -> Chris@629: (a'a;bb;"cc";dd") Chris@629: Chris@629: a'a \' 'bb' ' \"cc" ' dd\" ' Chris@629: -> Chris@629: (a'a;';bb; "cc" ;dd";) Chris@629: Chris@629: */ Chris@629: Chris@629: QStringList Chris@629: StringBits::split(QString line, QChar separator, bool quoted) Chris@629: { Chris@629: if (quoted) { Chris@629: return splitQuoted(line, separator); Chris@629: } else { Chris@629: return line.split(separator, Chris@629: separator == ' ' ? QString::SkipEmptyParts : Chris@629: QString::KeepEmptyParts); Chris@629: } Chris@629: } Chris@629: