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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1476 by senoner, Sun Nov 11 23:07:06 2007 UTC revision 3358 by capela, Wed Oct 18 08:57:21 2017 UTC
# Line 1  Line 1 
1  // qsamplerUtilities.cpp  // qsamplerUtilities.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2004-2017, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, 2008 Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 22  Line 22 
22    
23  #include "qsamplerUtilities.h"  #include "qsamplerUtilities.h"
24    
25    #include "qsamplerOptions.h"
26  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
27    
28  #include <stdio.h>  #include <QRegExp>
29  #include <qregexp.h>  
30    
31  using namespace QSampler;  using namespace QSampler;
32    
33  namespace qsamplerUtilities {  namespace qsamplerUtilities {
34    
35  static int _hexToNumber(char hex_digit) {  static int _hexToNumber ( char hex_digit )
36      switch (hex_digit) {  {
37          case '0': return 0;          switch (hex_digit) {
38          case '1': return 1;                  case '0': return 0;
39          case '2': return 2;                  case '1': return 1;
40          case '3': return 3;                  case '2': return 2;
41          case '4': return 4;                  case '3': return 3;
42          case '5': return 5;                  case '4': return 4;
43          case '6': return 6;                  case '5': return 5;
44          case '7': return 7;                  case '6': return 6;
45          case '8': return 8;                  case '7': return 7;
46          case '9': return 9;                  case '8': return 8;
47                    case '9': return 9;
48          case 'a': return 10;  
49          case 'b': return 11;                  case 'a': return 10;
50          case 'c': return 12;                  case 'b': return 11;
51          case 'd': return 13;                  case 'c': return 12;
52          case 'e': return 14;                  case 'd': return 13;
53          case 'f': return 15;                  case 'e': return 14;
54                    case 'f': return 15;
55          case 'A': return 10;  
56          case 'B': return 11;                  case 'A': return 10;
57          case 'C': return 12;                  case 'B': return 11;
58          case 'D': return 13;                  case 'C': return 12;
59          case 'E': return 14;                  case 'D': return 13;
60          case 'F': return 15;                  case 'E': return 14;
61                    case 'F': return 15;
62    
63          default:  return 0;                  default:  return 0;
64      }          }
65  }  }
66    
67  static int _hexsToNumber(char hex_digit0, char hex_digit1) {  static int _hexsToNumber ( char hex0, char hex1 )
68      return _hexToNumber(hex_digit1)*16 + _hexToNumber(hex_digit0);  {
69            return _hexToNumber(hex1) * 16 + _hexToNumber(hex0);
70  }  }
71    
72    
73  // returns true if the connected LSCP server supports escape sequences  // returns true if the connected LSCP server supports escape sequences
74  static bool _remoteSupportsEscapeSequences() {  static bool _remoteSupportsEscapeSequences (void)
75      const lscpVersion_t version = getRemoteLscpVersion();  {
76      // LSCP v1.2 or younger required          const lscpVersion_t version = getRemoteLscpVersion();
77      return (version.major > 1 || (version.major == 1 && version.minor >= 2));          // 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  // converts the given file path into a path as expected by LSCP 1.2
83  QString lscpEscapePath ( const QString& sPath )  QString lscpEscapePath ( const QString& sPath )
84  {  {
85      if (!_remoteSupportsEscapeSequences()) return sPath;          if (!_remoteSupportsEscapeSequences()) return sPath;
86    
87      QString path(sPath);          QString path(sPath);
88    
89      // replace POSIX path escape sequences (%HH) by LSCP escape sequences (\xHH)          // replace POSIX path escape sequences (%HH) by LSCP escape sequences (\xHH)
90      // TODO: missing code for other systems like Windows          // TODO: missing code for other systems like Windows
91      {          {
92          QRegExp regexp("%[0-9a-fA-F][0-9a-fA-F]");                  QRegExp regexp("%[0-9a-fA-F][0-9a-fA-F]");
93          for (int i = path.find(regexp); i >= 0; i = path.find(regexp, i + 4))                  for (int i = path.indexOf(regexp); i >= 0; i = path.indexOf(regexp, i + 4))
94              path.replace(i, 1, "\\x");                          path.replace(i, 1, "\\x");
95      }          }
96      // replace POSIX path escape sequence (%%) by its raw character          // replace POSIX path escape sequence (%%) by its raw character
97      for (int i = path.find("%%"); i >= 0; i = path.find("%%", ++i))          for (int i = path.indexOf("%%"); i >= 0; i = path.indexOf("%%", ++i))
98          path.remove(i, 1);                  path.remove(i, 1);
99    
100      // replace all non-basic characters by LSCP escape sequences          // replace all non-basic characters by LSCP escape sequences
101      {          {
102          const char pathSeparator = '/';                  const char pathSeparator = '/';
103          QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");                  QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");
104          for (int i = 0; i < int(path.length()); i++) {                  for (int i = 0; i < int(path.length()); i++) {
105              // first skip all previously added LSCP escape sequences                          // first skip all previously added LSCP escape sequences
106              if (path.find(regexp, i) == i) {                          if (path.indexOf(regexp, i) == i) {
107                  i += 3;                                  i += 3;
108                  continue;                                  continue;
109              }                          }
110              // now match all non-alphanumerics                          // now match all non-alphanumerics
111              // (we could exclude much more characters here, but that way                          // (we could exclude much more characters here, but that way
112              // we're sure it just works^TM)                          // we're sure it just works^TM)
113              const char c = path.at(i).latin1();                          const char c = path.at(i).toLatin1();
114              if (                          if (
115                  !(c >= '0' && c <= '9') &&                                  !(c >= '0' && c <= '9') &&
116                  !(c >= 'a' && c <= 'z') &&                                  !(c >= 'a' && c <= 'z') &&
117                  !(c >= 'A' && c <= 'Z') &&                                  !(c >= 'A' && c <= 'Z') &&
118                  #if defined(WIN32)                          #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
119                  !(c == ':') &&                                  !(c == ':') &&
120                  #endif                          #endif
121                  !(c == pathSeparator)                                  !(c == pathSeparator)
122              ) {                          ) {
123                  // convert the non-basic character into a LSCP escape sequence                                  // convert the non-basic character into a LSCP escape sequence
124                  char buf[5];                                  char buf[5];
125                  ::snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));                                  ::snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
126                  path.replace(i, 1, buf);                                  path.replace(i, 1, buf);
127                  i += 3;                                  i += 3;
128              }                          }
129          }                  }
130      }          }
131    
132      return path;          return path;
133  }  }
134    
135    
136  // converts a path returned by a LSCP command (and may contain escape  // converts a path returned by a LSCP command (and may contain escape
137  // sequences) into the appropriate POSIX path  // sequences) into the appropriate POSIX path
138  QString lscpEscapedPathToPosix(QString path) {  QString lscpEscapedPathToPosix ( const QString& sPath )
139      if (!_remoteSupportsEscapeSequences()) return path;  {
140            if (!_remoteSupportsEscapeSequences()) return sPath;
141    
142            QString path(sPath);
143    
144      // first escape all percent ('%') characters for POSIX          // first escape all percent ('%') characters for POSIX
145      for (int i = path.find('%'); i >= 0; i = path.find('%', i+2))          for (int i = path.indexOf('%'); i >= 0; i = path.indexOf('%', i+2))
146          path.replace(i, 1, "%%");                  path.replace(i, 1, "%%");
147    
148      // resolve LSCP hex escape sequences (\xHH)          // resolve LSCP hex escape sequences (\xHH)
149      QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");          QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");
150      for (int i = path.find(regexp); i >= 0; i = path.find(regexp, i + 4)) {          for (int i = path.indexOf(regexp); i >= 0; i = path.indexOf(regexp, i + 4)) {
151          const QString sHex = path.mid(i+2, 2).lower();                  const QString sHex = path.mid(i + 2, 2).toLower();
152          // the slash has to be escaped for POSIX as well                  // the slash has to be escaped for POSIX as well
153          if (sHex == "2f") {                  if (sHex == "2f") {
154              path.replace(i, 4, "%2f");                          path.replace(i, 4, "%2f");
155              continue;                          continue;
156          }                  }
157          // all other characters we simply decode                  // all other characters we simply decode
158          char cAscii = _hexsToNumber(sHex.at(1).latin1(), sHex.at(0).latin1());                  char cAscii = _hexsToNumber(sHex.at(1).toLatin1(), sHex.at(0).toLatin1());
159          path.replace(i, 4, cAscii);                  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      return path;          // 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  // converts a text returned by a LSCP command and may contain escape
198  // sequences) into raw text, that is with all escape sequences decoded  // sequences) into raw text, that is with all escape sequences decoded
199  QString lscpEscapedTextToRaw(QString txt) {  QString lscpEscapedTextToRaw ( const QString& sText )
200      if (!_remoteSupportsEscapeSequences()) return txt;  {
201            if (!_remoteSupportsEscapeSequences()) return sText;
202    
203            QString text(sText);
204    
205      // resolve LSCP hex escape sequences (\xHH)          // resolve LSCP hex escape sequences (\xHH)
206      QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");          QRegExp regexp(QRegExp::escape("\\x") + "[0-9a-fA-F][0-9a-fA-F]");
207      for (int i = txt.find(regexp); i >= 0; i = txt.find(regexp, i + 4)) {          for (int i = text.indexOf(regexp); i >= 0; i = text.indexOf(regexp, i + 4)) {
208          const QString sHex = txt.mid(i+2, 2).lower();                  const QString sHex = text.mid(i + 2, 2).toLower();
209          // decode into raw ASCII character                  // decode into raw ASCII character
210          char cAscii = _hexsToNumber(sHex.at(1).latin1(), sHex.at(0).latin1());                  char cAscii = _hexsToNumber(sHex.at(1).toLatin1(), sHex.at(0).toLatin1());
211          txt.replace(i, 4, cAscii);                  text.replace(i, 4, cAscii);
212      }          }
213    
214      return txt;          return text;
215  }  }
216    
217  lscpVersion_t getRemoteLscpVersion (void)  lscpVersion_t getRemoteLscpVersion (void)

Legend:
Removed from v.1476  
changed lines
  Added in v.3358

  ViewVC Help
Powered by ViewVC