]> git.tdb.fi Git - libs/core.git/blob - source/fs/utils.cpp
Make fix_case to work with relative paths
[libs/core.git] / source / fs / utils.cpp
1 #include <msp/strings/utils.h>
2 #include "dir.h"
3 #include "utils.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace FS {
9
10 string basename(const Path &p)
11 {
12         return p[-1];
13 }
14
15 Path dirname(const Path &p)
16 {
17         if(p.size()==1)
18         {
19                 if(p.is_absolute())
20                         return p;
21                 return ".";
22         }
23         return p.subpath(0, p.size()-1);
24 }
25
26 string basepart(const string &fn)
27 {
28         unsigned dot = fn.rfind('.');
29         return fn.substr(0, dot);
30 }
31
32 string extpart(const string &fn)
33 {
34         string::size_type dot = fn.rfind('.');
35         if(dot==string::npos)
36                 return string();
37         return fn.substr(dot);
38 }
39
40 Path fix_case(const Path &path)
41 {
42         bool found = true;
43         Path result;
44         for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
45         {
46                 if(!found || (result.empty() && (*i=="/" || *i==".")))
47                         result /= *i;
48                 else
49                 {
50                         list<string> files;
51                         if(result.size())
52                                 files = list_files(result);
53                         else
54                                 files = list_files(".");
55
56                         found = false;
57                         for(list<string>::iterator j=files.begin(); (j!=files.end() && !found); ++j)
58                                 if(!strcasecmp(*j,*i))
59                                 {
60                                         result /= *j;
61                                         found = true;
62                                 }
63
64                         if(!found)
65                                 result /= *i;
66                 }
67         }
68
69         return result;
70 }
71
72 Path relative(const Path &path, const Path &base)
73 {
74         if(path.is_absolute()!=base.is_absolute())
75                 throw invalid_argument("FS::relative");
76
77         Path::Iterator i = path.begin();
78         Path::Iterator j = base.begin();
79         for(; (i!=path.end() && j!=base.end() && *i==*j); ++i, ++j) ;
80
81         Path result;
82         for(; j!=base.end(); ++j)
83                 result /= "..";
84         for(; i!=path.end(); ++i)
85                 result /= *i;
86
87         return result;
88 }
89
90 Path common_ancestor(const Path &path1, const Path &path2)
91 {
92         Path::Iterator i = path1.begin();
93         Path::Iterator j = path2.begin();
94         Path result;
95         for(; (i!=path1.end() && j!=path2.end() && *i==*j); ++i, ++j)
96                 result /= *i;
97         return result;
98 }
99
100 int descendant_depth(const Path &path, const Path &parent)
101 {
102         if(path.is_absolute()!=parent.is_absolute())
103                 throw invalid_argument("FS::descendant_depth");
104
105         Path::Iterator i = path.begin();
106         Path::Iterator j = parent.begin();
107         for(; (i!=path.end() && j!=parent.end() && *i==*j); ++i, ++j) ;
108
109         if(j!=parent.end())
110                 return -1;
111         
112         int result = 0;
113         for(; i!=path.end(); ++i)
114                 ++result;
115
116         return result;
117 }
118
119 } // namespace FS
120 } // namespace Msp