/[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 2529 - (show annotations) (download)
Tue Mar 4 20:41:47 2014 UTC (5 years, 11 months ago) by schoenebeck
File size: 10534 byte(s)
* SFZ format: Added support for "#include" instruction (modified patch
  which was originally posted by Sergey on LS mailing list).
* Bumped version (1.0.0.svn34).

1 /***************************************************************************
2 * *
3 * Copyright (C) 2007-2014 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::toPosix() const {
52 // POSIX paths consist of forward slash separators and requires forward
53 // slashes in path and file names to be encoded as "%2f", the file names
54 // "." and ".." have special meanings
55 // (see http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap03.html#tag_03_169
56 // and http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap03.html#tag_03_266 )
57 std::string result;
58 for (int iElement = 0; iElement < elements.size(); iElement++) {
59 // encode percent characters
60 std::string e = elements[iElement];
61 for (
62 int pos = e.find("%"); pos != std::string::npos;
63 pos = e.find("%", pos+2)
64 ) e.replace(pos/*offset*/, 1/*length*/, "%%"/*by*/);
65 // encode forward slashes
66 for (
67 int pos = e.find("/"); pos != std::string::npos;
68 pos = e.find("/", pos+3)
69 ) e.replace(pos/*offset*/, 1/*length*/, "%2f"/*by*/);
70 // append encoded node to full encoded path
71 result += "/" + e;
72 }
73 if (!result.size()) result = "/";
74 return result;
75 }
76
77 std::string Path::toDbPath() const {
78 std::string result;
79 for (int iElement = 0; iElement < elements.size(); iElement++) {
80 // replace all slashes with '\0'
81 std::string e = elements[iElement];
82 for (int i = 0; i < e.length(); i++) {
83 if (e.at(i) == '/') e.at(i) = '\0';
84 }
85 // append encoded node to full encoded path
86 result += "/" + e;
87 }
88 if (!result.size()) result = "/";
89 return result;
90 }
91
92 std::string Path::toLscp() const {
93 std::string result;
94 #if WIN32
95 if(drive) {
96 result.assign(&drive,1);
97 result += ":";
98 }
99 #endif
100 for (int iElement = 0; iElement < elements.size(); iElement++) {
101 // replace "special characters" by LSCP escape sequences
102 std::string e = elements[iElement];
103 for (int i = 0; i < e.length(); i++) {
104 const char c = e.c_str()[i];
105 if (
106 !(c >= '0' && c <= '9') &&
107 !(c >= 'a' && c <= 'z') &&
108 !(c >= 'A' && c <= 'Z') &&
109 !(c == '!') && !(c == '#') && !(c == '$') && !(c == '%') &&
110 !(c == '&') && !(c == '(') && !(c == ')') && !(c == '*') &&
111 !(c == '+') && !(c == ',') && !(c == '-') && !(c == '.') &&
112 !(c == ':') && !(c == ';') && !(c == '<') && !(c == '=') &&
113 !(c == '>') && !(c == '?') && !(c == '@') && !(c == '[') &&
114 !(c == ']') && !(c == '^') && !(c == '_') && !(c == '`') &&
115 !(c == '{') && !(c == '|') && !(c == '}') && !(c == '~')
116 ) {
117 // convert the "special" character into a "\xHH" LSCP escape sequence
118 char buf[5];
119 snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
120 e.replace(i, 1, buf);
121 i += 3;
122 }
123 }
124 // append encoded node to full encoded path
125 result += "/" + e;
126 }
127 if (!result.size()) result = "/";
128 return result;
129 }
130
131 std::string Path::toWindows() const {
132 std::stringstream result;
133 const char cDrive =
134 ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z'))
135 ? drive : '?';
136 result << cDrive;
137 result << ':';
138 for (int iElement = 0; iElement < elements.size(); iElement++) {
139 // append encoded node to full encoded path
140 result << "\\" << elements[iElement];
141 }
142 if (elements.empty()) result << '\\';
143 return result.str();
144 }
145
146 Path Path::operator+(const Path& p) {
147 Path result = *this;
148 for (int i = 0; i < p.elements.size(); i++)
149 result.elements.push_back(p.elements[i]);
150 return result;
151 }
152
153 Path Path::operator+(const Path* p) {
154 return *this + *p;
155 }
156
157 Path Path::fromPosix(std::string path) {
158 Path result;
159 // first split the nodes
160 {
161 int nodeEnd;
162 for (
163 int nodeBegin = path.find_first_not_of('/');
164 nodeBegin != std::string::npos;
165 nodeBegin = path.find_first_not_of('/', nodeEnd)
166 ) {
167 nodeEnd = path.find_first_of('/', nodeBegin);
168 result.appendNode(
169 (nodeEnd != std::string::npos) ?
170 path.substr(nodeBegin, nodeEnd - nodeBegin) :
171 path.substr(nodeBegin)
172 );
173 }
174 }
175 // resolve POSIX escape sequences in all nodes
176 for (int iNode = 0; iNode < result.elements.size(); iNode++) {
177 std::string& s = result.elements[iNode];
178 for (int pos = s.find('%'); pos < s.length(); pos = s.find('%', ++pos)) {
179 if (pos+1 >= s.length()) { // unexpected character
180 //TODO: we might want to throw an exception here, for now we simply replace the character by '?'
181 s.replace(pos, 1, "?");
182 continue;
183 }
184 if (s.c_str()[pos+1] == '%') {
185 s.replace(pos, 2, "%");
186 continue;
187 }
188 if (pos+2 >= s.length()) {
189 //TODO: we might want to throw an exception here, for now we simply replace the character by '?'
190 s.replace(pos, 2, "?");
191 continue;
192 }
193 // expecting a "%HH" sequence here, convert it into the respective character
194 const std::string sHex = s.substr(pos+1, 2);
195 char cAscii = hexsToNumber(sHex.c_str()[1], sHex.c_str()[0]);
196 char pcAscii[] = { cAscii, 0 };
197 s.replace(pos, 3, pcAscii);
198 }
199 }
200 // check whether given string reflects an absolute path
201 // (indicated by a forward slash as first character on POSIX)
202 result.absolute = !path.empty() && path[0] == '/';
203 return result;
204 }
205
206 Path Path::fromDbPath(std::string path) {
207 Path result;
208 // first split the nodes
209 {
210 int nodeEnd;
211 for (
212 int nodeBegin = path.find_first_not_of('/');
213 nodeBegin != std::string::npos;
214 nodeBegin = path.find_first_not_of('/', nodeEnd)
215 ) {
216 nodeEnd = path.find_first_of('/', nodeBegin);
217
218 std::string s = (nodeEnd != std::string::npos) ?
219 path.substr(nodeBegin, nodeEnd - nodeBegin) :
220 path.substr(nodeBegin);
221
222 for (int i = 0; i < s.length(); i++) if (s.at(i) == '\0') s.at(i) = '/';
223 result.appendNode(s);
224 }
225 }
226 return result;
227 }
228
229 Path Path::fromWindows(std::string path) {
230 Path result;
231
232 int nodeEnd = 0;
233
234 // first retrieve drive
235 if (path.size() >= 2 && path.c_str()[1] == ':') {
236 result.setDrive(path.c_str()[0]);
237 nodeEnd = 2;
238 }
239
240 // split the nodes
241 {
242 for (
243 int nodeBegin = path.find_first_not_of('\\', nodeEnd);
244 nodeBegin != std::string::npos;
245 nodeBegin = path.find_first_not_of('\\', nodeEnd)
246 ) {
247 nodeEnd = path.find_first_of('\\', nodeBegin);
248 result.appendNode(
249 (nodeEnd != std::string::npos) ?
250 path.substr(nodeBegin, nodeEnd - nodeBegin) :
251 path.substr(nodeBegin)
252 );
253 }
254 }
255
256 // check whether given string reflects an absolute path
257 // (indicated either by a backslash or drive at the beginning on Windows)
258 result.absolute = result.drive || (!path.empty() && path[0] == '\\');
259
260 return result;
261 }
262
263 std::string Path::getName(std::string path) {
264 Path p;
265 #if WIN32
266 p.fromWindows(path);
267 #else
268 p.fromPosix(path);
269 #endif
270
271 return p.getName();
272 }
273
274 std::string Path::getName() {
275 if(elements.empty()) return "";
276 return elements[elements.size() - 1];
277 }
278
279 std::string Path::getBaseName(std::string path) {
280 Path p;
281 #if WIN32
282 p = fromWindows(path);
283 #else
284 p = fromPosix(path);
285 #endif
286
287 return p.getBaseName();
288 }
289
290 std::string Path::getBaseName() {
291 std::string name = getName();
292 size_t lastdot = name.find_last_of('.');
293 if(lastdot == std::string::npos) return name;
294 return name.substr(0, lastdot);
295 }
296
297 std::string Path::stripLastName() {
298 if (elements.size() > 0) elements.pop_back();
299 #if WIN32
300 return toWindows();
301 #endif
302
303 return toPosix();
304 }
305
306 std::string Path::stripLastName(std::string path) {
307 Path p;
308 #if WIN32
309 p = fromWindows(path);
310 #else
311 p = fromPosix(path);
312 #endif
313
314 return p.stripLastName();
315 }
316
317 bool Path::isAbsolute() const {
318 return absolute;
319 }
320
321 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC