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

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

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

revision 1338 by schoenebeck, Sun Sep 9 23:30:34 2007 UTC revision 2529 by schoenebeck, Tue Mar 4 20:41:47 2014 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2007 Christian Schoenebeck                              *   *   Copyright (C) 2007-2014 Christian Schoenebeck                         *
4   *                                                                         *   *                                                                         *
5   *   This library is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 20  Line 20 
20    
21  #include "Path.h"  #include "Path.h"
22    
23    // for function hexsToNumber()
24    #include "global_private.h"
25    
26    #include <sstream>
27    
28  namespace LinuxSampler {  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) {  void Path::appendNode(std::string Name) {
42      if (!Name.size()) return;      if (!Name.size()) return;
43      elements.push_back(Name);      elements.push_back(Name);
44  }  }
45    
46  std::string Path::toPosix() {  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      // 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      // slashes in path and file names to be encoded as "%2f", the file names
54      // "." and ".." have special meanings      // "." and ".." have special meanings
# Line 53  std::string Path::toPosix() { Line 74  std::string Path::toPosix() {
74      return result;      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) {  Path Path::operator+(const Path& p) {
147      Path result = *this;      Path result = *this;
148      for (int i = 0; i < p.elements.size(); i++)      for (int i = 0; i < p.elements.size(); i++)
# Line 64  Path Path::operator+(const Path* p) { Line 154  Path Path::operator+(const Path* p) {
154      return *this + *p;      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  } // namespace LinuxSampler

Legend:
Removed from v.1338  
changed lines
  Added in v.2529

  ViewVC Help
Powered by ViewVC