filesystem.cpp

Go to the documentation of this file.
00001 
00014 #include <dlrPortability/filesystem.h>
00015 
00016 /* ===================== Common includes ===================== */
00017 
00018 #include <algorithm>
00019 #include <sstream>
00020 #include <sys/stat.h>
00021 #include <sys/types.h>
00022 #include <dlrCommon/exception.h>
00023 #include <dlrCommon/functional.h>
00024 
00025 /* ===================== End common includes ===================== */
00026 
00027 #ifdef _WIN32
00028 
00029 /* ===================== Windows includes ===================== */
00030 
00031 #include <io.h>
00032 #include <windows.h>
00033 
00034 /* ===================== End Windows includes ===================== */
00035 
00036 #else /* #ifdef _WIN32 */
00037 
00038 /* ===================== Linux includes ===================== */
00039 
00040 #include <dirent.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043 
00044 /* ===================== End Linux includes ===================== */
00045 
00046 #endif /* #ifdef _WIN32 */
00047 
00048 
00049 /* ===================== Common code ===================== */
00050 
00051 namespace dlr {
00052 
00053   namespace portability {
00054 
00055 
00056     // This function returns a bool indicating whether or not the
00057     // specified path is a directory.
00058     bool
00059     isDirectory(const std::string& path)
00060     {
00061       struct stat statBuf;
00062       memset(&statBuf, 0, sizeof(statBuf));
00063       int returnValue = stat(path.c_str(), &statBuf);
00064       if(returnValue == 0) {
00065         // if(S_ISDIR(statBuf.st_mode)) {
00066         if((statBuf.st_mode & S_IFMT) == S_IFDIR) {
00067           return true;
00068         }
00069       }
00070       return false;
00071     }
00072     
00073 
00074     // Joins two path elements with the appropriate delimiter.
00075     std::string
00076     joinPath(const std::string& part0, const std::string& part1)
00077     {
00078       if(part0.empty()) {
00079         return part1;
00080       }
00081       if(part1.empty()) {
00082         return part0;
00083       }
00084       if(part0.size() >= pathDelimiter().size()) {
00085         if(part0.compare(
00086              part0.size() - pathDelimiter().size(), std::string::npos,
00087              pathDelimiter()) == 0) {
00088           return part0 + part1;
00089         }
00090       }
00091       return part0 + pathDelimiter() + part1;
00092     }
00093 
00094 
00095     // This function accepts a path returns a pair of strings in which
00096     // the first element is the directory name and the second is the
00097     // filename.
00098     std::pair<std::string, std::string>
00099     splitPath(const std::string& path)
00100     {
00101       std::string::size_type delimiterIndex = path.rfind(pathDelimiter());
00102       if(delimiterIndex == std::string::npos) {
00103         return std::make_pair(std::string(""), path);
00104       }
00105       if(delimiterIndex == path.size() - 1) {
00106         return std::make_pair(path, std::string(""));
00107       }
00108       return std::make_pair(
00109         path.substr(0, delimiterIndex + 1),
00110         path.substr(delimiterIndex + 1, std::string::npos));
00111     }
00112     
00113   } // namespace portability
00114 
00115 } // namespace dlr
00116 
00117 /* ===================== End common code ===================== */
00118 
00119 
00120 #ifdef _WIN32
00121 
00122 /* ===================== Windows code ===================== */
00123 
00124 // Anonymous namespace for stuff local to this file.
00125 namespace dlr {
00126 
00127   namespace portability {
00128 
00129     // Initialize on first use to avoid static initialization order fiasco.
00130     const std::string& pathDelimiter() {
00131       static std::string delimiter = "\\";
00132       return delimiter;
00133     }
00134 
00135   
00136     // Initialize on first use to avoid static initialization order fiasco.
00137     const std::string& extensionDelimiter() {
00138       static std::string delimiter = ".";
00139       return delimiter;
00140     }
00141 
00142 
00143     // Returns the names of the entries in the specified directory, in
00144     // no particular order.
00145     std::vector<std::string>
00146     listDirectory(const std::string& directoryName, bool fullPath)
00147     {
00148       std::vector<std::string> listing;
00149       std::string fileNameGlob = joinPath(directoryName, "*");
00150       WIN32_FIND_DATA findData;
00151       HANDLE handle = FindFirstFile(fileNameGlob.c_str(), &findData); 
00152       if (handle == INVALID_HANDLE_VALUE) { 
00153         return listing;
00154       } 
00155       while(1) {
00156         listing.push_back(std::string(findData.cFileName));
00157         if (!FindNextFile(handle, &findData)) {
00158           if (GetLastError() == ERROR_NO_MORE_FILES) {
00159             break;
00160           }
00161           std::ostringstream message;
00162           message << "Problem reading file names from " << directoryName;
00163           DLR_THROW(dlr::IOException, "listDirectory()",
00164                     message.str().c_str());
00165         }
00166       }
00167       if (!FindClose(handle)) { 
00168         std::ostringstream message;
00169         message << "Problem closing search handle for " << directoryName;
00170         DLR_THROW(dlr::IOException, "listDirectory()",
00171                   message.str().c_str());
00172       }
00173     
00174       if(fullPath) {
00175         // std::transform(listing.begin(), listing.end(), listing.begin(),
00176         //                std::bind1st(std::ptr_fun(joinPath), directoryName));
00177         typedef PointerToBinaryFunctionRA<std::string, std::string, std::string>
00178           functorType;
00179         std::transform(listing.begin(), listing.end(), listing.begin(),
00180                        std::bind1st(functorType(joinPath), directoryName));
00181       }
00182       return listing;
00183     }
00184   
00185   } // namespace portability
00186   
00187 } // namespace dlr
00188 
00189 /* ===================== End Windows code ===================== */
00190 
00191 #else /* #ifdef _WIN32 */
00192 
00193 /* ===================== Linux code ===================== */
00194 
00195 namespace dlr {
00196 
00197   namespace portability {
00198 
00199     // Initialize on first use to avoid static initialization order fiasco.
00200     const std::string& pathDelimiter() {
00201       static std::string delimiter = "/";
00202       return delimiter;
00203     }
00204 
00205   
00206     // Initialize on first use to avoid static initialization order fiasco.
00207     const std::string& extensionDelimiter() {
00208       static std::string delimiter = ".";
00209       return delimiter;
00210     }
00211 
00212 
00213     // Returns the names of the entries in the specified directory, in
00214     // no particular order.
00215     std::vector<std::string>
00216     listDirectory(const std::string& directoryName, bool fullPath)
00217     {
00218       std::vector<std::string> listing;
00219 
00220       DIR* directoryPtr = opendir(directoryName.c_str());
00221       if(directoryPtr == 0) {
00222         std::ostringstream message;
00223         char charBuffer[1024];
00224         if(strerror_r(errno, charBuffer, 1024) == 0) {
00225           charBuffer[1023] = '\0';
00226           message << charBuffer;
00227         } else {
00228           message << "Unknown error opening directory";
00229         }
00230         message << ": " << directoryName << std::endl;
00231         DLR_THROW(IOException, "listDirectory()", message.str().c_str());
00232       }
00233       while(1) {
00234         struct dirent* directoryEntryPtr = readdir(directoryPtr);
00235         if(directoryEntryPtr == 0) {
00236           // NULL return value indicates no more entries.
00237           // Can also indicate a bat directory stream, but we just
00238           // checked that above.
00239           break;
00240         }
00241         listing.push_back(std::string(directoryEntryPtr->d_name));
00242       }
00243     
00244       if(fullPath) {
00245         // std::transform(listing.begin(), listing.end(), listing.begin(),
00246         //                std::bind1st(std::ptr_fun(joinPath), directoryName));
00247         typedef PointerToBinaryFunctionRA<std::string, std::string, std::string>
00248           functorType;
00249         std::transform(listing.begin(), listing.end(), listing.begin(),
00250                        std::bind1st(functorType(joinPath), directoryName));
00251       }
00252       return listing;
00253     }
00254 
00255   } // namespace portability
00256 
00257 } // namespace dlr
00258 
00259 /* ===================== End Linux code ===================== */
00260 
00261 #endif /* #ifdef _WIN32 */
00262 

Generated on Mon Jul 9 20:34:02 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2