/[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 1943 - (show annotations) (download)
Tue Jul 14 18:25:11 2009 UTC (14 years, 9 months ago) by persson
File size: 9572 byte(s)
* fixed instrument database recursive import, which was broken on
  Windows

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

  ViewVC Help
Powered by ViewVC