1 /*==========================================================================
2 * Copyright (c) 2004 University of Massachusetts. All Rights Reserved.
4 * Use of the Lemur Toolkit for Language Modeling and Information Retrieval
5 * is subject to the terms of the software license set forth in the LICENSE
6 * file included with this software, and also available at
7 * http://www.lemurproject.org/license.html
9 *==========================================================================
20 #include "indri/Path.hpp"
21 #include "lemur/Exception.hpp"
22 #include "lemur/lemur-compat.hpp"
27 #include "indri/DirectoryIterator.hpp"
28 #include "indri/delete_range.hpp"
29 #include "indri/XMLNode.hpp"
30 #include "indri/XMLReader.hpp"
33 #define PATH_SEPARATOR '\\'
35 #define PATH_SEPARATOR '/'
38 static int path_last_separator( const std::string
& path
) {
41 // skip any trailing slashes
42 for( i
=path
.size()-1; i
>=0; i
-- ) {
43 if( path
[i
] != PATH_SEPARATOR
)
48 if( path
[i
] == PATH_SEPARATOR
)
55 void indri::file::Path::create( const std::string
& path
) {
56 if( lemur_compat::mkdir( path
.c_str(), 0777 ) < 0 ) {
57 if( errno
== EACCES
) {
58 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't create directory: '" + path
+ "' because of inadequate permissions." );
59 } else if( errno
== ENOENT
) {
60 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't create directory: '" + path
+ "' because at least one of the parent directories does not exist." );
61 } else if( errno
== EEXIST
) {
62 LEMUR_THROW( LEMUR_IO_ERROR
, "Couldn't create directory: '" + path
+ "' because something already exists there." );
67 void indri::file::Path::remove( const std::string
& path
) {
68 std::stack
<indri::file::DirectoryIterator
*> iterators
;
69 indri::utility::StackDeleter
<indri::file::DirectoryIterator
> sd( iterators
);
70 iterators
.push( new indri::file::DirectoryIterator( path
) );
72 while( iterators
.size() ) {
73 indri::file::DirectoryIterator
* top
= iterators
.top();
75 // all done, so go up a level
76 if( (*top
) == indri::file::DirectoryIterator::end() ) {
77 // release any search handles that may point
81 int result
= rmdir( top
->base().c_str() );
83 LEMUR_THROW( LEMUR_IO_ERROR
, "indri::file::Path::remove couldn't remove directory '" + top
->base() + "'." );
90 std::string path
= **top
;
93 if( indri::file::Path::isFile( path
) ) {
94 int result
= lemur_compat::remove( path
.c_str() );
96 LEMUR_THROW( LEMUR_IO_ERROR
, "indri::file::Path::remove couldn't remove file '" + path
+ "'." );
98 iterators
.push( new indri::file::DirectoryIterator( path
) );
103 std::string
indri::file::Path::trim( const std::string
& path
) {
104 if( path
.size() && path
[path
.length()-1] == PATH_SEPARATOR
) {
105 return path
.substr( 0, path
.length()-1 );
111 std::string
indri::file::Path::relative( const std::string
& basePath
, const std::string absolutePath
) {
112 std::string relativePath
= absolutePath
.substr( basePath
.length() );
114 while( relativePath
.length() && relativePath
[0] == PATH_SEPARATOR
)
115 relativePath
= relativePath
.substr(1);
120 void indri::file::Path::make( const std::string
& path
) {
121 if( !indri::file::Path::isDirectory( path
) ) {
122 std::string parent
= indri::file::Path::directory( path
);
126 indri::file::Path::make( parent
);
129 lemur_compat::mkdir( path
.c_str(), 0755 );
132 char indri::file::Path::pathSeparator() {
133 return PATH_SEPARATOR
;
136 bool indri::file::Path::isDirectory( const std::string
& path
) {
138 int result
= stat( path
.c_str(), &s
);
139 bool actualDirectory
= (result
>= 0) && (s
.st_mode
& S_IFDIR
);
141 return actualDirectory
;
144 bool indri::file::Path::exists( const std::string
& path
) {
146 return stat( path
.c_str(), &s
) >= 0;
149 bool indri::file::Path::isFile( const std::string
& path
) {
151 int result
= stat( path
.c_str(), &s
);
152 bool actualFile
= (result
>= 0) && (s
.st_mode
& S_IFREG
);
157 std::string
indri::file::Path::combine( const std::string
& root
, const std::string
& addition
) {
161 if( *(root
.end()-1) == PATH_SEPARATOR
)
162 return root
+ addition
;
164 return root
+ PATH_SEPARATOR
+ addition
;
167 std::string
indri::file::Path::directory( const std::string
& path
) {
168 int last
= path_last_separator( path
);
171 return path
.substr( 0, last
);
177 std::string
indri::file::Path::filename( const std::string
& path
) {
178 int last
= path_last_separator( path
);
180 if( last
!= std::string::npos
) {
181 return path
.substr( last
+1 );
187 std::string
indri::file::Path::extension( const std::string
& path
) {
188 int last
= path_last_separator( path
);
189 std::string::size_type lastDot
= path
.find_last_of( '.' );
191 if( int(lastDot
) > last
) {
192 return path
.substr( lastDot
+1 );
195 return std::string();
198 std::string
indri::file::Path::basename( const std::string
& path
) {
199 int last
= path_last_separator( path
);
200 std::string::size_type lastDot
= path
.find_last_of( '.' );
202 if( int(lastDot
) > last
) {
203 return path
.substr( 0, lastDot
);