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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1402 - (show annotations) (download)
Fri Oct 12 00:03:27 2007 UTC (12 years, 11 months ago) by schoenebeck
File size: 6307 byte(s)
* added support for escape sequences in LSCP response fields
* bugfix in escaping file names for LSCP: characters with an one digit hex
  code caused a space (i.e. "\x a" instead of "\x0a")

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

  ViewVC Help
Powered by ViewVC