Isis 3 Programmer Reference
PvlFormatPds.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include <sstream>
8 #include <iomanip>
9 
10 #include <QDebug>
11 
12 #include "IException.h"
13 #include "Message.h"
14 #include "IString.h"
15 #include "FileName.h"
16 #include "Constants.h"
17 #include "TextFile.h"
18 
19 #include "PvlFormatPds.h"
20 
21 using namespace std;
22 
23 namespace Isis {
24 
25  /*
26  * Constructs an empty PvlFormatPds
27  */
28  PvlFormatPds::PvlFormatPds() {
29  init();
30  }
31 
32 
33  /*
34  * Constructs a PvlFormatPds using the file name to ingest to fill the keyword
35  * to type map.
36  *
37  * @param file A file name with keyword=type. Where KEYWORD is the name of a
38  * keyword and TYPE is one of [string | integer | float | ...]
39  */
40  PvlFormatPds::PvlFormatPds(const QString &file) : PvlFormat(file) {
41  init();
42  }
43 
44 
45  /*
46  * Constructs a PvlFormatPds using the specified pre populated map of keyword name
47  * (QString) vs keyword type (KeywordType).
48  *
49  * @param keywordType A map with keyword, type. Where keyword is the name of a
50  * keyword in a PvlKeyword and type is one of [string | integer | float ]
51  */
52  PvlFormatPds::PvlFormatPds(Pvl &keywordType) : PvlFormat(keywordType) {
53  init();
54  }
55 
56 
59  }
60 
61 
62  /*
63  * Returns the keyword value formatted in "PDS" format
64  *
65  * @param keyword The PvlKeyword to be formatted
66  * @param num Use the ith value of the keyword
67  */
68  QString PvlFormatPds::formatValue(const PvlKeyword &keyword, int num) {
69 
70  QString name = keyword.name().toUpper();
71  if(name == "OBJECT" || (name == "GROUP")) {
72  QString val = (QString)keyword;
73  return val.toUpper();
74  }
75 
76  // Find out what type this keyword is
77  KeywordType keyType = type(keyword);
78 
79  switch(keyType) {
80  case StringKeyword:
81  return formatString(keyword, num);
82  break;
83 
84  case RealKeyword:
85  return formatReal(keyword, num, accuracy(keyword));
86  break;
87 
88  case IntegerKeyword:
89  return formatInteger(keyword, num, accuracy(keyword));
90  break;
91 
92  case HexKeyword:
93  return formatHex(keyword, num, accuracy(keyword));
94  break;
95 
96  case BinaryKeyword:
97  return formatBinary(keyword, num, accuracy(keyword));
98  break;
99 
100  case EnumKeyword:
101  return formatEnum(keyword, num);
102  break;
103 
104  case BoolKeyword:
105  return formatBool(keyword, num);
106  break;
107 
108  case NoTypeKeyword:
109  default:
110  return formatUnknown(keyword, num);
111  break;
112  }
113  return formatUnknown(keyword, num);
114  }
115 
116 
117  /*
118  * Returns the keyword value formatted as a "PDS" string
119  *
120  * @param keyword The PvlKeyword to be formatted
121  * @param num Use the ith value of the keyword
122  * @internal
123  * @history 2009-09-15 Jeannie Walldren - Moved the call to AddQuotes()
124  * inside the else-statement since
125  * the if portion of the code already
126  * adds quotes automatically
127  */
128  QString PvlFormatPds::formatString(const PvlKeyword &keyword, int num) {
129 
130  QString val;
131  bool singleUnit = false;
132 
133  // Create a Null value if the value index is greater than the number of values
134  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
135  return "NULL";
136  }
137 
138  // Handle PDS special values "N/A" "NULL" "UNK"
139  QString tmp = keyword[num][0].toUpper();
140  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
141  val += "\"" + tmp + "\"";
142  }
143  else {
144  val += keyword[num];
145  val = addQuotes(val);
146  }
147 
148 
149  // If it is an array start it off with a paren
150  if((keyword.size() > 1) && (num == 0)) {
151  val = "(" + val;
152  }
153 
154  // Add the units to this value
155  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
156  QString unit = keyword.unit(num);
157  // For now PDS units are case sensitive, so we should not UpCase them
158  // unit.UpCase();
159  val += " <" + unit + ">";
160  }
161 
162  // Add a comma for arrays
163  if(num != keyword.size() - 1) {
164  val += ", ";
165  }
166  // If it is an array, close it off
167  else if(keyword.size() > 1) {
168  val += ")";
169  }
170 
171  // Add the units to the end if all values have the same units
172  if((singleUnit) && (num == keyword.size() - 1) &&
173  (keyword.unit(num).size() > 0)) {
174  QString unit = keyword.unit(num);
175  // For now PDS units are case sensitive, so we should not UpCase them
176  // unit.UpCase();
177  val += " <" + unit + ">";
178  }
179 
180  return val;
181  }
182 
183 
184  /*
185  * Returns the keyword value formatted as a "PDS" real number
186  *
187  * @param keyword The PvlKeyword to be formatted
188  * @param num Use the ith value of the keyword
189  */
190  QString PvlFormatPds::formatReal(const PvlKeyword &keyword, int num,
191  int places) {
192 
193  QString val;
194  val.clear();
195  bool singleUnit = false;
196 
197  // Create a Null value if the value index is greater than the number of values
198  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
199  return "NULL";
200  }
201 
202  // If it is an array start it off with a paren
203  if((keyword.size() > 1) && (num == 0)) {
204  val += "(";
205  }
206 
207  // Handle PDS special values "N/A" "NULL" "UNK"
208  QString tmp = keyword[num].toUpper();
209  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
210  val += "\"" + tmp + "\"";
211  }
212  else if(places >= 0) {
213  stringstream out;
214  out << setiosflags(ios::fixed) << setprecision(places) << toDouble((QString)keyword[num]);
215  val += out.str().c_str();
216  }
217  else {
218  val += keyword[num];
219  }
220 
221  // Add the units to this value
222  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
223  QString unit = keyword.unit(num);
224  // unit.UpCase();
225  val += " <" + unit + ">";
226  }
227 
228  // Add a comma for arrays
229  if(num != keyword.size() - 1) {
230  val += ", ";
231  }
232  // If it is an array, close it off
233  else if(keyword.size() > 1) {
234  val += ")";
235  }
236 
237  // Add the units to the end if all values have the same units
238  if((singleUnit) && (num == keyword.size() - 1) &&
239  (keyword.unit(num).size() > 0)) {
240  QString unit = keyword.unit(num);
241  // unit.UpCase();
242  val += " <" + unit + ">";
243  }
244 
245  return val;
246  }
247 
248 
249  /*
250  * Returns the keyword value formatted as a "PDS" enumeration
251  *
252  * @param keyword The PvlKeyword to be formatted
253  * @param num Use the ith value of the keyword
254  */
255  QString PvlFormatPds::formatEnum(const PvlKeyword &keyword, int num) {
256 
257  QString val;
258  val.clear();
259  bool singleUnit = false;
260 
261  // Create a Null value if the value index is greater than the number of values
262  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
263  return "NULL";
264  }
265 
266  // If it is an array start it off with a paren
267  if((keyword.size() > 1) && (num == 0)) {
268  val += "(";
269  }
270 
271  // Handle PDS special values "N/A" "NULL" "UNK"
272  QString tmp = keyword[num].toUpper();
273  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
274  val += "\"" + tmp + "\"";
275  }
276  else {
277  val += keyword[num];
278  }
279 
280  // Add the units to this value
281  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
282  QString unit = keyword.unit(num);
283  // unit.UpCase();
284  val += " <" + unit + ">";
285  }
286 
287  // Add a comma for arrays
288  if(num != keyword.size() - 1) {
289  val += ", ";
290  }
291  // If it is an array, close it off
292  else if(keyword.size() > 1) {
293  val += ")";
294  }
295 
296  // Add the units to the end if all values have the same units
297  if((singleUnit) && (num == keyword.size() - 1) &&
298  (keyword.unit(num).size() > 0)) {
299  QString unit = keyword.unit(num);
300  // unit.UpCase();
301  val += " <" + unit + ">";
302  }
303 
304  return val;
305  }
306 
307 
308  /*
309  * Returns the keyword value formatted without any knowledge of its type
310  *
311  * @param keyword The PvlKeyword to be formatted
312  * @param num Use the ith value of the keyword
313  * @internal
314  * @history 2009-09-15 Jeannie Walldren - Moved the call to AddQuotes()
315  * inside the else-statement since
316  * the if portion of the code already
317  * adds quotes automatically
318  */
319  QString PvlFormatPds::formatUnknown(const PvlKeyword &keyword, int num) {
320 
321  QString val;
322  val.clear();
323  bool singleUnit = false;
324 
325  // Create a Null value if the value index is greater than the number of values
326  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
327  return "NULL";
328  }
329 
330  // Handle PDS special values "N/A" "NULL" "UNK"
331  QString tmp = keyword[num].toUpper();
332  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
333  val += "\"" + tmp + "\"";
334  }
335  else {
336  val += keyword[num];
337  val = PvlFormat::addQuotes(val);
338  }
339 
340 
341  // If it is an array start it off with a paren
342  if((keyword.size() > 1) && (num == 0)) {
343  val = "(" + val;
344  }
345 
346  // Add the units to this value
347  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
348  QString unit = keyword.unit(num);
349  // unit.UpCase();
350  val += " <" + unit + ">";
351  }
352 
353  // Add a comma for arrays
354  if(num != keyword.size() - 1) {
355  val += ", ";
356  }
357  // If it is an array, close it off
358  else if(keyword.size() > 1) {
359  val += ")";
360  }
361 
362  // Add the units to the end if all values have the same units
363  if((singleUnit) && (num == keyword.size() - 1) &&
364  (keyword.unit(num).size() > 0)) {
365  QString unit = keyword.unit(num);
366  // unit.UpCase();
367  val += " <" + unit + ">";
368  }
369 
370  return val;
371  }
372 
373 
374  /*
375  * Returns the keyword value formatted as an integer
376  *
377  * @param keyword The PvlKeyword to be formatted
378  * @param num Use the ith value of the keyword
379  */
380  QString PvlFormatPds::formatInteger(const PvlKeyword &keyword, int num, int bytes) {
381 
382  QString val;
383  val.clear();
384  bool singleUnit = false;
385 
386  // Create a Null value if the value index is greater than the number of values
387  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
388  return "NULL";
389  }
390 
391  // If it is an array start it off with a paren
392  if((keyword.size() > 1) && (num == 0)) {
393  val += "(";
394  }
395 
396  // Handle PDS special values "N/A" "NULL" "UNK"
397  QString tmp = keyword[num].toUpper();
398  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
399  val += "\"" + tmp + "\"";
400  }
401  else {
402  val += keyword[num];
403  }
404 
405  // Add the units to this value
406  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
407  QString unit = keyword.unit(num);
408  // unit.UpCase();
409  val += " <" + unit + ">";
410  }
411 
412  // Add a comma for arrays
413  if(num != keyword.size() - 1) {
414  val += ", ";
415  }
416  // If it is an array, close it off
417  else if(keyword.size() > 1) {
418  val += ")";
419  }
420 
421  // Add the units to the end if all values have the same units
422  if((singleUnit) && (num == keyword.size() - 1) &&
423  (keyword.unit(num).size() > 0)) {
424  QString unit = keyword.unit(num);
425  // unit.UpCase();
426  val += " <" + unit + ">";
427  }
428 
429  return val;
430  }
431 
432 
433  /*
434  * Returns the keyword value formatted as a binary value
435  *
436  * @param keyword The PvlKeyword to be formatted
437  * @param num Use the ith value of the keyword
438  */
439  QString PvlFormatPds::formatBinary(const PvlKeyword &keyword, int num, int bits) {
440 
441  QString val;
442  val.clear();
443  bool singleUnit = false;
444 
445  // Create a Null value if the value index is greater than the number of values
446  stringstream ss;
447  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
448  return "NULL";
449  }
450 
451  // If it is an array start it off with a paren
452  if((keyword.size() > 1) && (num == 0)) {
453  val += "(";
454  }
455 
456  // Handle PDS special values "N/A" "NULL" "UNK"
457  QString tmp = keyword[num].toUpper();
458  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
459  val += "\"" + tmp + "\"";
460  }
461  else {
462  tmp.clear();
463  BigInt value = toBigInt((QString)keyword[num]);
464  string binDig = "01";
465  do {
466  tmp = binDig[value % 2] + tmp;
467  value /= 2;
468  }
469  while(value);
470 
471  ss << right << setfill('0') << setw(bits) << tmp;
472  tmp = ss.str().c_str();
473  val += "2#" + tmp + "#";
474  }
475 
476  // Add the units to this value
477  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
478  QString unit = keyword.unit(num);
479  // unit.UpCase();
480  val += " <" + unit + ">";
481  }
482 
483  // Add a comma for arrays
484  if(num != keyword.size() - 1) {
485  val += ", ";
486  }
487  // If it is an array, close it off
488  else if(keyword.size() > 1) {
489  val += ")";
490  }
491 
492  // Add the units to the end if all values have the same units
493  if((singleUnit) && (num == keyword.size() - 1) &&
494  (keyword.unit(num).size() > 0)) {
495  QString unit = keyword.unit(num);
496  // unit.UpCase();
497  val += " <" + unit + ">";
498  }
499 
500  return val;
501  }
502 
503 
504  /*
505  * Returns the keyword value formatted as a hexidecimal value
506  *
507  * @param keyword The PvlKeyword to be formatted
508  * @param num Use the ith value of the keyword
509  */
510 
511 
512  QString PvlFormatPds::formatHex(const PvlKeyword &keyword, int num, int bytes) {
513 
514  QString val;
515  val.clear();
516  bool singleUnit = false;
517 
518  // Create a Null value if the value index is greater than the number of values
519  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
520  return "NULL";
521  }
522 
523  // If it is an array start it off with a paren
524  if((keyword.size() > 1) && (num == 0)) {
525  val += "(";
526  }
527 
528  // Handle PDS special values "N/A" "NULL" "UNK"
529  QString tmp = keyword[num].toUpper();
530  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
531  val += "\"" + tmp + "\"";
532  }
533  else {
534  stringstream ss;
535  if(bytes == 2) {
536  ss << hex << (unsigned short int)toInt((QString)keyword[num]);
537  }
538  else if(bytes == 4) {
539  ss << hex << (unsigned int)toInt((QString)keyword[num]);
540  }
541  else {
542  ss << hex << toBigInt((QString)keyword[num]);
543  }
544  QString h = ss.str().c_str();
545  h = h.toUpper();
546  val += "16#" + h + "#";
547  }
548 
549  // Add the units to this value
550  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
551  QString unit = keyword.unit(num);
552  // unit.UpCase();
553  val += " <" + unit + ">";
554  }
555 
556  // Add a comma for arrays
557  if(num != keyword.size() - 1) {
558  val += ", ";
559  }
560  // If it is an array, close it off
561  else if(keyword.size() > 1) {
562  val += ")";
563  }
564 
565  // Add the units to the end if all values have the same units
566  if((singleUnit) && (num == keyword.size() - 1) &&
567  (keyword.unit(num).size() > 0)) {
568  QString unit = keyword.unit(num);
569  // unit.UpCase();
570  val += " <" + unit + ">";
571  }
572 
573  return val;
574  }
575 
576 
577  /*
578  * Returns the keyword value formatted as a boolean value
579  *
580  * @param keyword The PvlKeyword to be formatted
581  * @param num Use the ith value of the keyword
582  */
583  QString PvlFormatPds::formatBool(const PvlKeyword &keyword, int num) {
584 
585  QString val;
586  val.clear();
587 
588  // Create a Null value if the value index is greater than the number of values
589  if((num >= keyword.size()) || (keyword[num].size() == 0)) {
590  return "NULL";
591  }
592 
593  // If it is an array start it off with a paren
594  if((keyword.size() > 1) && (num == 0)) {
595  val += "(";
596  }
597 
598  // Handle PDS special values "N/A" "NULL" "UNK"
599  QString tmp = keyword[num];
600  tmp = tmp.toUpper();
601  if((tmp == "N/A") || (tmp == "NULL") || (tmp == "UNK")) {
602  val += "\"" + tmp + "\"";
603  }
604  else {
605  val += keyword[num];
606  }
607 
608  // Add a comma for arrays
609  if(num != keyword.size() - 1) {
610  val += ", ";
611  }
612  // If it is an array, close it off
613  else if(keyword.size() > 1) {
614  val += ")";
615  }
616 
617  return val;
618  }
619 
620 
621 
622 
623  /*
624  * Format the name of this container
625  *
626  * @param keyword The keyword (i.e., the Object or Group)
627  */
628  QString PvlFormatPds::formatName(const PvlKeyword &keyword) {
629  QString text = keyword.name();
630  text = text.toUpper();
631  return text;
632  };
633 
634 
635  /*
636  * Format the end of a group or object
637  *
638  * @param name A string representing the end text.
639  * @param keyword The keyword (i.e., the Object or Group) that is ending
640  */
641  QString PvlFormatPds::formatEnd(const QString name,
642  const PvlKeyword &keyword) {
643  QString left = name.toUpper();
644  left += " = ";
645  QString right = (QString)keyword;
646  right = right.toUpper();
647  return left + right;
648  };
649 
650 
651  /*
652  * Put quotes around the value of a keyword of type string according to PDS
653  * standards. All keywords identified as "string" are quoted for PDS labels.
654  *
655  * @param value The value of a PvlKeyword to be formatted.
656  * @internal
657  * @history 2009-09-15 Jeannie Walldren - Added case to skip add quotes if
658  * the first character of the
659  * string is " or '
660  */
661  QString PvlFormatPds::addQuotes(const QString value) {
662 
663  QString val = value;
664 
665  bool quoteValue = true;
666  bool singleQuoteValue = false;
667  if(val.contains(" ")) {
668  if(val.contains("\"")) {
669  singleQuoteValue = true;
670  quoteValue = false;
671  }
672  }
673 
674  // Turn the quoting back off if this value looks like a sequence
675  // In this case the internal values should already be quoted.
676  if(val[0] == '(') {
677  singleQuoteValue = false;
678  quoteValue = false;
679  }
680  else if(val[0] == '"') {
681  singleQuoteValue = false;
682  quoteValue = false;
683  }
684  else if(val[0] == '\'') {
685  singleQuoteValue = false;
686  quoteValue = false;
687  }
688 
689  if(quoteValue) {
690  val = "\"" + val + "\"";
691  }
692  else if(singleQuoteValue) {
693  val = "'" + val + "'";
694  }
695 
696  return val;
697  }
698 
699 }
700 
Isis::PvlKeyword::name
QString name() const
Returns the keyword name.
Definition: PvlKeyword.h:98
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::KeywordType
KeywordType
The different types of keywords that can be formatted.
Definition: PvlFormat.h:19
Isis::PvlFormatPds::init
void init()
Clears all PvlFormatPds specific data.
Definition: PvlFormatPds.cpp:58
Isis::toBigInt
BigInt toBigInt(const QString &string)
Global function to convert from a string to a "big" integer.
Definition: IString.cpp:115
Isis::toInt
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:93
Isis::BigInt
long long int BigInt
Big int.
Definition: Constants.h:49
Isis::toDouble
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:149
std
Namespace for the standard library.
Isis::PvlFormat::init
void init()
Clears all PvlFormat data.
Definition: PvlFormat.cpp:56
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16