USGS

Isis 3.0 Object Programmers' Reference

Home

Blob.cpp
Go to the documentation of this file.
1 
23 #include "Blob.h"
24 
25 #include <cstring>
26 #include <fstream>
27 #include <sstream>
28 
29 #include <QDebug>
30 
31 #include "FileName.h"
32 #include "IException.h"
33 #include "Message.h"
34 #include "Pvl.h"
35 
36 using namespace std;
37 namespace Isis {
44  Blob::Blob(const QString &name, const QString &type) {
45  p_blobName = name;
46  p_buffer = NULL;
47  p_labelFile = "";
48  p_nbytes = 0;
49  p_type = type;
50 
51  p_blobPvl.setName(p_type);
52  p_blobPvl += PvlKeyword("Name", p_blobName);
53  p_blobPvl += PvlKeyword("StartByte", "0");
54  p_blobPvl += PvlKeyword("Bytes", "0");
55  }
56 
65  Blob::Blob(const QString &name, const QString &type,
66  const QString &file) {
67  p_blobName = name;
68  p_buffer = NULL;
69  p_nbytes = 0;
70  p_type = type;
71  p_labelFile = FileName(file).expanded();
72 
73  Read(file);
74  }
75 
81  Blob::Blob(const Blob &other) {
82  p_blobPvl = other.p_blobPvl;
83  p_blobName = other.p_blobName;
84  p_startByte = other.p_startByte;
85  p_nbytes = other.p_nbytes;
86  p_type = other.p_type;
87  p_detached = other.p_detached;
88  p_labelFile = other.p_labelFile;
89 
90  p_buffer = NULL;
91 
92  if (other.p_buffer) {
93  p_buffer = new char[p_nbytes];
94 
95  for (int i = 0; i < p_nbytes; i++) {
96  p_buffer[i] = other.p_buffer[i];
97  }
98  }
99  }
100 
108  Blob &Blob::operator=(const Blob &other) {
109  p_blobPvl = other.p_blobPvl;
110  p_blobName = other.p_blobName;
111  p_startByte = other.p_startByte;
112  p_nbytes = other.p_nbytes;
113  p_type = other.p_type;
114  p_detached = other.p_detached;
115  p_labelFile = other.p_labelFile;
116 
117  p_buffer = NULL;
118 
119  if (other.p_buffer) {
120  p_buffer = new char[p_nbytes];
121 
122  for (int i = 0; i < p_nbytes; i++) {
123  p_buffer[i] = other.p_buffer[i];
124  }
125  }
126 
127  return *this;
128  }
129 
131  Blob::~Blob() {
132  if (p_buffer != NULL) delete [] p_buffer;
133  }
134 
140  QString Blob::Type() const {
141  return p_type;
142  }
143 
149  QString Blob::Name() const {
150  return p_blobName;
151  }
152 
158  int Blob::Size() const {
159  return p_nbytes;
160  }
161 
167  PvlObject &Blob::Label() {
168  return p_blobPvl;
169  }
170 
179  void Blob::Find(const Pvl &pvl) {
180  bool found = false;
181  try {
182  // Search for the blob name
183  QString blobName = p_blobName.toUpper();
184  for (int o = 0; o < pvl.objects(); o++) {
185  const PvlObject &obj = pvl.object(o);
186  if (obj.isNamed(p_type)) {
187  QString curName = obj["Name"];
188  curName = curName.toUpper();
189  if (blobName == curName) {
190  p_blobPvl = obj;
191  found = true;
192  break;
193  }
194  else {
195  if (p_type == "OriginalLabel" && curName == "ORIGINALLABEL") {
196  p_blobPvl = obj;
197  found = true;
198  break;
199  }
200  }
201  }
202  }
203  }
204  catch (IException &e) {
205  QString msg = "Invalid " + p_type + " label format";
206  throw IException(e, IException::Unknown, msg, _FILEINFO_);
207  }
208 
209  // Did we find it?
210  if (!found) {
211  QString msg = "Unable to find " + p_type + " [" + p_blobName + "]";
212  throw IException(IException::Programmer, msg, _FILEINFO_);
213  }
214 
215  // Ok the blob exists so we need to prep for reading the binary data
216  try {
217  p_startByte = p_blobPvl["StartByte"];
218  p_nbytes = p_blobPvl["Bytes"];
219  p_detached = "";
220  if (p_blobPvl.hasKeyword("^" + p_type)) {
221  QString path = "";
222  if (p_labelFile != "") {
223  path = FileName(p_labelFile).path() + "/";
224  }
225  p_detached = path + (QString) p_blobPvl["^"+p_type];
226  p_blobPvl.deleteKeyword("^" + p_type);
227  }
228  }
229  catch (IException &e) {
230  QString msg = "Invalid " + p_type + " label format";
231  throw IException(e, IException::Unknown, msg, _FILEINFO_);
232  }
233  }
234 
243  void Blob::Read(const QString &file) {
244  // Expand the filename
245  QString temp(FileName(file).expanded());
246 
247  // Get the pvl
248  Pvl pvl;
249  try {
250  pvl.read(temp);
251  }
252  catch (IException &e) {
253  QString msg = "Invalid " + p_type + " label format";
254  throw IException(e, IException::Unknown, msg, _FILEINFO_);
255  }
256 
257  Read(file, pvl);
258  }
259 
268  void Blob::Read(const QString &file, const Pvl &pvlLabels) {
269 
270  // Expand the filename
271  QString temp(FileName(file).expanded());
272 
273  // Open the file
274  fstream istm;
275  istm.open(temp.toAscii().data(), std::ios::in);
276  if (!istm) {
277  QString message = Message::FileOpen(temp);
278  throw IException(IException::Io, message, _FILEINFO_);
279  }
280 
281  try {
282  // Check pvl and read from the stream
283  Read(pvlLabels, istm);
284  }
285  catch (IException &e) {
286  istm.close();
287  QString msg = "Unable to open " + p_type + " [" + p_blobName +
288  "] in file [" + temp + "]";
289  throw IException(e, IException::Io, msg, _FILEINFO_);
290  }
291 
292  istm.close();
293  }
294 
303  void Blob::Read(const Pvl &pvl, std::istream &istm) {
304  try {
305  Find(pvl);
306  ReadInit();
307  if (p_detached != "") {
308  fstream dstm;
309  dstm.open(p_detached.toAscii().data(), std::ios::in);
310  if (!dstm) {
311  QString message = Message::FileOpen(p_detached);
312  throw IException(IException::Io, message, _FILEINFO_);
313  }
314  ReadData(dstm);
315  }
316  else {
317  ReadData(istm);
318  }
319  }
320  catch (IException &e) {
321  QString msg = "Unable to read " + p_type + " [" + p_blobName + "]";
322  throw IException(e, IException::Io, msg, _FILEINFO_);
323  }
324  }
325 
330  void Blob::ReadInit(){
331  }
332 
340  void Blob::ReadData(std::istream &stream) {
341  // Read the binary data
342  if (p_buffer != NULL) delete [] p_buffer;
343  p_buffer = new char[p_nbytes];
344 
345  streampos sbyte = p_startByte - 1;
346  stream.seekg(sbyte, std::ios::beg);
347  if (!stream.good()) {
348  QString msg = "Error preparing to read data from " + p_type +
349  " [" + p_blobName + "]";
350  throw IException(IException::Io, msg, _FILEINFO_);
351  }
352 
353  stream.read(p_buffer, p_nbytes);
354  if (!stream.good()) {
355  QString msg = "Error reading data from " + p_type + " [" + p_blobName + "]";
356  throw IException(IException::Io, msg, _FILEINFO_);
357  }
358  }
359 
369  void Blob::Write(const QString &file) {
370  // Determine the size of the label and write it out
371  try {
372  WriteInit();
373  Pvl pvl;
374  pvl.addObject(p_blobPvl);
375  ostringstream os;
376  os << pvl << endl;
377  os.seekp(0, std::ios::end);
378  BigInt nbytes = (BigInt) os.tellp() + (BigInt) 64;
379  p_startByte = nbytes + 1 + 1; // 1-based;
380  pvl.findObject(p_type)["StartByte"] = toString(p_startByte);
381  pvl.findObject(p_type)["Bytes"] = toString(p_nbytes);
382  pvl.write(file);
383 
384  // Prepare and write the binary data
385  fstream stream;
386  ios::openmode flags = std::ios::in | std::ios::binary | std::ios::out;
387  stream.open(file.toAscii().data(), flags);
388  if (!stream) {
389  QString message = "Unable to open [" + file + "]";
390  throw IException(IException::Io, message, _FILEINFO_);
391  }
392 
393  streampos sbyte = p_startByte - 1;
394  stream.seekp(sbyte, std::ios::beg);
395  if (!stream.good()) {
396  stream.close();
397  QString msg = "Error preparing to write data to " +
398  p_type + " [" + p_blobName + "]";
399  throw IException(IException::Io, msg, _FILEINFO_);
400  }
401 
402  WriteData(stream);
403  stream.close();
404  }
405  catch (IException &e) {
406  QString msg = "Unable to create " + p_type + " file [" + file + "]";
407  throw IException(e, IException::Io, msg, _FILEINFO_);
408  }
409  }
410 
418  void Blob::Write(Pvl &pvl, std::fstream &stm,
419  const QString &detachedFileName) {
420  // Handle 64-bit I/O
421  WriteInit();
422 
423  // Find out where they wanted to write the blob
424  streampos sbyte = stm.tellp();
425  sbyte += 1;
426 
427  // Find out where the end-of-file is
428  stm.seekp(0, std::ios::end);
429  streampos eofbyte = stm.tellp();
430  eofbyte += 1;
431 
432  // Handle detached blobs
433  if (detachedFileName != "") {
434  p_blobPvl += PvlKeyword("^" + p_type, detachedFileName);
435  }
436 
437  // See if the blob is already in the file
438  p_blobPvl["StartByte"] = toString((BigInt)sbyte);
439  p_blobPvl["Bytes"] = toString(p_nbytes);
440 
441  bool found = false;
442  for (int i = 0; i < pvl.objects(); i++) {
443  if (pvl.object(i).name() == p_blobPvl.name()) {
444  PvlObject &obj = pvl.object(i);
445  if ((QString)obj["Name"] == (QString)p_blobPvl["Name"]) {
446  found = true;
447 
448  BigInt oldSbyte = obj["StartByte"];
449  int oldNbytes = (int) obj["Bytes"];
450 
451  // Does it fit in the old space
452  if (p_nbytes <= oldNbytes) {
453  p_blobPvl["StartByte"] = obj["StartByte"];
454  sbyte = oldSbyte;
455  }
456 
457  // Was the old space at the end of the file
458  else if (((oldSbyte + oldNbytes) == eofbyte) &&
459  (eofbyte >= sbyte)) {
460  p_blobPvl["StartByte"] = obj["StartByte"];
461  sbyte = oldSbyte;
462  }
463 
464  // Put it at the requested position/end of the file
465  else {
466  // Leave this here for clarity
467  }
468 
469  obj = p_blobPvl;
470  }
471  }
472  }
473 
474  // Didn't find the same blob so add it to the labels
475  if (!found) {
476  pvl.addObject(p_blobPvl);
477  }
478 
479  stm.seekp((BigInt) sbyte - (BigInt)1);
480  WriteData(stm);
481 
482  // Handle detached blobs
483  if (detachedFileName != "") {
484  p_blobPvl.deleteKeyword("^" + p_type);
485  }
486  }
487 
492  void Blob::WriteInit(){
493  }
494 
502  void Blob::WriteData(std::fstream &stream) {
503  stream.write(p_buffer, p_nbytes);
504  if (!stream.good()) {
505  QString msg = "Error writing data to " + p_type + " [" + p_blobName + "]";
506  throw IException(IException::Io, msg, _FILEINFO_);
507  }
508  }
509 
510 
518  bool IsBlob(PvlObject &obj) {
519  if (obj.isNamed("TABLE")) return true;
520  return false;
521  }
522 } // end namespace isis
523