Deprecate MediaAccess::downloads (accidentally deleted)
[platform/upstream/libzypp.git] / zypp / Pathname.cc
1 /*---------------------------------------------------------------------\
2  |                          ____ _   __ __ ___                          |
3  |                         |__  / \ / / . \ . \                         |
4  |                           / / \ V /|  _/  _/                         |
5  |                          / /__ | | | | | |                           |
6  |                         /_____||_| |_| |_|                           |
7  |                                                                      |
8  \---------------------------------------------------------------------*/
9 /** \file       zypp/Pathname.cc
10  *
11 */
12 #include <iostream>
13
14 #include "zypp/base/String.h"
15 #include "zypp/Pathname.h"
16 #include "zypp/Url.h"
17
18 using std::string;
19
20 ///////////////////////////////////////////////////////////////////
21 namespace zypp
22 { /////////////////////////////////////////////////////////////////
23   ///////////////////////////////////////////////////////////////////
24   namespace filesystem
25   { /////////////////////////////////////////////////////////////////
26
27     ///////////////////////////////////////////////////////////////////
28     namespace
29     { /////////////////////////////////////////////////////////////////
30
31       ///////////////////////////////////////////////////////////////////
32       //
33       //        CLASS NAME : DirStack
34       //
35       /** silly helper to build Pathnames.
36       */
37       class DirStack {
38
39         struct Dir {
40
41           Dir *  up;
42           Dir *  dn;
43           string name;
44
45           Dir( const string & n = "" ) {
46             name = n;
47             up = dn = 0;
48           }
49
50           ~Dir() {
51             if ( up )
52               up->dn = dn;
53             if ( dn )
54               dn->up = up;
55           }
56         };
57
58         Dir *  top;
59         Dir *  bot;
60
61         void Pop() {
62           if ( !top )
63             return;
64           top = top->dn;
65           if ( top )
66             delete top->up;
67           else {
68             delete bot;
69             bot = 0;
70           }
71         }
72
73       public:
74
75         DirStack() { top = bot = 0; }
76         ~DirStack() {
77           while ( bot )
78             Pop();
79         }
80
81         void Push( const string & n ) {
82           if ( n.empty() || n == "." ) { // '.' or '/' only for bot
83             if ( bot )
84               return;
85           } else if ( n == ".." && top ) {
86             if ( top->name == "" )          // "/.."        ==> "/"
87               return;
88
89             if ( top->name != "." && top->name != ".." ) {      // "somedir/.." ==> ""
90               Pop();
91               return;
92             }
93             // "../.." "./.." stays
94           }
95
96           Dir * d = new Dir( n );
97           if ( !top )
98             top = bot = d;
99           else {
100             top->up = d;
101             d->dn = top;
102             d->up = 0;
103             top = d;
104           }
105         }
106
107         string str() {
108           if ( !bot )
109             return "";
110           string ret;
111           for ( Dir * d = bot; d; d = d->up ) {
112             if ( d != bot )
113               ret += "/";
114             ret += d->name;
115           }
116           if ( ret.empty() )
117             return "/";
118           return ret;
119         }
120       };
121
122       /////////////////////////////////////////////////////////////////
123     } // namespace
124     ///////////////////////////////////////////////////////////////////
125
126     ///////////////////////////////////////////////////////////////////
127     //
128     //  METHOD NAME : Pathname::_assign
129     //  METHOD TYPE : void
130     //
131     void Pathname::_assign( const string & name_tv )
132     {
133       prfx_i = 0;
134       name_t = name_tv;
135
136       if ( name_t.empty() )
137         return;
138
139       string   Tprfx;
140       DirStack Stack_Ci;
141
142       char *       Buf_aci    = new char[name_tv.length() + 1];
143       char *       W_pci      = Buf_aci;
144       const char * R_pci      = name_tv.c_str();
145
146       // check for prefix
147       if (    name_t.length() >= 2
148            && name_t[1] == ':'
149            && (    ( 'a' <= name_t[0] && name_t[0] <= 'z' )
150                 || ( 'A' <= name_t[0] && name_t[0] <= 'Z' ) ) ) {
151         Tprfx  = name_t.substr( 0, 2 );
152         prfx_i = 2;
153         R_pci += 2;
154       }
155
156       // rel or abs path
157       if ( *R_pci == '/' || *R_pci == '\\' ) {
158         Stack_Ci.Push( "" );
159         ++R_pci;
160       } else {
161         Stack_Ci.Push( "." );
162       }
163
164       do {
165         switch ( *R_pci ) {
166         case '/':
167         case '\\':
168         case '\0':
169           if ( W_pci != Buf_aci ) {
170             *W_pci = '\0';
171             W_pci = Buf_aci;
172             Stack_Ci.Push( Buf_aci );
173           }
174           break;
175
176         default:
177           *W_pci++ = *R_pci;
178           break;
179         }
180       } while( *R_pci++ );
181
182       delete[] Buf_aci;
183       name_t = Tprfx + Stack_Ci.str();
184     }
185
186     ///////////////////////////////////////////////////////////////////
187     //
188     //  METHOD NAME : Pathname::dirname
189     //  METHOD TYPE : Pathname
190     //
191     Pathname Pathname::dirname( const Pathname & name_tv )
192     {
193       if ( name_tv.empty() )
194         return "";
195
196       Pathname ret_t( name_tv );
197       string::size_type idx = ret_t.name_t.find_last_of( '/' );
198
199       if ( idx == string::npos ) {
200         ret_t.name_t.erase( ret_t.prfx_i );
201         ret_t.name_t += ".";
202       } else if ( idx == ret_t.prfx_i ) {
203         ret_t.name_t.erase( ret_t.prfx_i );
204         ret_t.name_t += "/";
205       } else {
206         ret_t.name_t.erase( idx );
207       }
208
209       return ret_t;
210     }
211
212     ///////////////////////////////////////////////////////////////////
213     //
214     //  METHOD NAME : Pathname::basename
215     //  METHOD TYPE : string
216     //
217     string Pathname::basename( const Pathname & name_tv )
218     {
219       if ( name_tv.empty() )
220         return string();
221
222       string ret_t( name_tv.asString() );
223       ret_t.erase( 0, name_tv.prfx_i );
224       string::size_type idx = ret_t.find_last_of( '/' );
225       if ( idx != string::npos ) {
226         ret_t.erase( 0, idx+1 );
227       }
228
229       return ret_t;
230     }
231
232     ///////////////////////////////////////////////////////////////////
233     //
234     //  METHOD NAME : Pathname::asUrl
235     //  METHOD TYPE : Url
236     //
237     Url Pathname::asUrl() const
238     {
239       Url ret( "dir:///" );
240       ret.setPathName( asString() );
241       return ret;
242     }
243
244     ///////////////////////////////////////////////////////////////////
245     //
246     //  METHOD NAME : Pathname::extension
247     //  METHOD TYPE : string
248     //
249     string Pathname::extension( const Pathname & name_tv )
250     {
251       if ( name_tv.empty() )
252         return string();
253
254       string base( basename( name_tv ) );
255       string::size_type pos = base.rfind( '.' );
256       if ( pos == string::npos )
257         return string();
258       return base.substr( pos );
259     }
260
261     ///////////////////////////////////////////////////////////////////
262     //
263     //  METHOD NAME : Pathname::assertprefix
264     //  METHOD TYPE : Pathname
265     //
266     Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r )
267     {
268       if ( root_r.empty()
269            || path_r == root_r
270            || str::hasPrefix( path_r.asString(), root_r.asString() ) )
271         return path_r;
272       return root_r / path_r;
273     }
274
275     ///////////////////////////////////////////////////////////////////
276     //
277     //  METHOD NAME : Pathname::cat
278     //  METHOD TYPE : Pathname
279     //
280     Pathname Pathname::cat( const Pathname & name_tv, const Pathname & add_tv )
281     {
282       if ( add_tv.empty() )
283         return name_tv;
284       if ( name_tv.empty() )
285         return add_tv;
286
287       string ret_ti( add_tv.asString() );
288       ret_ti.replace( 0, add_tv.prfx_i, "/" );
289
290       return name_tv.asString() + ret_ti;
291     }
292
293     ///////////////////////////////////////////////////////////////////
294     //
295     //  METHOD NAME : Pathname::Extend
296     //  METHOD TYPE : Pathname
297     //
298     Pathname Pathname::extend( const Pathname & l, const string & r )
299     {
300       return l.asString() + r;
301     }
302
303     /////////////////////////////////////////////////////////////////
304   } // namespace filesystem
305   ///////////////////////////////////////////////////////////////////
306   /////////////////////////////////////////////////////////////////
307 } // namespace zypp
308 ///////////////////////////////////////////////////////////////////