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