0f9778356ac4543b96f415b8b14f1cc7dde7fbaa
[supertux.git] / src / file_system.cpp
1 #include <config.h>
2
3 #include "log.hpp"
4 #include "file_system.hpp"
5
6 #include <string>
7 #include <vector>
8 #include <sstream>
9
10 namespace FileSystem
11 {
12
13 std::string dirname(const std::string& filename)
14 {
15   std::string::size_type p = filename.find_last_of('/');
16   if(p == std::string::npos)                              
17     return "";
18   
19   return filename.substr(0, p+1);
20 }
21
22 std::string basename(const std::string& filename)
23 {
24   std::string::size_type p = filename.find_last_of('/');
25   if(p == std::string::npos)
26     return filename;
27
28   return filename.substr(p+1, filename.size()-p-1);
29 }
30
31 std::string normalize(const std::string& filename)
32 {
33   std::vector<std::string> path_stack;
34
35   const char* p = filename.c_str();
36
37   while(true) {
38     while(*p == '/') {
39       p++;
40       continue;
41     }
42
43     const char* pstart = p;
44     while(*p != '/' && *p != 0) {
45       ++p;
46     }
47
48     size_t len = p - pstart;
49     if(len == 0)
50       break;
51     
52     std::string pathelem(pstart, p-pstart);
53     if(pathelem == ".")
54       continue;
55     
56     if(pathelem == "..") {
57       if(path_stack.empty()) {
58
59         log_warning << "Invalid '..' in path '" << filename << "'" << std::endl;
60         // push it into the result path so that the users sees his error...
61         path_stack.push_back(pathelem);
62       } else {
63         path_stack.pop_back();
64       }
65     } else {
66       path_stack.push_back(pathelem);
67     }
68   }
69
70   // construct path
71   std::ostringstream result;
72   for(std::vector<std::string>::iterator i = path_stack.begin();
73       i != path_stack.end(); ++i) {
74     result << '/' << *i;
75   }
76   if(path_stack.empty())
77     result << '/';
78
79   return result.str();
80 }
81
82 }
83