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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3091 - (hide annotations) (download)
Mon Jan 16 15:01:21 2017 UTC (3 years, 10 months ago) by schoenebeck
File size: 11369 byte(s)
* Cleanup of instruments DB file creation and opening code.
* The instrument DB path of linuxsampler's --create-instruments-db argument
  is now optional, if it is missing, then a default location is used.
* Bumped version (2.0.0.svn39).

1 schoenebeck 1332 /***************************************************************************
2     * *
3 schoenebeck 3082 * Copyright (C) 2007-2017 Christian Schoenebeck *
4 schoenebeck 1332 * *
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 schoenebeck 1399 // for function hexsToNumber()
24 schoenebeck 1424 #include "global_private.h"
25 schoenebeck 1399
26 schoenebeck 1471 #include <sstream>
27    
28 schoenebeck 1332 namespace LinuxSampler {
29    
30 schoenebeck 2529 Path::Path() : drive(0), absolute(false) {
31 schoenebeck 1471 }
32    
33 schoenebeck 2529 Path::Path(std::string path) {
34     #if WIN32
35     *this = fromWindows(path);
36     #else
37     *this = fromPosix(path);
38     #endif
39     }
40    
41 schoenebeck 1332 void Path::appendNode(std::string Name) {
42     if (!Name.size()) return;
43     elements.push_back(Name);
44     }
45    
46 schoenebeck 1471 void Path::setDrive(const char& Drive) {
47     drive = Drive;
48 schoenebeck 2529 absolute = true;
49 schoenebeck 1471 }
50    
51 schoenebeck 3082 std::string Path::toNativeFSPath() const {
52     #if WIN32
53     return toWindows();
54     #else
55     return toPosix();
56     #endif
57     }
58    
59 schoenebeck 1471 std::string Path::toPosix() const {
60 schoenebeck 1332 // 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 schoenebeck 1338 // encode percent characters
68 schoenebeck 1332 std::string e = elements[iElement];
69     for (
70 schoenebeck 3054 int pos = (int)e.find("%"); pos != std::string::npos;
71     pos = (int)e.find("%", pos+2)
72 schoenebeck 1338 ) e.replace(pos/*offset*/, 1/*length*/, "%%"/*by*/);
73     // encode forward slashes
74     for (
75 schoenebeck 3054 int pos = (int)e.find("/"); pos != std::string::npos;
76     pos = (int)e.find("/", pos+3)
77 schoenebeck 1332 ) 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 schoenebeck 1471 std::string Path::toDbPath() const {
86 iliev 1345 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 schoenebeck 1471 std::string Path::toLscp() const {
101 schoenebeck 1399 std::string result;
102 senoner 1537 #if WIN32
103     if(drive) {
104     result.assign(&drive,1);
105     result += ":";
106     }
107     #endif
108 schoenebeck 1399 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 schoenebeck 1471 std::string Path::toWindows() const {
140     std::stringstream result;
141 senoner 1481 const char cDrive =
142     ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z'))
143 schoenebeck 1471 ? drive : '?';
144 senoner 1481 result << cDrive;
145 schoenebeck 1471 result << ':';
146     for (int iElement = 0; iElement < elements.size(); iElement++) {
147     // append encoded node to full encoded path
148     result << "\\" << elements[iElement];
149     }
150 persson 1943 if (elements.empty()) result << '\\';
151 schoenebeck 1471 return result.str();
152     }
153    
154 schoenebeck 1332 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 schoenebeck 3082 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 schoenebeck 1399 Path Path::fromPosix(std::string path) {
186     Path result;
187     // first split the nodes
188     {
189     int nodeEnd;
190     for (
191 schoenebeck 3054 int nodeBegin = (int)path.find_first_not_of('/');
192 schoenebeck 1399 nodeBegin != std::string::npos;
193 schoenebeck 3054 nodeBegin = (int)path.find_first_not_of('/', nodeEnd)
194 schoenebeck 1399 ) {
195 schoenebeck 3054 nodeEnd = (int)path.find_first_of('/', nodeBegin);
196 schoenebeck 1399 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 schoenebeck 3054 for (size_t pos = s.find('%'); pos < s.length(); pos = s.find('%', ++pos)) {
207 schoenebeck 1399 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 schoenebeck 2529 // 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 schoenebeck 1399 return result;
232     }
233    
234 iliev 1403 Path Path::fromDbPath(std::string path) {
235     Path result;
236     // first split the nodes
237     {
238     int nodeEnd;
239     for (
240 schoenebeck 3054 int nodeBegin = (int)path.find_first_not_of('/');
241 iliev 1403 nodeBegin != std::string::npos;
242 schoenebeck 3054 nodeBegin = (int)path.find_first_not_of('/', nodeEnd)
243 iliev 1403 ) {
244 schoenebeck 3054 nodeEnd = (int)path.find_first_of('/', nodeBegin);
245 iliev 1403
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 senoner 1481 Path Path::fromWindows(std::string path) {
258 schoenebeck 1471 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 schoenebeck 3054 int nodeBegin = (int)path.find_first_not_of('\\', nodeEnd);
272 schoenebeck 1471 nodeBegin != std::string::npos;
273 schoenebeck 3054 nodeBegin = (int)path.find_first_not_of('\\', nodeEnd)
274 schoenebeck 1471 ) {
275 schoenebeck 3054 nodeEnd = (int)path.find_first_of('\\', nodeBegin);
276 schoenebeck 1471 result.appendNode(
277     (nodeEnd != std::string::npos) ?
278     path.substr(nodeBegin, nodeEnd - nodeBegin) :
279     path.substr(nodeBegin)
280     );
281     }
282     }
283    
284 schoenebeck 2529 // 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 schoenebeck 1471 return result;
289     }
290    
291 iliev 1782 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 schoenebeck 3082 std::string Path::getName() const {
303 iliev 1782 if(elements.empty()) return "";
304     return elements[elements.size() - 1];
305     }
306    
307     std::string Path::getBaseName(std::string path) {
308 iliev 2012 Path p;
309 iliev 1782 #if WIN32
310     p = fromWindows(path);
311     #else
312     p = fromPosix(path);
313     #endif
314    
315     return p.getBaseName();
316     }
317    
318 schoenebeck 3082 std::string Path::getBaseName() const {
319 iliev 1782 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 iliev 2012 std::string Path::stripLastName() {
326     if (elements.size() > 0) elements.pop_back();
327     #if WIN32
328     return toWindows();
329 schoenebeck 3082 #else
330     return toPosix();
331 iliev 2012 #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 schoenebeck 2529 bool Path::isAbsolute() const {
346     return absolute;
347     }
348    
349 schoenebeck 3091 std::vector<std::string>& Path::nodes() {
350     return elements;
351     }
352    
353 schoenebeck 1332 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC