annotate base/StringBits.cpp @ 1346:75ad55315db4 3.0-integration

More work on getting tests (especially file encoding ones) running on Windows. Various problems here to do with interaction with test filenames in Hg repos
author Chris Cannam
date Fri, 06 Jan 2017 15:44:55 +0000
parents eecf544bed92
children 48e9f538e6e9
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@1022 23 #include "Debug.h"
Chris@1022 24
Chris@1022 25 using namespace std;
Chris@1022 26
Chris@629 27 double
Chris@629 28 StringBits::stringToDoubleLocaleFree(QString s, bool *ok)
Chris@629 29 {
Chris@629 30 int dp = 0;
Chris@629 31 int sign = 1;
Chris@629 32 int i = 0;
Chris@629 33 double result = 0.0;
Chris@629 34 int len = s.length();
Chris@629 35
Chris@629 36 result = 0.0;
Chris@629 37
Chris@629 38 if (ok) *ok = true;
Chris@629 39
Chris@629 40 while (i < len && s[i].isSpace()) ++i;
Chris@629 41 if (i < len && s[i] == '-') sign = -1;
Chris@629 42
Chris@629 43 while (i < len) {
Chris@629 44
Chris@629 45 QChar c = s[i];
Chris@629 46
Chris@629 47 if (c.isDigit()) {
Chris@629 48
Chris@629 49 double d = c.digitValue();
Chris@629 50
Chris@629 51 if (dp > 0) {
Chris@629 52 for (int p = dp; p > 0; --p) d /= 10.0;
Chris@629 53 ++dp;
Chris@629 54 } else {
Chris@629 55 result *= 10.0;
Chris@629 56 }
Chris@629 57
Chris@629 58 result += d;
Chris@629 59
Chris@629 60 } else if (c == '.') {
Chris@629 61
Chris@629 62 dp = 1;
Chris@629 63
Chris@629 64 } else if (ok) {
Chris@629 65 *ok = false;
Chris@629 66 }
Chris@629 67
Chris@629 68 ++i;
Chris@629 69 }
Chris@629 70
Chris@629 71 return result * sign;
Chris@629 72 }
Chris@629 73
Chris@629 74 QStringList
Chris@629 75 StringBits::splitQuoted(QString s, QChar separator)
Chris@629 76 {
Chris@629 77 QStringList tokens;
Chris@629 78 QString tok;
Chris@629 79
Chris@1022 80 // sep -> just seen a field separator (or start of line)
Chris@1022 81 // unq -> in an unquoted field
Chris@1022 82 // q1 -> in a single-quoted field
Chris@1022 83 // q2 -> in a double-quoted field
Chris@1022 84
Chris@629 85 enum { sep, unq, q1, q2 } mode = sep;
Chris@629 86
Chris@629 87 for (int i = 0; i < s.length(); ++i) {
Chris@629 88
Chris@629 89 QChar c = s[i];
Chris@629 90
Chris@629 91 if (c == '\'') {
Chris@629 92 switch (mode) {
Chris@629 93 case sep: mode = q1; break;
Chris@629 94 case unq: case q2: tok += c; break;
Chris@1019 95 case q1: mode = unq; break;
Chris@629 96 }
Chris@629 97
Chris@629 98 } else if (c == '"') {
Chris@629 99 switch (mode) {
Chris@629 100 case sep: mode = q2; break;
Chris@629 101 case unq: case q1: tok += c; break;
Chris@1019 102 case q2: mode = unq; break;
Chris@629 103 }
Chris@629 104
Chris@629 105 } else if (c == separator || (separator == ' ' && c.isSpace())) {
Chris@629 106 switch (mode) {
Chris@629 107 case sep: if (separator != ' ') tokens << ""; break;
Chris@629 108 case unq: mode = sep; tokens << tok; tok = ""; break;
Chris@629 109 case q1: case q2: tok += c; break;
Chris@629 110 }
Chris@629 111
Chris@629 112 } else if (c == '\\') {
Chris@629 113 if (++i < s.length()) {
Chris@629 114 c = s[i];
Chris@629 115 switch (mode) {
Chris@629 116 case sep: mode = unq; tok += c; break;
Chris@928 117 case unq: case q1: case q2: tok += c; break;
Chris@629 118 }
Chris@629 119 }
Chris@629 120
Chris@629 121 } else {
Chris@629 122 switch (mode) {
Chris@629 123 case sep: mode = unq; tok += c; break;
Chris@928 124 case unq: case q1: case q2: tok += c; break;
Chris@629 125 }
Chris@629 126 }
Chris@629 127 }
Chris@629 128
Chris@1022 129 if (tok != "" || mode != sep) {
Chris@1022 130 if (mode == q1) {
Chris@1022 131 tokens << ("'" + tok); // turns out it wasn't quoted after all
Chris@1022 132 } else if (mode == q2) {
Chris@1022 133 tokens << ("\"" + tok);
Chris@1022 134 } else {
Chris@1022 135 tokens << tok;
Chris@1022 136 }
Chris@1022 137 }
Chris@1022 138
Chris@629 139 return tokens;
Chris@629 140 }
Chris@629 141
Chris@629 142 QStringList
Chris@629 143 StringBits::split(QString line, QChar separator, bool quoted)
Chris@629 144 {
Chris@629 145 if (quoted) {
Chris@629 146 return splitQuoted(line, separator);
Chris@629 147 } else {
Chris@629 148 return line.split(separator,
Chris@629 149 separator == ' ' ? QString::SkipEmptyParts :
Chris@629 150 QString::KeepEmptyParts);
Chris@629 151 }
Chris@629 152 }
Chris@629 153