Merged changes from branches/supertux-milestone2-grumbel/ to trunk/supertux/
[supertux.git] / src / util / file_system.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "util/log.hpp"
18
19 #include <sstream>
20 #include <vector>
21
22 namespace FileSystem {
23
24 std::string dirname(const std::string& filename)
25 {
26   std::string::size_type p = filename.find_last_of('/');
27   if(p == std::string::npos)
28     p = filename.find_last_of('\\');
29   if(p == std::string::npos)
30     return "./";
31
32   return filename.substr(0, p+1);
33 }
34
35 std::string basename(const std::string& filename)
36 {
37   std::string::size_type p = filename.find_last_of('/');
38   if(p == std::string::npos)
39     p = filename.find_last_of('\\');
40   if(p == std::string::npos)
41     return filename;
42
43   return filename.substr(p+1, filename.size()-p-1);
44 }
45
46 std::string strip_extension(const std::string& filename)
47 {
48   std::string::size_type p = filename.find_last_of('.');
49   if(p == std::string::npos)
50     return filename;
51
52   return filename.substr(0, p);
53 }
54
55 std::string normalize(const std::string& filename)
56 {
57   std::vector<std::string> path_stack;
58
59   const char* p = filename.c_str();
60
61   while(true) {
62     while(*p == '/' || *p == '\\') {
63       p++;
64       continue;
65     }
66
67     const char* pstart = p;
68     while(*p != '/' && *p != '\\' && *p != 0) {
69       ++p;
70     }
71
72     size_t len = p - pstart;
73     if(len == 0)
74       break;
75
76     std::string pathelem(pstart, p-pstart);
77     if(pathelem == ".")
78       continue;
79
80     if(pathelem == "..") {
81       if(path_stack.empty()) {
82
83         log_warning << "Invalid '..' in path '" << filename << "'" << std::endl;
84         // push it into the result path so that the user sees his error...
85         path_stack.push_back(pathelem);
86       } else {
87         path_stack.pop_back();
88       }
89     } else {
90       path_stack.push_back(pathelem);
91     }
92   }
93
94   // construct path
95   std::ostringstream result;
96   for(std::vector<std::string>::iterator i = path_stack.begin();
97       i != path_stack.end(); ++i) {
98     result << '/' << *i;
99   }
100   if(path_stack.empty())
101     result << '/';
102
103   return result.str();
104 }
105
106 } // namespace FileSystem
107
108 /* EOF */