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