/[svn]/qsampler/trunk/src/qsamplerUtilities.cpp
ViewVC logotype

Contents of /qsampler/trunk/src/qsamplerUtilities.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3555 - (show annotations) (download)
Tue Aug 13 10:19:32 2019 UTC (4 years, 7 months ago) by capela
File size: 6885 byte(s)
- In late compliance to C++11, all NULL constants replaced for nullptr.
1 // qsamplerUtilities.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved.
5 Copyright (C) 2007, 2008 Christian Schoenebeck
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 *****************************************************************************/
22
23 #include "qsamplerUtilities.h"
24
25 #include "qsamplerOptions.h"
26 #include "qsamplerMainForm.h"
27
28 #include <QRegExp>
29
30
31 using namespace QSampler;
32
33 namespace qsamplerUtilities {
34
35 static int _hexToNumber ( char hex_digit )
36 {
37 switch (hex_digit) {
38 case '0': return 0;
39 case '1': return 1;
40 case '2': return 2;
41 case '3': return 3;
42 case '4': return 4;
43 case '5': return 5;
44 case '6': return 6;
45 case '7': return 7;
46 case '8': return 8;
47 case '9': return 9;
48
49 case 'a': return 10;
50 case 'b': return 11;
51 case 'c': return 12;
52 case 'd': return 13;
53 case 'e': return 14;
54 case 'f': return 15;
55
56 case 'A': return 10;
57 case 'B': return 11;
58 case 'C': return 12;
59 case 'D': return 13;
60 case 'E': return 14;
61 case 'F': return 15;
62
63 default: return 0;
64 }
65 }
66
67 static int _hexsToNumber ( char hex0, char hex1 )
68 {
69 return _hexToNumber(hex1) * 16 + _hexToNumber(hex0);
70 }
71
72
73 // returns true if the connected LSCP server supports escape sequences
74 static bool _remoteSupportsEscapeSequences (void)
75 {
76 const lscpVersion_t version = getRemoteLscpVersion();
77 // LSCP v1.2 or younger required
78 return (version.major > 1 || (version.major == 1 && version.minor >= 2));
79 }
80
81
82 // converts the given file path into a path as expected by LSCP 1.2
83 QString lscpEscapePath ( const QString& sPath )
84 {
85 if (!_remoteSupportsEscapeSequences()) return sPath;
86
87 QString path(sPath);
88
89 // replace POSIX path escape sequences (%HH) by LSCP escape sequences (\xHH)
90 // TODO: missing code for other systems like Windows
91 {
92 QRegExp regexp("%[0-9a-fA-F][0-9a-fA-F]");
93 for (int i = path.indexOf(regexp); i >= 0; i = path.indexOf(regexp, i + 4))
94 path.replace(i, 1, "\\x");
95 }
96 // replace POSIX path escape sequence (%%) by its raw character
97 for (int i = path.indexOf("%%"); i >= 0; i = path.indexOf("%%", ++i))
98 path.remove(i, 1);
99
100 // replace all non-basic characters by LSCP escape sequences
101 {
102 const char pathSeparator = '/';
103 QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");
104 for (int i = 0; i < int(path.length()); i++) {
105 // first skip all previously added LSCP escape sequences
106 if (path.indexOf(regexp, i) == i) {
107 i += 3;
108 continue;
109 }
110 // now match all non-alphanumerics
111 // (we could exclude much more characters here, but that way
112 // we're sure it just works^TM)
113 const char c = path.at(i).toLatin1();
114 if (
115 !(c >= '0' && c <= '9') &&
116 !(c >= 'a' && c <= 'z') &&
117 !(c >= 'A' && c <= 'Z') &&
118 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
119 !(c == ':') &&
120 #endif
121 !(c == pathSeparator)
122 ) {
123 // convert the non-basic character into a LSCP escape sequence
124 char buf[5];
125 ::snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
126 path.replace(i, 1, buf);
127 i += 3;
128 }
129 }
130 }
131
132 return path;
133 }
134
135
136 // converts a path returned by a LSCP command (and may contain escape
137 // sequences) into the appropriate POSIX path
138 QString lscpEscapedPathToPosix ( const QString& sPath )
139 {
140 if (!_remoteSupportsEscapeSequences()) return sPath;
141
142 QString path(sPath);
143
144 // first escape all percent ('%') characters for POSIX
145 for (int i = path.indexOf('%'); i >= 0; i = path.indexOf('%', i+2))
146 path.replace(i, 1, "%%");
147
148 // resolve LSCP hex escape sequences (\xHH)
149 QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");
150 for (int i = path.indexOf(regexp); i >= 0; i = path.indexOf(regexp, i + 4)) {
151 const QString sHex = path.mid(i + 2, 2).toLower();
152 // the slash has to be escaped for POSIX as well
153 if (sHex == "2f") {
154 path.replace(i, 4, "%2f");
155 continue;
156 }
157 // all other characters we simply decode
158 char cAscii = _hexsToNumber(sHex.at(1).toLatin1(), sHex.at(0).toLatin1());
159 path.replace(i, 4, cAscii);
160 }
161
162 return path;
163 }
164
165
166 // converts the given text as expected by LSCP 1.2
167 // (that is by encoding special characters with LSCP escape sequences)
168 QString lscpEscapeText ( const QString& sText )
169 {
170 if (!_remoteSupportsEscapeSequences()) return sText;
171
172 QString text(sText);
173
174 // replace all non-basic characters by LSCP escape sequences
175 for (int i = 0; i < int(text.length()); ++i) {
176 // match all non-alphanumerics
177 // (we could exclude much more characters here, but that way
178 // we're sure it just works^TM)
179 const char c = text.at(i).toLatin1();
180 if (
181 !(c >= '0' && c <= '9') &&
182 !(c >= 'a' && c <= 'z') &&
183 !(c >= 'A' && c <= 'Z')
184 ) {
185 // convert the non-basic character into a LSCP escape sequence
186 char buf[5];
187 ::snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
188 text.replace(i, 1, buf);
189 i += 3;
190 }
191 }
192
193 return text;
194 }
195
196
197 // converts a text returned by a LSCP command and may contain escape
198 // sequences) into raw text, that is with all escape sequences decoded
199 QString lscpEscapedTextToRaw ( const QString& sText )
200 {
201 if (!_remoteSupportsEscapeSequences()) return sText;
202
203 QString text(sText);
204
205 // resolve LSCP hex escape sequences (\xHH)
206 QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");
207 for (int i = text.indexOf(regexp); i >= 0; i = text.indexOf(regexp, i + 4)) {
208 const QString sHex = text.mid(i + 2, 2).toLower();
209 // decode into raw ASCII character
210 char cAscii = _hexsToNumber(sHex.at(1).toLatin1(), sHex.at(0).toLatin1());
211 text.replace(i, 4, cAscii);
212 }
213
214 return text;
215 }
216
217 lscpVersion_t getRemoteLscpVersion (void)
218 {
219 lscpVersion_t result = { 0, 0 };
220
221 MainForm* pMainForm = MainForm::getInstance();
222 if (pMainForm == nullptr)
223 return result;
224 if (pMainForm->client() == nullptr)
225 return result;
226
227 lscp_server_info_t* pServerInfo =
228 ::lscp_get_server_info(pMainForm->client());
229 if (pServerInfo && pServerInfo->protocol_version)
230 ::sscanf(pServerInfo->protocol_version, "%d.%d",
231 &result.major, &result.minor);
232
233 return result;
234 }
235
236 } // namespace qsamplerUtilities
237
238
239 // end of qsamplerUtilities.cpp

  ViewVC Help
Powered by ViewVC