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
21using namespace std;
22
23namespace 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
58 void PvlFormatPds::init() {
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
void init()
Clears all PvlFormatPds specific data.
A single keyword-value pair.
Definition PvlKeyword.h:87
QString name() const
Returns the keyword name.
Definition PvlKeyword.h:103
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
BigInt toBigInt(const QString &string)
Global function to convert from a string to a "big" integer.
Definition IString.cpp:115
long long int BigInt
Big int.
Definition Constants.h:49
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149
Namespace for the standard library.