Isis 3 Programmer Reference
Table.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "Table.h"
8 
9 #include <fstream>
10 #include <string>
11 
12 #include "Blob.h"
13 #include "Endian.h"
14 #include "IException.h"
15 #include "TableField.h"
16 
17 using namespace std;
18 namespace Isis {
19 
20  Table::Table(Blob &blob) {
21  initFromBlob(blob);
22  }
23 
24 
43  Table::Table(const QString &tableName, Isis::TableRecord &rec) {
44  p_name = tableName;
45  p_assoc = Table::None;
46  p_label += Isis::PvlKeyword("Records", 0);
47  p_label += Isis::PvlKeyword("ByteOrder", "NULL");
48  for (int f = 0; f < rec.Fields(); f++) {
49  p_label.addGroup(rec[f].pvlGroup());
50  }
51  p_record = rec;
52  }
53 
54 
67  Table::Table(const QString &tableName) {
68  p_name = tableName;
69  p_assoc = Table::None;
70  }
71 
72 
87  Table::Table(const QString &tableName, const QString &file) {
88  Blob blob(tableName, "Table", file);
89  initFromBlob(blob);
90  }
91 
92 
108  Table::Table(const QString &tableName, const QString &file, const Pvl &fileHeader) {
109  Blob blob(tableName, "Table");
110  blob.Read(file, fileHeader);
111  initFromBlob(blob);
112  }
113 
114 
121  Table::Table(const Table &other) {
122  p_name = other.p_name;
123  p_label = other.p_label;
124  p_record = other.p_record;
125  p_records = other.p_records;
126  p_assoc = other.p_assoc;
127  p_swap = other.p_swap;
128 
129  for (unsigned int i = 0; i < other.p_recbufs.size(); i++) {
130  char *data = new char[RecordSize()];
131 
132  for (int j = 0; j < RecordSize(); j++) {
133  data[j] = other.p_recbufs[i][j];
134  }
135 
136  p_recbufs.push_back(data);
137  }
138  }
139 
140 
146  void Table::initFromBlob(Blob &blob) {
147  Clear();
148 
149  p_label = blob.Label();
150 
151  p_name = p_label["Name"][0];
152  p_records = p_label["Records"];
153 
154  Isis::TableRecord rec;
155  for (int g = 0; g < p_label.groups(); g++) {
156  if (p_label.group(g).isNamed("Field")) {
157  Isis::TableField f(p_label.group(g));
158  rec += f;
159  }
160  }
161 
162  p_record = rec;
163 
164  p_assoc = Table::None;
165  if (p_label.hasKeyword("Association")) {
166  QString temp = (QString) p_label["Association"];
167  temp = temp.toUpper();
168  if (temp == "SAMPLES") p_assoc = Table::Samples;
169  if (temp == "LINES") p_assoc = Table::Lines;
170  if (temp == "BANDS") p_assoc = Table::Bands;
171  }
172 
173  // Determine if we need to swap stuff when we read the data
174  Isis::ByteOrder bo = Isis::ByteOrderEnumeration(p_label["ByteOrder"]);
175  p_swap = false;
176  if (Isis::IsLsb() && (bo == Isis::Msb)) p_swap = true;
177  if (Isis::IsMsb() && (bo == Isis::Lsb)) p_swap = true;
178 
179  for (int rec = 0; rec < p_records; rec++) {
180  size_t bufferPos = rec * RecordSize();
181 
182  char *buf = new char[RecordSize()];
183  memcpy(buf, &blob.getBuffer()[bufferPos], RecordSize());
184 
185  if (p_swap) p_record.Swap(buf);
186  p_recbufs.push_back(buf);
187  }
188  }
189 
190 
200  Table &Table::operator=(const Isis::Table &other) {
201  Clear();
202  p_name = other.p_name;
203  p_label = other.p_label;
204  p_record = other.p_record;
205  p_records = other.p_records;
206  p_assoc = other.p_assoc;
207  p_swap = other.p_swap;
208 
209  for (unsigned int i = 0; i < other.p_recbufs.size(); i++) {
210  char *data = new char[RecordSize()];
211 
212  for (int j = 0; j < RecordSize(); j++) {
213  data[j] = other.p_recbufs[i][j];
214  }
215 
216  p_recbufs.push_back(data);
217  }
218 
219  return *this;
220  }
221 
222 
224  Table::~Table() {
225  Clear();
226  }
227 
228 
236  void Table::Write(const QString &file) {
237  Blob blob = toBlob();
238  blob.Write(file);
239  }
240 
241 
247  QString Table::Name() const {
248  return p_name;
249  }
250 
251 
260  PvlObject &Table::Label() {
261  return p_label;
262  }
263 
264 
270  void Table::SetAssociation(const Table::Association assoc) {
271  p_assoc = assoc;
272  }
273 
274 
281  bool Table::IsSampleAssociated() {
282  return (p_assoc == Table::Samples);
283  }
284 
285 
292  bool Table::IsLineAssociated() {
293  return (p_assoc == Table::Lines);
294  }
295 
296 
303  bool Table::IsBandAssociated() {
304  return (p_assoc == Table::Bands);
305  }
306 
307 
313  int Table::Records() const {
314  return p_recbufs.size();
315  }
316 
317 
323  int Table::RecordFields() const {
324  return p_record.Fields();
325  }
326 
327 
333  int Table::RecordSize() const {
334  return p_record.RecordSize();
335  }
336 
337 
345  Isis::TableRecord &Table::operator[](const int index) {
346  p_record.Unpack(p_recbufs[index]);
347  return p_record;
348  }
349 
350 
356  void Table::operator+=(Isis::TableRecord &rec) {
357  if (RecordSize() == 0) {
358  IString msg = "Unable to add records to Isis Table ["
359  + p_name + "]. Bytes per record = [0 bytes].";
360  throw IException(IException::Unknown, msg, _FILEINFO_);
361  }
362 
363  if (RecordSize() != rec.RecordSize()) {
364  QString msg = "Unable to add the given record with size = ["
365  + Isis::toString(rec.RecordSize()) + " bytes] to to Isis Table ["
366  + p_name + "] with record size = ["
367  + Isis::toString(RecordSize()) + " bytes]. Record sizes must match.";
368  throw IException(IException::Unknown, msg, _FILEINFO_);
369  }
370  char *newbuf = new char[RecordSize()];
371  rec.Pack(newbuf);
372  p_recbufs.push_back(newbuf);
373  }
374 
375 
382  void Table::Update(const Isis::TableRecord &rec, const int index) {
383  rec.Pack(p_recbufs[index]);
384  }
385 
386 
392  void Table::Delete(const int index) {
393  vector<char *>::iterator it = p_recbufs.begin();
394  for (int i = 0; i < index; i++, it++);
395  delete [] p_recbufs[index];
396  p_recbufs.erase(it);
397  }
398 
399 
403  void Table::Clear() {
404  for (int i = 0; i < (int)p_recbufs.size(); i++) delete [] p_recbufs[i];
405  p_recbufs.clear();
406  }
407 
408 
414  Blob Table::toBlob() const {
415  Blob tableBlob(Name(), "Table");
416  PvlObject &blobLabel = tableBlob.Label();
417 
418  // Label setup
419  blobLabel += PvlKeyword("Records", Isis::toString(Records()));
420  int nbytes = Records() * RecordSize();
421 
422  if (Isis::IsLsb()) {
423  blobLabel+= PvlKeyword("ByteOrder", Isis::ByteOrderName(Isis::Lsb));
424  }
425  else {
426  blobLabel+= PvlKeyword("ByteOrder", Isis::ByteOrderName(Isis::Msb));
427  }
428 
429  if (p_assoc == Samples) {
430  blobLabel += Isis::PvlKeyword("Association", "Samples");
431  }
432  else if (p_assoc == Lines) {
433  blobLabel += Isis::PvlKeyword("Association", "Lines");
434  }
435  else if (p_assoc == Bands) {
436  blobLabel += Isis::PvlKeyword("Association", "Bands");
437  }
438 
439  for (int i = 0; i < p_label.keywords(); i++) {
440  if (!blobLabel.hasKeyword(p_label[i].name())) {
441  blobLabel += p_label[i];
442  }
443  }
444 
445  for (int i = 0; i < p_label.comments(); i++){
446  blobLabel.addComment(p_label.comment(i));
447  }
448 
449  for (int g = 0; g < p_label.groups(); g++) {
450  blobLabel += p_label.group(g);
451  }
452 
453  // Binary data setup
454  char *buf = new char[nbytes];
455 
456  for (int rec = 0; rec < Records(); rec++) {
457  size_t bufferPos = rec * RecordSize();
458 
459  memcpy(&buf[bufferPos], p_recbufs[rec], RecordSize());
460  }
461 
462  tableBlob.takeData(buf, nbytes);
463 
464  return tableBlob;
465  }
466 
467 
480  QString Table::toString(Table table, QString fieldDelimiter) {
481  QString tableValues;
482  // add the first record with header, the given delimiter, and a new line after each record
483  tableValues += TableRecord::toString(table[0], fieldDelimiter, true, true);
484  // add remaining records without header, the same delimeter, and new line after each record
485  for (int recordIndex = 1; recordIndex < table.Records(); recordIndex++) {
486  tableValues += TableRecord::toString(table[recordIndex], fieldDelimiter);
487  }
488  return tableValues;
489  }
490 
491 }
Isis::TableRecord::Pack
void Pack(char *buf) const
Writes record information into the binary buffer.
Definition: TableRecord.cpp:100
Isis::Blob::takeData
void takeData(char *buffer, int nbytes)
Set the data stored in the BLOB without copying it.
Definition: Blob.cpp:398
Isis::PvlObject::group
PvlGroup & group(const int index)
Return the group at the specified index.
Definition: PvlObject.cpp:452
Isis::PvlObject
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:61
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::IsLsb
bool IsLsb()
Return true if this host is an LSB first machine and false if it is not.
Definition: Endian.h:67
Isis::Table::p_assoc
Association p_assoc
Association Type of the table.
Definition: Table.h:131
Isis::Table::p_label
PvlObject p_label
The label for storing additional information.
Definition: Table.h:135
Isis::TableRecord::Fields
int Fields() const
Returns the number of fields that are currently in the record.
Definition: TableRecord.cpp:78
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::TableRecord
Definition: TableRecord.h:38
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::ByteOrder
ByteOrder
Tests the current architecture for byte order.
Definition: Endian.h:42
Isis::Blob::Write
void Write(const QString &file)
Write the blob data out to a file.
Definition: Blob.cpp:417
Isis::Table::p_records
int p_records
Holds record count read from labels, may differ from the size of p_recbufs.
Definition: Table.h:128
Isis::TableRecord::RecordSize
int RecordSize() const
Returns the number of bytes per record.
Definition: TableRecord.cpp:87
Isis::Blob::Read
void Read(const QString &file, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >())
This method reads Pvl values from a specified file.
Definition: Blob.cpp:255
Isis::IsMsb
bool IsMsb()
Return true if this host is an MSB first machine and false if it is not.
Definition: Endian.h:83
Isis::Blob::getBuffer
char * getBuffer()
Get the internal data buff of the Blob.
Definition: Blob.cpp:546
Isis::Blob::Label
PvlObject & Label()
Accessor method that returns a PvlObject containing the Blob label.
Definition: Blob.cpp:151
Isis::PvlObject::hasKeyword
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
Definition: PvlObject.cpp:236
Isis::Table
Class for storing Table blobs information.
Definition: Table.h:61
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::TableRecord::Unpack
void Unpack(const char *buf)
Reads record information from the binary buffer.
Definition: TableRecord.cpp:152
std
Namespace for the standard library.
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis::Table::p_swap
bool p_swap
Only used for reading.
Definition: Table.h:132
Isis::Table::p_recbufs
std::vector< char * > p_recbufs
Buffers containing record values.
Definition: Table.h:126
Isis::Table::Records
int Records() const
Returns the number of records.
Definition: Table.cpp:313
Isis::Table::p_name
QString p_name
The name of the Table.
Definition: Table.h:134
Isis::Table::p_record
TableRecord p_record
The current table record.
Definition: Table.h:125
Isis::Blob
Definition: Blob.h:51
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::TableField
Class for storing an Isis::Table's field information.
Definition: TableField.h:47