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       typedef std::vector<std::string>::const_iterator DelimIter;
00102       
00103       const std::vector<std::string>& delimiterVector = pathDelimiters();
00104       std::string::size_type delimiterIndex = std::string::npos;
00105 
00106       DelimIter delimIter = delimiterVector.begin();
00107       while(delimIter != delimiterVector.end()) {
00108         delimiterIndex = std::min(delimiterIndex, path.rfind(*delimIter));
00109         ++delimIter;
00110       }
00111       if(delimiterIndex == std::string::npos) {
00112         return std::make_pair(std::string(""), path);
00113       }
00114       if(delimiterIndex == path.size() - 1) {
00115         return std::make_pair(path, std::string(""));
00116       }
00117       return std::make_pair(
00118         path.substr(0, delimiterIndex + 1),
00119         path.substr(delimiterIndex + 1, std::string::npos));
00120     }
00121     
00122   } // namespace portability
00123 
00124 } // namespace dlr
00125 
00126 /* ===================== End common code ===================== */
00127 
00128 
00129 #ifdef _WIN32
00130 
00131 /* ===================== Windows code ===================== */
00132 
00133 // Anonymous namespace for stuff local to this file.
00134 namespace dlr {
00135 
00136   namespace portability {
00137 
00138     // Initialize on first use to avoid static initialization order fiasco.
00139     const std::string& pathDelimiter() {
00140       static std::string delimiter = "\\";
00141       return delimiter;
00142     }
00143 
00144 
00145     // Initialize on first use to avoid static initialization order fiasco.
00146     const std::vector<std::string>& pathDelimiters() {
00147       static bool needsInit = true;
00148       static std::vector<std::string> delimiterVector;
00149       if(needsInit) {
00150         delimiterVector.push_back("\\");
00151         delimiterVector.push_back("/");
00152         needsInit = false;
00153       }
00154       return delimiterVector;
00155     }
00156 
00157     
00158     // Initialize on first use to avoid static initialization order fiasco.
00159     const std::string& extensionDelimiter() {
00160       static std::string delimiter = ".";
00161       return delimiter;
00162     }
00163 
00164 
00165     // Returns the names of the entries in the specified directory, in
00166     // no particular order.
00167     std::vector<std::string>
00168     listDirectory(const std::string& directoryName, bool fullPath)
00169     {
00170       std::vector<std::string> listing;
00171       std::string fileNameGlob = joinPath(directoryName, "*");
00172       WIN32_FIND_DATA findData;
00173       HANDLE handle = FindFirstFile(fileNameGlob.c_str(), &findData); 
00174       if (handle == INVALID_HANDLE_VALUE) { 
00175         return listing;
00176       } 
00177       while(1) {
00178         listing.push_back(std::string(findData.cFileName));
00179         if (!FindNextFile(handle, &findData)) {
00180           if (GetLastError() == ERROR_NO_MORE_FILES) {
00181             break;
00182           }
00183           std::ostringstream message;
00184           message << "Problem reading file names from " << directoryName;
00185           DLR_THROW(dlr::IOException, "listDirectory()",
00186                     message.str().c_str());
00187         }
00188       }
00189       if (!FindClose(handle)) { 
00190         std::ostringstream message;
00191         message << "Problem closing search handle for " << directoryName;
00192         DLR_THROW(dlr::IOException, "listDirectory()",
00193                   message.str().c_str());
00194       }
00195     
00196       if(fullPath) {
00197         // std::transform(listing.begin(), listing.end(), listing.begin(),
00198         //                std::bind1st(std::ptr_fun(joinPath), directoryName));
00199         typedef PointerToBinaryFunctionRA<std::string, std::string, std::string>
00200           functorType;
00201         std::transform(listing.begin(), listing.end(), listing.begin(),
00202                        std::bind1st(functorType(joinPath), directoryName));
00203       }
00204       return listing;
00205     }
00206   
00207   } // namespace portability
00208   
00209 } // namespace dlr
00210 
00211 /* ===================== End Windows code ===================== */
00212 
00213 #else /* #ifdef _WIN32 */
00214 
00215 /* ===================== Linux code ===================== */
00216 
00217 namespace dlr {
00218 
00219   namespace portability {
00220 
00221     // Initialize on first use to avoid static initialization order fiasco.
00222     const std::string& pathDelimiter() {
00223       static std::string delimiter = "/";
00224       return delimiter;
00225     }
00226 
00227   
00228     // Initialize on first use to avoid static initialization order fiasco.
00229     const std::vector<std::string>& pathDelimiters() {
00230       bool needsInit = true;
00231       static std::vector<std::string> delimiterVector;
00232       if(needsInit) {
00233         delimiterVector.push_back("/");
00234         needsInit = false;
00235       }
00236       return delimiterVector;
00237     }
00238 
00239     
00240     // Initialize on first use to avoid static initialization order fiasco.
00241     const std::string& extensionDelimiter() {
00242       static std::string delimiter = ".";
00243       return delimiter;
00244     }
00245 
00246 
00247     // Returns the names of the entries in the specified directory, in
00248     // no particular order.
00249     std::vector<std::string>
00250     listDirectory(const std::string& directoryName, bool fullPath)
00251     {
00252       std::vector<std::string> listing;
00253 
00254       DIR* directoryPtr = opendir(directoryName.c_str());
00255       if(directoryPtr == 0) {
00256         std::ostringstream message;
00257         char charBuffer[1024];
00258         if(strerror_r(errno, charBuffer, 1024) == 0) {
00259           charBuffer[1023] = '\0';
00260           message << charBuffer;
00261         } else {
00262           message << "Unknown error opening directory";
00263         }
00264         message << ": " << directoryName << std::endl;
00265         DLR_THROW(IOException, "listDirectory()", message.str().c_str());
00266       }
00267       try {
00268         while(1) {
00269           struct dirent* directoryEntryPtr = readdir(directoryPtr);
00270           if(directoryEntryPtr == 0) {
00271             // NULL return value indicates no more entries.
00272             // Can also indicate a bat directory stream, but we just
00273             // checked that above.
00274             break;
00275           }
00276           listing.push_back(std::string(directoryEntryPtr->d_name));
00277         }
00278       } catch(...) {
00279         closedir(directoryPtr);
00280         throw;
00281       }
00282       closedir(directoryPtr);
00283       
00284       if(fullPath) {
00285         // std::transform(listing.begin(), listing.end(), listing.begin(),
00286         //                std::bind1st(std::ptr_fun(joinPath), directoryName));
00287         typedef PointerToBinaryFunctionRA<std::string, std::string, std::string>
00288           functorType;
00289         std::transform(listing.begin(), listing.end(), listing.begin(),
00290                        std::bind1st(functorType(joinPath), directoryName));
00291       }
00292       return listing;
00293     }
00294 
00295   } // namespace portability
00296 
00297 } // namespace dlr
00298 
00299 /* ===================== End Linux code ===================== */
00300 
00301 #endif /* #ifdef _WIN32 */
00302 

Generated on Wed Nov 25 00:03:49 2009 for dlrPortability Utility Library by  doxygen 1.5.8