USGS

Isis 3.0 Object Programmers' Reference

Home

Blob.cpp

Go to the documentation of this file.
00001 
00024 #include <fstream>
00025 #include <sstream>
00026 #include <cstring>
00027 #include "Blob.h"
00028 #include "Pvl.h"
00029 #include "Filename.h"
00030 #include "iException.h"
00031 #include "iException.h"
00032 #include "iException.h"
00033 #include "Message.h"
00034 
00035 using namespace std;
00036 namespace Isis {
00043   Blob::Blob (const std::string &name, const std::string &type) {
00044     p_blobName = name;
00045     p_buffer = NULL;
00046     p_labelFile = "";
00047     p_nbytes = 0;
00048     p_type = type;
00049 
00050     p_blobPvl.SetName(p_type);
00051     p_blobPvl += Isis::PvlKeyword("Name",p_blobName);
00052     p_blobPvl += Isis::PvlKeyword("StartByte",0);
00053     p_blobPvl += Isis::PvlKeyword("Bytes",0);
00054   }
00055 
00064   Blob::Blob (const std::string &name, const std::string &type, const std::string &file) {
00065     p_blobName = name;
00066     p_buffer = NULL;
00067     p_nbytes = 0;
00068     p_type = type;
00069     p_labelFile = Filename(file).Expanded();
00070 
00071     Read(file);
00072   }
00073 
00079   Blob::Blob (const Blob& other) {
00080     p_blobPvl = other.p_blobPvl;
00081     p_blobName = other.p_blobName;
00082     p_startByte = other.p_startByte;
00083     p_nbytes = other.p_nbytes;
00084     p_type = other.p_type;
00085     p_detached = other.p_detached;
00086     p_labelFile = other.p_labelFile;
00087 
00088     p_buffer = NULL;
00089 
00090     if(other.p_buffer) {
00091       p_buffer = new char[p_nbytes];
00092 
00093       for(int i = 0; i < p_nbytes; i++) {
00094         p_buffer[i] = other.p_buffer[i];
00095       }
00096     }
00097   }
00098 
00100   Blob::~Blob() {
00101     if (p_buffer != NULL) delete [] p_buffer;
00102   }
00103 
00111   Blob &Blob::operator=(const Blob &other) {
00112     p_blobPvl = other.p_blobPvl;
00113     p_blobName = other.p_blobName;
00114     p_startByte = other.p_startByte;
00115     p_nbytes = other.p_nbytes;
00116     p_type = other.p_type;
00117     p_detached = other.p_detached;
00118     p_labelFile = other.p_labelFile;
00119 
00120     p_buffer = NULL;
00121 
00122     if(other.p_buffer) {
00123       p_buffer = new char[p_nbytes];
00124 
00125       for(int i = 0; i < p_nbytes; i++) {
00126         p_buffer[i] = other.p_buffer[i];
00127       }
00128     }
00129 
00130     return *this;
00131   }
00132 
00141   void Blob::Read (const std::string &file) {
00142     // Expand the filename
00143     string temp(Filename(file).Expanded());
00144 
00145     // Open the file
00146     fstream istm;
00147     istm.open(temp.c_str(),std::ios::in);
00148     if (!istm) {
00149       string message = Isis::Message::FileOpen(temp);
00150       throw Isis::iException::Message(Isis::iException::Io,message,_FILEINFO_);
00151     }
00152 
00153     // Get the pvl
00154     try {
00155       Isis::Pvl pvl;
00156       try {
00157         istm >> pvl;
00158       }
00159       catch (Isis::iException &e) {
00160         istm.close();
00161         string msg = "Invalid " + p_type + " label format";
00162         throw Isis::iException::Message(Isis::iException::Pvl,msg,_FILEINFO_);
00163       }
00164 
00165       // Check pvl and read from the stream
00166       Read(pvl,istm);
00167     }
00168     catch (Isis::iException &e) {
00169       istm.close();
00170       string msg = "Unable to open " + p_type + " [" + p_blobName +
00171                    "] in file [" + temp + "]";
00172       throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00173     }
00174 
00175     istm.close();
00176   }
00177 
00178   // Read blob from an open file (probably a cube)
00179   void Blob::Read (Isis::Pvl &pvl, std::fstream &istm) {
00180     try {
00181       Find(pvl);
00182       ReadInit();
00183       if (p_detached != "") {
00184         fstream dstm;
00185         dstm.open(p_detached.c_str(),std::ios::in);
00186         if (!dstm) {
00187           string message = Isis::Message::FileOpen(p_detached);
00188           throw Isis::iException::Message(Isis::iException::Io,message,_FILEINFO_);
00189         }
00190         ReadData(dstm);
00191       }
00192       else {
00193         ReadData(istm);
00194       }
00195     }
00196     catch (Isis::iException &e) {
00197       string msg = "Unable to read " + p_type + " [" + p_blobName + "]";
00198       throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00199     }
00200   }
00201 
00202   // Search PVL for the desire blob
00203   void Blob::Find (Isis::Pvl &pvl) {
00204     bool found = false;
00205     try {
00206       // Search for the blob name
00207       Isis::iString blobName = p_blobName;
00208       blobName.UpCase();
00209       for (int o=0; o<pvl.Objects(); o++) {
00210         Isis::PvlObject &obj = pvl.Object(o);
00211         if (obj.IsNamed(p_type)) {
00212           Isis::iString curName = (string) obj["Name"];
00213           curName.UpCase();
00214           if (blobName == curName) {
00215             p_blobPvl = obj;
00216             found = true;
00217             break;
00218           }
00219           else {
00220             if (p_type == "OriginalLabel" && curName == "ORIGINALLABEL") {
00221               p_blobPvl = obj;
00222               found = true;
00223               break;
00224             }
00225           }     
00226         }
00227       }
00228     }
00229     catch (Isis::iException &e) {
00230       string msg = "Invalid " + p_type + " label format";
00231       throw Isis::iException::Message(Isis::iException::Pvl,msg,_FILEINFO_);
00232     }
00233 
00234     // Did we find it?
00235     if (!found) {
00236       string msg = "Unable to find " + p_type + " [" + p_blobName + "]";
00237       throw Isis::iException::Message(Isis::iException::Programmer,msg,_FILEINFO_);
00238     }
00239 
00240     // Ok the blob exists so we need to prep for reading the binary data
00241     try {
00242       p_startByte = p_blobPvl["StartByte"];
00243       p_nbytes = p_blobPvl["Bytes"];
00244       p_detached = "";
00245       if (p_blobPvl.HasKeyword("^"+p_type)) {
00246         string path = "";
00247         if (p_labelFile != "") {
00248           path = Filename(p_labelFile).Path() + "/";
00249         }
00250         p_detached = path + (std::string) p_blobPvl["^"+p_type];
00251         p_blobPvl.DeleteKeyword("^"+p_type);
00252       }
00253     }
00254     catch (Isis::iException &e) {
00255       string msg = "Invalid " + p_type + " label format";
00256       throw Isis::iException::Message(Isis::iException::Pvl,msg,_FILEINFO_);
00257     }
00258   }
00259 
00267   void Blob::ReadData (std::fstream &stream) {
00268     // Read the binary data
00269     if (p_buffer != NULL) delete [] p_buffer;
00270     p_buffer = new char[p_nbytes];
00271 
00272     streampos sbyte = p_startByte - 1;
00273     stream.seekg(sbyte,std::ios::beg);
00274     if (!stream.good()) {
00275       string msg = "Error preparing to read data from " + p_type +
00276                     " [" + p_blobName + "]";
00277       throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00278     }
00279 
00280     stream.read(p_buffer,p_nbytes);
00281     if (!stream.good()) {
00282       string msg = "Error reading data from " + p_type + " [" + p_blobName + "]";
00283       throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00284     }
00285   }
00286 
00296   void Blob::Write(const std::string &file) {
00297     // Determine the size of the label and write it out
00298     try {
00299       WriteInit();
00300       Isis::Pvl pvl;
00301       pvl.AddObject(p_blobPvl);
00302       ostringstream os;
00303       os << pvl << endl;
00304       os.seekp(0,std::ios::end);
00305       Isis::BigInt nbytes = (Isis::BigInt) os.tellp() + (Isis::BigInt) 64;
00306       p_startByte = nbytes + 1 + 1; // 1-based;
00307       pvl.FindObject(p_type)["StartByte"] = p_startByte;
00308       pvl.FindObject(p_type)["Bytes"] = p_nbytes;
00309       pvl.Write(file);
00310 
00311       // Prepare and write the binary data
00312       fstream stream;
00313       ios::openmode flags = std::ios::in | std::ios::binary | std::ios::out;
00314       stream.open(file.c_str(),flags);
00315       if (!stream) {
00316         string message = "Unable to open [" + file + "]";
00317         throw Isis::iException::Message(Isis::iException::Io,message,_FILEINFO_);
00318       }
00319 
00320       streampos sbyte = p_startByte - 1;
00321       stream.seekp(sbyte,std::ios::beg);
00322       if (!stream.good()) {
00323         stream.close();
00324         string msg = "Error preparing to write data to " +
00325                      p_type + " [" + p_blobName + "]";
00326         throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00327       }
00328 
00329       WriteData(stream);
00330       stream.close();
00331     }
00332     catch (Isis::iException &e) {
00333       string msg = "Unable to create " + p_type + " file [" + file + "]";
00334       throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00335     }
00336   }
00337 
00345   void Blob::Write(Isis::Pvl &pvl, std::fstream &stm,
00346                    const std::string &detachedFilename) {
00347     // Handle 64-bit I/O
00348     WriteInit();
00349 
00350     // Find out where they wanted to write the blob
00351     streampos sbyte = stm.tellp();
00352     sbyte += 1;
00353 
00354     // Find out where the end-of-file is
00355     stm.seekp(0,std::ios::end);
00356     streampos eofbyte = stm.tellp();
00357     eofbyte += 1;
00358 
00359     // Handle detached blobs
00360     if (detachedFilename != "") {
00361       p_blobPvl += Isis::PvlKeyword("^"+p_type,detachedFilename);
00362     }
00363 
00364     // See if the blob is already in the file
00365     p_blobPvl["StartByte"] = (Isis::BigInt) sbyte;
00366     p_blobPvl["Bytes"] = p_nbytes;
00367 
00368     bool found = false;
00369     for (int i=0; i<pvl.Objects(); i++) {
00370       if (pvl.Object(i).Name() == p_blobPvl.Name()) {
00371         PvlObject &obj = pvl.Object(i);
00372         if ((string) obj["Name"] == (string) p_blobPvl["Name"]) {
00373           found = true;
00374 
00375           Isis::BigInt oldSbyte = obj["StartByte"];
00376           int oldNbytes = (int) obj["Bytes"];
00377 
00378           // Does it fit in the old space
00379           if (p_nbytes <= oldNbytes) {
00380             p_blobPvl["StartByte"] = obj["StartByte"];
00381             sbyte = oldSbyte;
00382           }
00383 
00384           // Was the old space at the end of the file
00385           else if (((oldSbyte + oldNbytes) == eofbyte) &&
00386                    (eofbyte >= sbyte)) {
00387             p_blobPvl["StartByte"] = obj["StartByte"];
00388             sbyte = oldSbyte;
00389           }
00390 
00391           // Put it at the requested position/end of the file
00392           else {
00393             // Leave this here for clarity
00394           }
00395 
00396           obj = p_blobPvl;
00397         }
00398       }
00399     }
00400 
00401     // Didn't find the same blob so add it to the labels
00402     if (!found) {
00403       pvl.AddObject(p_blobPvl);
00404     }
00405 
00406     stm.seekp((Isis::BigInt) sbyte-(Isis::BigInt)1);
00407     WriteData(stm);
00408 
00409     // Handle detached blobs
00410     if (detachedFilename != "") {
00411       p_blobPvl.DeleteKeyword("^"+p_type);
00412     }
00413   }
00414 
00422   void Blob::WriteData(std::fstream &stream) {
00423     stream.write(p_buffer,p_nbytes);
00424     if (!stream.good()) {
00425       string msg = "Error writing data to " + p_type + " [" + p_blobName + "]";
00426       throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
00427     }
00428   }
00429 
00437   bool IsBlob(Isis::PvlObject &obj) {
00438     if (obj.IsNamed("TABLE")) return true;
00439     return false;
00440   }
00441 } // end namespace isis
00442