Loading [MathJax]/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
PvlFormat.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "IException.h"
8 #include "IString.h"
9 #include "Message.h"
10 #include "FileName.h"
11 #include "PvlKeyword.h"
12 #include "TextFile.h"
13 #include "Pvl.h"
14 #include "PvlFormat.h"
15 
16 using namespace std;
17 
18 namespace Isis {
19 
20  /*
21  * Constructs an empty PvlFormat
22  */
23  PvlFormat::PvlFormat() {
24  init();
25  }
26 
27 
28  /*
29  * Constructs a PvlFormat using the file name to ingest as the keyword to type
30  * mapping. This is provided as a convience for child objects. The map is not
31  * used for output of PvlKeywords in Normal Isis format.
32  *
33  * @param file A file name with keyword=type. Where KEYWORD is the name of a
34  * keyword in this PvlKeyword and TYPE is one of [QString | integer | float ]
35  */
36  PvlFormat::PvlFormat(const QString &file) {
37  init();
38  add(file);
39  }
40 
41 
42  /*
43  * Constructs a PvlFormat using the specified pre populated Pvl map of keyword
44  * name (QString) vs keyword type (KeywordType).
45  *
46  * @param keywordType A Pvl with keyword=type. Where keyword is the name of a
47  * keyword in a PvlKeyword and type is one of [QString | integer | float ]
48  */
49  PvlFormat::PvlFormat(Pvl &keywordType) {
50  init();
51  add(keywordType);
52  }
53 
54 
56  void PvlFormat::init() {
57  m_keywordMap.clear();
58  m_keywordMapFile.clear();
59  m_charLimit = 80;
60  }
61 
62 
63  /*
64  * Add the contents of a file to the keyword type mapping. The file should
65  * contain KEYWORD=TYPE (one per line), where TYPE is one of the QStrings
66  * KeywordType can convert.
67  */
68  void PvlFormat::add(const QString &file) {
69  m_keywordMapFile = file;
70 
71  // Open the file and internalize it into the Pvl map
72  try {
73  Pvl pvl(file);
74  add(pvl);
75  }
76  catch(IException &e) {
77  QString msg;
78  msg += "Unable to open or read keyword to type mapping file [";
79  msg += file + "]";
80  throw IException(e, IException::Programmer, msg, _FILEINFO_);
81  }
82  }
83 
84 
85  /*
86  * Add the contents of a Pvl to the keyword type mapping. The pvl should
87  * contain KEYWORD=TYPE, where TYPE is one of the QStrings KeywordType can
88  * convert.
89  */
90  void PvlFormat::add(Pvl &pvl) {
91  for(int i = 0; i < pvl.keywords(); ++i) {
92  PvlKeyword &key = pvl[i];
93  QString name = key.name().toUpper();
94  QString type = key[0].toUpper();
95  PvlKeyword newKey(name, type);
96  for(int j = 1; j < key.size(); ++j) newKey.addValue(key[j]);
97  // Make sure we don't duplicate Keys
98  if (m_keywordMap.hasKeyword(name)) {
99  m_keywordMap.deleteKeyword(name);
100  }
101  m_keywordMap.addKeyword(newKey);
102  }
103  }
104 
105 
106  /*
107  * Returns the type of the keyword from the supplied map if any
108  *
109  * @param keyword The PvlKeyword to have its type returned
110  */
111  KeywordType PvlFormat::type(const PvlKeyword &keyword) {
112  QString name = keyword.name().toUpper();
113  if(m_keywordMap.hasKeyword(name)) {
114  PvlKeyword &key = m_keywordMap.findKeyword(name);
115  return toKeywordType(key[0]);
116  }
117  return NoTypeKeyword;
118  }
119 
120 
121  /*
122  * Returns the number of digits of accuracy (right of decimal place) this
123  * keyword should be output with
124  *
125  * @param keyword The PvlKeyword the accuracy is need for
126  * @return The number of decimal places to be output. If this number is not
127  * available in keyword map return -1.
128  */
129  int PvlFormat::accuracy(const PvlKeyword &keyword) {
130  QString name = keyword.name().toUpper();
131  if(m_keywordMap.hasKeyword(name)) {
132  PvlKeyword &key = m_keywordMap.findKeyword(name);
133  if(key.size() > 1) {
134  return toInt(key[1]);
135  }
136  }
137  return -1;
138  }
139 
140 
141  /*
142  * Returns the keyword name and value(s) formatted in "Normal" Isis format
143  *
144  * @param keyword The PvlKeyword to be formatted
145  * @param num Use the ith value of the keyword
146  */
147  QString PvlFormat::formatValue(const PvlKeyword &keyword, int num) {
148 
149  QString val;
150  val.clear();
151 
152  // Find out if the units are the same for all values
153  bool singleUnit = isSingleUnit(keyword);
154 
155  // Create a Null value if the value index is greater than the number of values
156  if(num >= keyword.size()) {
157  return "Null";
158  }
159 
160  // Create a Null value if the requested index is an empty QString
161  if(keyword[num].size() == 0) {
162  val += "Null";
163  }
164  else {
165  val += keyword[num];
166  }
167 
168  val = addQuotes(val);
169 
170  // If it is an array start it off with a paren
171  if((keyword.size() > 1) && (num == 0)) {
172  val = "(" + val;
173  }
174 
175  // Add the units to this value
176  if((!singleUnit) && (keyword.unit(num).size() > 0)) {
177  val += " <" + keyword.unit(num) + ">";
178  }
179 
180  // Add a comma for arrays
181  if(num != keyword.size() - 1) {
182  val += ", ";
183  }
184  // If it is an array close it off
185  else if(keyword.size() > 1) {
186  val += ")";
187  }
188 
189  // Add the units to the end if all values have the same units
190  if((singleUnit) && (num == keyword.size() - 1) &&
191  (keyword.unit(num).size() > 0)) {
192  val += " <" + keyword.unit(num) + ">";
193  }
194 
195  return val;
196  }
197 
198 
199  /*
200  * Format the name of the container
201  *
202  * @param keyword The PvlContainer being closed.
203  */
204  QString PvlFormat::formatName(const PvlKeyword &keyword) {
205  return keyword.name();
206  }
207 
208 
209  /*
210  * Format the end of a container
211  *
212  * @param name The text used to signify the end of a container
213  * @param keyword The PvlContainer being closed.
214  */
215  QString PvlFormat::formatEnd(const QString name,
216  const PvlKeyword &keyword) {
217  return "End_" + formatName(keyword);
218  }
219 
220 
221  /*
222  * Add single or double quotes around a value if necessary. The Isis definition
223  * of when quotes are necessary is used.
224  *
225  * @param value The PvlKeyword value to be quoted if necessary.
226  */
227  QString PvlFormat::addQuotes(const QString value) {
228  QString val = value;
229 
230  bool needQuotes = false;
231 
232  // find out if we need quotes and what kind of quotes might already exist
233  char existingQuoteType = '\0';
234  for (int pos = 0; !needQuotes && pos < val.size(); pos++) {
235  // check for values indicating we need quotes, if we have a sequence
236  // it should already be properly quoted...
237  if (pos == 0) {
238  if (val[pos] == '(' || val[pos] == '{') {
239  // Find closing
240  int closePos = -1;
241  if (val[pos] == '(') {
242  closePos = val.indexOf(')');
243  }
244  if (val[pos] == '{') {
245  closePos = val.indexOf('}');
246  }
247 
248  // If no closing paren or brace or If closing paren/brace not at end of value
249  if (closePos == -1 || closePos != val.size() - 1) {
250  needQuotes = true;
251  }
252  else {
253  break;
254  }
255  }
256  }
257 
258  if (val[pos] == ' ' || val[pos] == '(' ||
259  val[pos] == '(' || val[pos] == ')' ||
260  val[pos] == '{' || val[pos] == '}' ||
261  val[pos] == ',' || val[pos] == '=') {
262  needQuotes = true;
263  }
264 
265  if (pos == val.size() - 1 && val[pos] == '-') {
266  needQuotes = true;
267  }
268 
269  // remember if we are a quote, what quote type we are
270  if (existingQuoteType == '\0') {
271  if (val[pos] == '"') {
272  existingQuoteType = '"';
273  }
274  else if (val[pos] == '\'') {
275  existingQuoteType = '\'';
276  }
277  }
278  else {
279  // make sure we dont have mixing of our outside quote type
280  if (val[pos] == '"' || val[pos] == '\'') {
281  val[pos] = existingQuoteType;
282  }
283  }
284  }
285 
286  // figure out what kind of quotes we want to add
287  char quoteValue = '"';
288 
289  if(existingQuoteType == '"') {
290  quoteValue = '\'';
291  }
292 
293  if(needQuotes) {
294  val = quoteValue + val + quoteValue;
295  }
296 
297  return val;
298  }
299 
300 
307  bool PvlFormat::isSingleUnit(const PvlKeyword &keyword) {
308 
309  // See if the units are all the same
310  bool singleUnit = true;
311  for(int i = 0; i < keyword.size(); i ++) {
312  if(!keyword.stringEqual(keyword.unit(i), keyword.unit(0))) {
313  singleUnit = false;
314  }
315  }
316 
317  return singleUnit;
318  }
319 }
320 
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::KeywordType
KeywordType
The different types of keywords that can be formatted.
Definition: PvlFormat.h:19
Isis::toInt
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:93
Isis::toKeywordType
KeywordType toKeywordType(const QString type)
Convert a string representing a type of keyword to the corresponding enumeration.
Definition: PvlFormat.h:38
std
Namespace for the standard library.
Isis::PvlKeyword::size
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:125
Isis::PvlKeyword::unit
QString unit(const int index=0) const
Returns the units of measurement of the element of the array of values for the object at the specifie...
Definition: PvlKeyword.cpp:357
Isis::PvlKeyword::stringEqual
static bool stringEqual(const QString &string1, const QString &string2)
Checks to see if two QStrings are equal.
Definition: PvlKeyword.cpp:535
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the USGS Astrogeology Discussion Board
To report a bug, or suggest a feature go to: ISIS Github
File Modified: 07/13/2023 15:17:07