/[svn]/linuxsampler/trunk/src/common/Path.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/Path.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3082 - (show annotations) (download)
Mon Jan 9 18:39:35 2017 UTC (7 years, 3 months ago) by schoenebeck
File size: 11303 byte(s)
* Added support for sfz extension opcode 'script' which may be used to
  load real-time instrument script file (NKSP script language).
* Removed code duplication in SFZ file loading code.
* Bumped version (2.0.0.svn37).

1 /***************************************************************************
2 * *
3 * Copyright (C) 2007-2017 Christian Schoenebeck *
4 * *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This library is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this library; if not, write to the Free Software *
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
18 * MA 02111-1307 USA *
19 ***************************************************************************/
20
21 #include "Path.h"
22
23 // for function hexsToNumber()
24 #include "global_private.h"
25
26 #include <sstream>
27
28 namespace LinuxSampler {
29
30 Path::Path() : drive(0), absolute(false) {
31 }
32
33 Path::Path(std::string path) {
34 #if WIN32
35 *this = fromWindows(path);
36 #else
37 *this = fromPosix(path);
38 #endif
39 }
40
41 void Path::appendNode(std::string Name) {
42 if (!Name.size()) return;
43 elements.push_back(Name);
44 }
45
46 void Path::setDrive(const char& Drive) {
47 drive = Drive;
48 absolute = true;
49 }
50
51 std::string Path::toNativeFSPath() const {
52 #if WIN32
53 return toWindows();
54 #else
55 return toPosix();
56 #endif
57 }
58
59 std::string Path::toPosix() const {
60 // POSIX paths consist of forward slash separators and requires forward
61 // slashes in path and file names to be encoded as "%2f", the file names
62 // "." and ".." have special meanings
63 // (see http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap03.html#tag_03_169
64 // and http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap03.html#tag_03_266 )
65 std::string result;
66 for (int iElement = 0; iElement < elements.size(); iElement++) {
67 // encode percent characters
68 std::string e = elements[iElement];
69 for (
70 int pos = (int)e.find("%"); pos != std::string::npos;
71 pos = (int)e.find("%", pos+2)
72 ) e.replace(pos/*offset*/, 1/*length*/, "%%"/*by*/);
73 // encode forward slashes
74 for (
75 int pos = (int)e.find("/"); pos != std::string::npos;
76 pos = (int)e.find("/", pos+3)
77 ) e.replace(pos/*offset*/, 1/*length*/, "%2f"/*by*/);
78 // append encoded node to full encoded path
79 result += "/" + e;
80 }
81 if (!result.size()) result = "/";
82 return result;
83 }
84
85 std::string Path::toDbPath() const {
86 std::string result;
87 for (int iElement = 0; iElement < elements.size(); iElement++) {
88 // replace all slashes with '\0'
89 std::string e = elements[iElement];
90 for (int i = 0; i < e.length(); i++) {
91 if (e.at(i) == '/') e.at(i) = '\0';
92 }
93 // append encoded node to full encoded path
94 result += "/" + e;
95 }
96 if (!result.size()) result = "/";
97 return result;
98 }
99
100 std::string Path::toLscp() const {
101 std::string result;
102 #if WIN32
103 if(drive) {
104 result.assign(&drive,1);
105 result += ":";
106 }
107 #endif
108 for (int iElement = 0; iElement < elements.size(); iElement++) {
109 // replace "special characters" by LSCP escape sequences
110 std::string e = elements[iElement];
111 for (int i = 0; i < e.length(); i++) {
112 const char c = e.c_str()[i];
113 if (
114 !(c >= '0' && c <= '9') &&
115 !(c >= 'a' && c <= 'z') &&
116 !(c >= 'A' && c <= 'Z') &&
117 !(c == '!') && !(c == '#') && !(c == '$') && !(c == '%') &&
118 !(c == '&') && !(c == '(') && !(c == ')') && !(c == '*') &&
119 !(c == '+') && !(c == ',') && !(c == '-') && !(c == '.') &&
120 !(c == ':') && !(c == ';') && !(c == '<') && !(c == '=') &&
121 !(c == '>') && !(c == '?') && !(c == '@') && !(c == '[') &&
122 !(c == ']') && !(c == '^') && !(c == '_') && !(c == '`') &&
123 !(c == '{') && !(c == '|') && !(c == '}') && !(c == '~')
124 ) {
125 // convert the "special" character into a "\xHH" LSCP escape sequence
126 char buf[5];
127 snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
128 e.replace(i, 1, buf);
129 i += 3;
130 }
131 }
132 // append encoded node to full encoded path
133 result += "/" + e;
134 }
135 if (!result.size()) result = "/";
136 return result;
137 }
138
139 std::string Path::toWindows() const {
140 std::stringstream result;
141 const char cDrive =
142 ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z'))
143 ? drive : '?';
144 result << cDrive;
145 result << ':';
146 for (int iElement = 0; iElement < elements.size(); iElement++) {
147 // append encoded node to full encoded path
148 result << "\\" << elements[iElement];
149 }
150 if (elements.empty()) result << '\\';
151 return result.str();
152 }
153
154 Path Path::operator+(const Path& p) {
155 Path result = *this;
156 for (int i = 0; i < p.elements.size(); i++)
157 result.elements.push_back(p.elements[i]);
158 return result;
159 }
160
161 Path Path::operator+(const Path* p) {
162 return *this + *p;
163 }
164
165 Path Path::fromUnknownFS(std::string path) {
166 bool hasDrive = false;
167 int nSlash = 0, nBackSlash = 0;
168
169 if (path.length() >= 2)
170 hasDrive = (path[1] == ':');
171
172 for (size_t i = 0; i < path.size(); ++i) {
173 if (path[i] == '/') nSlash++;
174 if (path[i] == '\\') nBackSlash++;
175 }
176
177 if (!hasDrive && nSlash > nBackSlash)
178 return Path::fromPosix(path);
179 else if (hasDrive || nBackSlash > nSlash)
180 return Path::fromWindows(path);
181 else
182 return Path(path); // expect local file system encoding
183 }
184
185 Path Path::fromPosix(std::string path) {
186 Path result;
187 // first split the nodes
188 {
189 int nodeEnd;
190 for (
191 int nodeBegin = (int)path.find_first_not_of('/');
192 nodeBegin != std::string::npos;
193 nodeBegin = (int)path.find_first_not_of('/', nodeEnd)
194 ) {
195 nodeEnd = (int)path.find_first_of('/', nodeBegin);
196 result.appendNode(
197 (nodeEnd != std::string::npos) ?
198 path.substr(nodeBegin, nodeEnd - nodeBegin) :
199 path.substr(nodeBegin)
200 );
201 }
202 }
203 // resolve POSIX escape sequences in all nodes
204 for (int iNode = 0; iNode < result.elements.size(); iNode++) {
205 std::string& s = result.elements[iNode];
206 for (size_t pos = s.find('%'); pos < s.length(); pos = s.find('%', ++pos)) {
207 if (pos+1 >= s.length()) { // unexpected character
208 //TODO: we might want to throw an exception here, for now we simply replace the character by '?'
209 s.replace(pos, 1, "?");
210 continue;
211 }
212 if (s.c_str()[pos+1] == '%') {
213 s.replace(pos, 2, "%");
214 continue;
215 }
216 if (pos+2 >= s.length()) {
217 //TODO: we might want to throw an exception here, for now we simply replace the character by '?'
218 s.replace(pos, 2, "?");
219 continue;
220 }
221 // expecting a "%HH" sequence here, convert it into the respective character
222 const std::string sHex = s.substr(pos+1, 2);
223 char cAscii = hexsToNumber(sHex.c_str()[1], sHex.c_str()[0]);
224 char pcAscii[] = { cAscii, 0 };
225 s.replace(pos, 3, pcAscii);
226 }
227 }
228 // check whether given string reflects an absolute path
229 // (indicated by a forward slash as first character on POSIX)
230 result.absolute = !path.empty() && path[0] == '/';
231 return result;
232 }
233
234 Path Path::fromDbPath(std::string path) {
235 Path result;
236 // first split the nodes
237 {
238 int nodeEnd;
239 for (
240 int nodeBegin = (int)path.find_first_not_of('/');
241 nodeBegin != std::string::npos;
242 nodeBegin = (int)path.find_first_not_of('/', nodeEnd)
243 ) {
244 nodeEnd = (int)path.find_first_of('/', nodeBegin);
245
246 std::string s = (nodeEnd != std::string::npos) ?
247 path.substr(nodeBegin, nodeEnd - nodeBegin) :
248 path.substr(nodeBegin);
249
250 for (int i = 0; i < s.length(); i++) if (s.at(i) == '\0') s.at(i) = '/';
251 result.appendNode(s);
252 }
253 }
254 return result;
255 }
256
257 Path Path::fromWindows(std::string path) {
258 Path result;
259
260 int nodeEnd = 0;
261
262 // first retrieve drive
263 if (path.size() >= 2 && path.c_str()[1] == ':') {
264 result.setDrive(path.c_str()[0]);
265 nodeEnd = 2;
266 }
267
268 // split the nodes
269 {
270 for (
271 int nodeBegin = (int)path.find_first_not_of('\\', nodeEnd);
272 nodeBegin != std::string::npos;
273 nodeBegin = (int)path.find_first_not_of('\\', nodeEnd)
274 ) {
275 nodeEnd = (int)path.find_first_of('\\', nodeBegin);
276 result.appendNode(
277 (nodeEnd != std::string::npos) ?
278 path.substr(nodeBegin, nodeEnd - nodeBegin) :
279 path.substr(nodeBegin)
280 );
281 }
282 }
283
284 // check whether given string reflects an absolute path
285 // (indicated either by a backslash or drive at the beginning on Windows)
286 result.absolute = result.drive || (!path.empty() && path[0] == '\\');
287
288 return result;
289 }
290
291 std::string Path::getName(std::string path) {
292 Path p;
293 #if WIN32
294 p.fromWindows(path);
295 #else
296 p.fromPosix(path);
297 #endif
298
299 return p.getName();
300 }
301
302 std::string Path::getName() const {
303 if(elements.empty()) return "";
304 return elements[elements.size() - 1];
305 }
306
307 std::string Path::getBaseName(std::string path) {
308 Path p;
309 #if WIN32
310 p = fromWindows(path);
311 #else
312 p = fromPosix(path);
313 #endif
314
315 return p.getBaseName();
316 }
317
318 std::string Path::getBaseName() const {
319 std::string name = getName();
320 size_t lastdot = name.find_last_of('.');
321 if(lastdot == std::string::npos) return name;
322 return name.substr(0, lastdot);
323 }
324
325 std::string Path::stripLastName() {
326 if (elements.size() > 0) elements.pop_back();
327 #if WIN32
328 return toWindows();
329 #else
330 return toPosix();
331 #endif
332 }
333
334 std::string Path::stripLastName(std::string path) {
335 Path p;
336 #if WIN32
337 p = fromWindows(path);
338 #else
339 p = fromPosix(path);
340 #endif
341
342 return p.stripLastName();
343 }
344
345 bool Path::isAbsolute() const {
346 return absolute;
347 }
348
349 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC