USGS

Isis 3.0 Object Programmers' Reference

Home

Filename.cpp

Go to the documentation of this file.
00001 
00023 #include <cstdlib>
00024 #include <fstream>
00025 #include <iostream>
00026 
00027 #include "Preference.h"
00028 #include "iString.h"
00029 #include "iException.h"
00030 #include "Filename.h"
00031 
00032 using namespace std;
00033 namespace Isis {
00034 
00036   Filename::Filename () {
00037     p_original.clear();
00038   }
00039 
00046   Filename::Filename (const std::string &file)
00047       : QFileInfo () {
00048     p_original = file;
00049     QFileInfo::setFile ((iString)Expand (file));
00050   }
00051 
00062   Filename::Filename (const std::string &name, const std::string &extension) {
00063     Temporary (name, extension);
00064   }
00065 
00067   Filename::~Filename () {}
00068 
00075   void Filename::operator=(const std::string &file) {
00076     p_original = file;
00077     QFileInfo::setFile ((iString)Expand (file));
00078   }
00079 
00086   void Filename::operator=(const char *file) {
00087     p_original = file;
00088     QFileInfo::setFile ((iString)Expand (file));
00089   }
00090 
00104   std::string Filename::Path() const {
00105     return QFileInfo::absolutePath().toStdString();
00106   }
00107 
00116   std::string Filename::Basename() const {
00117     if (QFileInfo::suffix().length() == 0) {
00118       return QFileInfo::baseName().toStdString();
00119     }
00120     else {
00121       return QFileInfo::completeBaseName().toStdString();
00122     }
00123   }
00124 
00131   std::string Filename::Name() const {
00132     return QFileInfo::fileName().toStdString();
00133   }
00134 
00140   std::string Filename::Extension () const {
00141     return QFileInfo::suffix().toStdString();
00142   }
00143 
00151   std::string Filename::Expanded () const {
00152     return QFileInfo::absoluteFilePath().toStdString();
00153   }
00154 
00160   bool Filename::Exists () {
00161     return QFileInfo::exists();
00162   }
00163 
00167   std::string Filename::OriginalPath() const {
00168     QFileInfo fi(p_original.c_str());
00169     return fi.path().toStdString();
00170   }
00171 
00182   void Filename::AddExtension (const std::string &ext) {
00183     // Don't modify the extension if it is already there
00184     if (Extension() == ext) return;
00185 
00186     // Add the argument as an extension to the current filename
00187     if (ext.length() > 0) {
00188       QFileInfo::setFile (iString(Expanded() + "." + ext));
00189     }
00190   }
00191 
00195   void Filename::RemoveExtension () {
00196     QFileInfo::setFile (iString(this->Path() + "/" + this->Basename()));
00197   }
00198 
00211   void Filename::HighestVersion (){
00212 
00213     CheckVersion();
00214 
00215     int highestVersion = -1;
00216     Isis::iString highestVersionStr;
00217 
00218     // Get the path of the current file and make sure it exists
00219     QDir dir((QString)(iString)Path());
00220     if (!dir.exists()) {
00221       string msg = "The path [" + Path() + "] does not exist";
00222       throw Isis::iException::Message(Isis::iException::Io,msg, _FILEINFO_);
00223     }
00224 
00225     // Find the beginning and end of the "?"s in the versioned filename
00226     unsigned int start = Name().find_first_of("?");
00227     unsigned int end = Name().find_last_of("?");
00228     unsigned int charsAfterVersion = Name().length() - end - 1;
00229 
00230 
00231     // Loop through all files in the dir and see if they match our name
00232     for (unsigned int indx=0; indx < dir.count(); indx++) {
00233 
00234       string file = dir[indx].toStdString();
00235       bool leftSide = file.substr(0, start) == Name().substr(0, start);
00236       bool rightSide = ((int)file.length()-(int)charsAfterVersion) >= 0;
00237       if (rightSide) {
00238         rightSide = rightSide &&
00239         (file.substr(file.length()-charsAfterVersion) == Name().substr(end+1));
00240       }
00241 
00242       if (leftSide && rightSide) {
00243 
00244         Isis::iString version = file.substr(start, file.length()-charsAfterVersion-start);
00245 
00246         if ((version.length() > 0) &&
00247             (version.find_first_not_of("0123456789") == string::npos) &&
00248             (version.ToInteger() > highestVersion)) {
00249           highestVersion = version.ToInteger();
00250           highestVersionStr = version;
00251         }
00252       }
00253     }
00254 
00255     // Make sure we got a version number
00256     if (highestVersion == -1) {
00257       string msg = "No versions available for file [" + Expanded() + "]";
00258       throw Isis::iException::Message(Isis::iException::Programmer,msg, _FILEINFO_);
00259     }
00260 
00261     string temp = Path() + "/" + Name().substr(0, start) +
00262                   highestVersionStr + Name().substr(end+1);
00263     QFileInfo::setFile(temp.c_str());
00264   }
00265 
00281   void Filename::NewVersion (){
00282 
00283     CheckVersion();
00284 
00285     // Get the path of the current file and make sure it exists
00286     QDir dir((QString)(iString)Path());
00287     if (!dir.exists()) {
00288       string msg = "The path [" + Path() + "] does not exist";
00289       throw Isis::iException::Message(Isis::iException::Io,msg, _FILEINFO_);
00290     }
00291 
00292     // Find the beginning and end of the "?"s in the versioned filename
00293     unsigned int start = Name().find_first_of("?");
00294     unsigned int end = Name().find_last_of("?");
00295     unsigned int charsAfterVersion = Name().length() - end - 1;
00296 
00297     int highestVersion = 0;
00298     // Loop through all files in the dir and see if they match our name
00299     for (unsigned int indx=0; indx < dir.count(); indx++) {
00300 
00301       string file = dir[indx].toStdString();
00302       bool leftSide = file.substr(0, start) == Name().substr(0, start);
00303       bool rightSide = ((int)file.length()-(int)charsAfterVersion) >= 0;
00304       if (rightSide) {
00305         rightSide = rightSide &&
00306         (file.substr(file.length()-charsAfterVersion) == Name().substr(end+1));
00307       }
00308 
00309       if (leftSide && rightSide) {
00310 
00311         Isis::iString version = file.substr(start, file.length()-charsAfterVersion-start);
00312 
00313         if ((version.length() > 0) &&
00314             (version.find_first_not_of("0123456789") == string::npos) &&
00315             (version.ToInteger() > highestVersion)) {
00316           highestVersion = version.ToInteger();
00317         }
00318       }
00319     }
00320     //create a string with the new version number
00321     Isis::iString newVersion = ++highestVersion;
00322 
00323 
00324 
00325     //pad each extra "?" with a 0. This maintains the length of the Filename
00326     //so that "file.???.ext" will be "file.001.ext" instead of "file.1.ext"
00327     int zeroesNeeded = end - start - newVersion.length();
00328     for (int i = 0 ; i <= zeroesNeeded; i++){
00329       newVersion = "0" + newVersion;
00330     }
00331 
00332     string temp = Path() + "/" + Name().substr(0, start) +
00333                   newVersion + Name().substr(end+1);
00334     QFileInfo::setFile(temp.c_str());
00335   }
00336 
00342   void Filename::MakeDirectory() {
00343 
00344     QDir dir;
00345     if (!dir.mkdir(iString(Expanded()))) {
00346       string msg = "Unable to create directory [" + Expanded() + "]";
00347       throw Isis::iException::Message(Isis::iException::Programmer,
00348                                       msg, _FILEINFO_);
00349     }
00350 
00351   }
00352 
00367   void Filename::Temporary (const std::string &name, const std::string &extension) {
00368     string tempDir;
00369     tempDir.clear();
00370     // If the IsisPreference exists use it otherwise just use name as is
00371     if (!(name.at(0)=='/') && Isis::Preference::Preferences().HasGroup("DataDirectory")) {
00372       Isis::PvlGroup &dataDir = Isis::Preference::Preferences().FindGroup("DataDirectory");
00373       if (dataDir.HasKeyword("Temporary")) {
00374         tempDir = (string) dataDir["Temporary"];
00375       }
00376     }
00377 
00378     // Start off by appending "100000" to the name if that file exists
00379     // increment it and try again
00380     int add = 100000;
00381     string tfile;
00382 
00383     do {
00384       Isis::iString num(add);
00385       tfile = tempDir + "/" + name + num + "." + extension;
00386       QFileInfo f(tfile.c_str());
00387       if (f.exists()) {
00388         add++;
00389       }
00390       else {
00391         p_original = tfile;
00392         QFileInfo::setFile (tfile.c_str());
00393         return;
00394       }
00395     } while (add < 1000000);
00396 
00397     string msg = "No temporary files available for [" + name + extension + "]";
00398     throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00399 
00400   }
00401 
00410   string Filename::Expand (const std::string &file) {
00411 
00412     // Setup an index for searching strings
00413     std::string::size_type pos, pos2;
00414 
00415     // Work with a tempory copy
00416     string temp = file;
00417 
00418     // Strip off any cube attributes
00419     if ((pos = temp.find("+")) != std::string::npos) temp.erase(pos);
00420 
00421 
00422     // Expand any $xxxxx into ISIS preferences and environment variables
00423     // *** NOTE *** This may be very operating system dependent
00424     string prefVar;
00425     string var;
00426     pos = 0;
00427 
00428     // Loop while there are any "$" at the current position or after
00429     // Some "$" might be skipped if no translation can be found
00430     while ((pos = temp.find("$", pos)) != std::string::npos) {
00431       pos2 = temp.find ("/", pos);
00432       var = temp.substr(pos+1, pos2-pos-1);
00433       string value;
00434       value.clear();
00435 
00436       // Find the corresponding Isis Preference if one exists
00437       if (Isis::Preference::Preferences().HasGroup("DataDirectory")) {
00438         Isis::PvlGroup &dataDir = Isis::Preference::Preferences().FindGroup("DataDirectory");
00439         if (dataDir.HasKeyword(var)) {
00440           value = (string) dataDir[var];
00441         }
00442       }
00443 
00444       // Find the corresponding environment variable if one exists
00445       if (value.length() == 0) {
00446         char *val;
00447         val = getenv(var.c_str());
00448         if (val != NULL) value = val;
00449       }
00450 
00451       // Replace the $xxxx with the pref/env, but don't move
00452       // the pointer. We may have replaced one $ for another.
00453       // Note: May need to put a test for circular replaces in here
00454       if (value.length() > 0) {
00455         temp.replace (pos, pos2-pos, value);
00456       }
00457       // No pref or env was available so ignore this "$" and move on
00458       else {
00459         pos++;
00460       }
00461     }
00462     return temp;
00463   }
00464 
00472   void Filename::CheckVersion () const {
00473 
00474     // Find the series of "?"
00475     string name = Expanded();
00476 
00477     std::string::size_type start = name.find_first_of("?");
00478     std::string::size_type end = name.find_last_of("?");
00479 
00480     // Make sure there was at least one "?" for a version number
00481     if (start == string::npos || end == string::npos) {
00482       string msg = "Filename [" + Expanded() +
00483                    "] does not contain a version sequence";
00484       throw Isis::iException::Message(Isis::iException::Programmer,msg, _FILEINFO_);
00485     }
00486 
00487     // Make sure all chars between start and end are "?"
00488     for (unsigned int pos=start; pos<=end; ++pos) {
00489       if (name[pos] != '?') {
00490         string msg = "Only one version sequence is allowed per filename [" +
00491                      Expanded() + "]";
00492         throw Isis::iException::Message(Isis::iException::Programmer,msg, _FILEINFO_);
00493       }
00494     }
00495   }
00496 } // end namespace Isis