10#include <QRegularExpression>
11#include "PvlKeyword.h"
12#include "IException.h"
16#include "PvlSequence.h"
21using json = nlohmann::json;
68 for (
int i = 0; i < vecValue.size(); i++) {
123 if (
size() == 0)
return true;
124 if (index < 0 || index >= (
int)
m_values.size()) {
141 QString
final =
name.trimmed();
142 if (
final.contains(QRegExp(
"\\s"))) {
143 QString msg =
"[" +
name +
"] is invalid. Keyword name cannot ";
144 msg +=
"contain whitespace.";
154 QByteArray finalAscii =
final.toLatin1();
155 m_name =
new char[finalAscii.size() + 1];
156 strncpy(
m_name, finalAscii.data(),
final.size() + 1);
206 m_units =
new std::vector<QString>();
211 for (
int i = 0; i <
m_values.size(); i++) {
229 while(!found && ++i < (
int)
m_values.size()) {
243 (*m_units)[i] = units;
246 IString msg =
"PvlKeyword::setUnits called with value [" + value +
247 "] which does not exist in this Keyword";
324 if (jsonobj.is_array()) {
325 QString msg =
"Unable to convert " +
name() +
" with nested json array value into PvlKeyword";
328 else if (jsonobj.is_number())
330 value = QString::number(jsonobj.get<
double>(),
'g', 16);
332 else if (jsonobj.is_boolean())
334 value = QString(jsonobj.get<
bool>() ?
"true" :
"false");
336 else if (jsonobj.is_null())
338 value = QString(
"Null");
342 value = QString::fromStdString(jsonobj);
378 PvlKeyword::operator QString()
const {
379 return operator[](0);
396 if (index < 0 || index >= (
int)
m_values.size()) {
398 "for Keyword [" + QString(
m_name) +
"]";
418 if (index < 0 || index >= (
int)
m_values.size()) {
437 if (index < 0 || index >= (
int)
m_units->size()) {
464 else if (
comment.size() == 1) {
492 token = cmt.
Token(
" ");
493 int length = temp.size() + token.size() + 1;
494 while((length < 72) && (token.size() > 0)) {
496 token = cmt.
Token(
" ");
497 length = temp.size() + token.size() + 1;
501 if (token.size() != 0)
addComment(token.c_str());
521 if (index < 0 || index >= (
int)
m_comments->size()) {
537 static bool firstTime =
true;
538 static bool iPVL =
true;
546 if (s ==
"PVL") iPVL =
false;
549 if (iPVL)
return toIPvl(value);
562 bool lastlower =
true;
563 for (
int i = 0; i < value.size(); i++) {
564 if ((lastlower) && (value[i].isUpper())) upcase =
true;
565 if (value[i] ==
'_') {
569 out += value[i].toUpper();
574 out += value[i].toLower();
575 if (value[i].isLower()) lastlower =
true;
589 bool lastlower =
false;
590 for (
int i = 0; i < value.size(); i++) {
591 if ((lastlower) && (value[i].isUpper())) out +=
"_";
592 if (value[i] ==
'_') {
597 out += value[i].toUpper();
598 if (value[i].isLower()) lastlower =
true;
613 const QString &QString2) {
626 if (s1 == s2)
return true;
640 if (index < 0 || index >= (
int)
m_values.size()) {
655 for (
int i = 0; i < seq.
Size(); i++) {
657 for (
int j = 0; j < (int)seq[i].size(); j++) {
658 QString val = seq[i][j];
659 if (val.contains(
" ")) {
660 temp +=
"\"" + val +
"\"";
665 if (j < (
int) seq[i].
size() - 1) temp +=
", ";
689 const QString &textToWrite,
740 QString remainingText = textToWrite;
741 int spaceForText =
format.charLimit() - 1 -
format.formatEOL().length() - startColumn;
746 vector< pair<int, int> > quotedAreas;
750 if (textToWrite.count() > 0 && (textToWrite[0] ==
'(' || textToWrite[0] ==
'"')) {
761 vector< pair<char, char> > quoteStartEnds;
762 quoteStartEnds.push_back(pair<char, char>(
'"',
'"'));
763 quoteStartEnds.push_back(pair<char, char>(
'\'',
'\''));
764 quoteStartEnds.push_back(pair<char, char>(
'<',
'>'));
768 for (
int pos = 0; pos < remainingText.size(); pos++) {
770 if (remainingText[pos] ==
'\n' || remainingText[pos] ==
'\r') {
771 if (pos != remainingText.size() - 1) {
772 remainingText = remainingText.mid(0, pos) +
773 remainingText.mid(pos + 1);
776 remainingText = remainingText.mid(0, pos);
781 if (quoteStart == -1) {
783 remainingText[pos-1] ==
' ' &&
784 remainingText[pos] ==
' ') {
785 remainingText = remainingText.mid(0, pos) +
786 remainingText.mid(pos + 1);
791 for (
unsigned int i = 0;
792 (quoteStart < 0) && i < quoteStartEnds.size();
794 if (quoteStartEnds[i].first == remainingText[pos]) {
804 if (quoteStart != (
int)pos && quoteStart != -1) {
805 for (
unsigned int i = 0; i < quoteStartEnds.size(); i++) {
806 if (quoteStartEnds[i].second == remainingText[pos]) {
807 if (quoteStartEnds[i].first != remainingText[quoteStart]) {
812 quotedAreas.push_back(pair<int, int>(quoteStart, pos));
826 int charsLeft = spaceForText;
827 int printedSoFar = 0;
830 while(!remainingText.isEmpty()) {
832 int lastSpacePosition = charsLeft;
836 if (lastSpacePosition >= (
int)remainingText.length()) {
837 lastSpacePosition = remainingText.length();
844 int excellentSpace = -1;
845 int searchPosition = lastSpacePosition;
846 bool doneSearching =
false;
848 while(!doneSearching) {
849 bool currentPosQuoted =
false;
851 for (
unsigned int i = 0; i < quotedAreas.size(); i++) {
852 if (searchPosition + printedSoFar >= quotedAreas[i].first &&
853 searchPosition + printedSoFar <= quotedAreas[i].second) {
854 currentPosQuoted =
true;
858 if (remainingText[searchPosition] ==
' ') {
859 bool validSpace =
true;
863 if (searchPosition > 0 && remainingText[searchPosition - 1] ==
'-') {
867 if (validSpace && goodSpace < 0) {
868 goodSpace = searchPosition;
874 if (validSpace && !currentPosQuoted) {
875 if ((
int)searchPosition < (
int)(remainingText.size() - 1) &&
876 remainingText[searchPosition+1] !=
'<') {
877 excellentSpace = searchPosition;
882 doneSearching = (excellentSpace >= 0 || searchPosition <= 1);
887 if (excellentSpace > 0) {
888 lastSpacePosition = excellentSpace;
890 else if (goodSpace > 0) {
891 lastSpacePosition = goodSpace;
894 lastSpacePosition = -1;
900 if (lastSpacePosition >= 0) {
901 os << remainingText.mid(0, lastSpacePosition);
903 remainingText = remainingText.mid(lastSpacePosition);
904 printedSoFar += lastSpacePosition;
910 if (remainingText.mid(charsLeft-1, 2) ==
"//") {
911 os << remainingText.mid(0, charsLeft - 2);
913 remainingText = remainingText.mid(charsLeft - 2);
914 printedSoFar += charsLeft - 2;
917 os << remainingText.mid(0, charsLeft - 1);
919 remainingText = remainingText.mid(charsLeft - 1);
920 printedSoFar += charsLeft - 1;
925 if (!remainingText.isEmpty()) {
930 if (remainingText[0] ==
' ') {
931 remainingText = remainingText.mid(1);
936 charsLeft = spaceForText;
950 for (
int space = 0; space < numSpaces; space ++) {
989 QString keywordString;
991 bool keywordDone =
false;
992 bool multiLineComment =
false;
993 bool error = !is.good();
995 while(!error && !keywordDone) {
996 istream::pos_type beforeLine = is.tellg();
1003 if (line.isEmpty() && !is.good()) {
1004 if (keywordString.isEmpty() ||
1005 keywordString[keywordString.size()-1] ==
'\n') {
1008 if (multiLineComment) {
1019 if (!multiLineComment) {
1020 if (line.size() > 0 && line[0] ==
'#') {
1024 if (line.size() > 1 && line[0] ==
'/' &&
1025 (line[1] ==
'*' || line[1] ==
'/')) {
1028 if (line[1] ==
'*') {
1029 multiLineComment =
true;
1030 keywordString += line.mid(0, 2);
1031 line = line.mid(2).trimmed();
1036 if (multiLineComment) {
1039 if (line.contains(
"/*")) {
1040 IString msg =
"Error when reading a pvl: Cannot have ['/*'] inside a "
1041 "multi-line comment";
1045 if (line.contains(
"*/")) {
1046 multiLineComment =
false;
1048 line = line.mid(0, line.indexOf(
"*/")).trimmed() +
" */";
1052 if (line.isEmpty()) {
1057 keywordString += line +
'\n';
1061 else if (keywordString.isEmpty()) {
1062 keywordString = line;
1065 else if (!
comment && keywordString[keywordString.size()-1] ==
'-') {
1066 keywordString = keywordString.mid(0, keywordString.size() - 1) + line;
1070 keywordString +=
" " + line;
1073 if (line[line.size()-1] ==
'-') {
1077 std::vector<QString> keywordComments;
1078 QString keywordName;
1079 std::vector< std::pair<QString, QString> > keywordValues;
1081 bool attemptedRead =
false;
1090 if (is.eof() && !is.bad()) {
1095 is.seekg(beforeLine, ios::beg);
1097 QString msg =
"Unable to read PVL keyword [";
1098 msg += keywordString;
1105 if (attemptedRead) {
1109 if (is.good() && is.peek() ==
'<' && !keywordValues.empty()) {
1116 for (
unsigned int value = 0; value < keywordValues.size(); value++) {
1117 result.
addValue(keywordValues[value].first,
1118 keywordValues[value].second);
1124 if (!attemptedRead) {
1125 error = error || !is.good();
1132 while(keywordString.contains(
'\n')) {
1133 keywordString = keywordString.mid(keywordString.indexOf(
'\n') + 1);
1138 if (keywordString.isEmpty() && !multiLineComment) {
1139 msg =
"PVL input contains no Pvl Keywords";
1141 else if (multiLineComment) {
1142 msg =
"PVL input ends while still in a multi-line comment";
1145 msg =
"The PVL keyword [" + keywordString +
"] does not appear to be";
1146 msg +=
" a valid Pvl Keyword";
1154 while(keywordString.contains(
'\n'))
1155 keywordString = keywordString.mid(keywordString.indexOf(
'\n') + 1);
1159 if (keywordString.isEmpty()) {
1160 msg =
"Error reading PVL keyword";
1163 msg =
"The PVL keyword [" + keywordString +
"] does not appear to be";
1180 for (
unsigned int i = 0; i <
comments.size(); i++) {
1201 std::vector<QString> &keywordComments,
1202 QString &keywordName,
1203 std::vector< std::pair<QString, QString> > &keywordValues) {
1205 keywordComments.clear();
1207 keywordValues.clear();
1210 bool explicitIncomplete =
false;
1219 if (keyword.isEmpty())
return 0;
1238 while(keyword.contains(
"\n")) {
1241 bool noneStripped =
true;
1245 QString keywordStart = keyword.mid(0, 2);
1248 if (keywordStart ==
"/*") {
1249 noneStripped =
false;
1250 bool inComment =
true;
1252 while(inComment && keyword.contains(
"*/")) {
1255 int closePos = keyword.indexOf(
"*/\n");
1257 if (closePos == -1) {
1258 closePos = keyword.indexOf(
"*/") + 2;
1259 keyword = keyword.mid(0, closePos) +
"\n" +
1260 keyword.mid(closePos);
1263 QString
comment = keyword.mid(0, keyword.indexOf(
"\n")).trimmed();
1267 bool needsStart = (
comment.size() < 2);
1268 bool needsStartSpace =
comment.size() < 3;
1270 int commentEndPos =
comment.size() - 2;
1271 bool needsEnd = (commentEndPos < 0);
1272 bool needsEndSpace =
comment.size() < 3;
1278 needsStart = (
comment.mid(0, 2) !=
"/*");
1282 needsEnd = (
comment.mid(commentEndPos, 2) !=
"*/");
1285 if (!needsStartSpace) {
1286 needsStartSpace = (
comment.mid(0, 3) !=
"/* ");
1289 if (!needsEndSpace) {
1290 needsEndSpace = (
comment.mid(commentEndPos - 1, 3) !=
" */");
1296 else if (needsStartSpace) {
1303 else if (needsEndSpace) {
1307 inComment = needsEnd;
1309 keywordComments.push_back(
comment);
1311 if (keyword.contains(
"\n")) {
1312 keyword = keyword.mid(keyword.indexOf(
"\n") + 1).trimmed();
1317 if (keyword.size() >= 2)
1318 keywordStart = keyword.mid(0, 2);
1320 inComment = (keywordStart ==
"/*");
1327 for (
unsigned int index = 0; index < keywordComments.size(); index++) {
1328 QString
comment = keywordComments[index];
1335 for (
unsigned int index = 0; index < keywordComments.size(); index++) {
1336 QString
comment = keywordComments[index];
1338 while(
comment.size() < longest) {
1343 keywordComments[index] =
comment;
1349 for (
unsigned int commentType = 0;
1350 commentType <
sizeof(
comments) /
sizeof(QString);
1353 if (keywordStart.startsWith(
comments[commentType])) {
1356 QString
comment = keyword.mid(0, keyword.indexOf(
"\n"));
1357 keywordComments.push_back(
comment.trimmed());
1359 noneStripped =
false;
1361 if (keyword.contains(
"\n")) {
1362 keyword = keyword.mid(keyword.indexOf(
"\n") + 1).trimmed();
1369 if (noneStripped && keyword.contains(
"/*") &&
1370 keyword.contains(
"*/")) {
1371 QString firstPart = keyword.mid(0, keyword.indexOf(
"\n"));
1372 QString lastPart = keyword.mid(keyword.indexOf(
"\n") + 1);
1374 keyword = firstPart.trimmed() +
" " + lastPart.trimmed();
1375 noneStripped =
false;
1379 QString msg =
"Expected a comment in PVL but found [";
1387 if (keyword.isEmpty()) {
1402 keywordName = readValue(keyword, explicitIncomplete);
1406 if (keyword.isEmpty()) {
1416 bool allowedValueless =
false;
1417 static const std::vector<QString> reservedKeywordNames = {
"OBJECT",
1425 const QString keywordNameUpper = keywordName.toUpper();
1426 for (
const auto &reservedKeywordName : reservedKeywordNames) {
1427 if (keywordNameUpper == reservedKeywordName) {
1428 allowedValueless =
true;
1432 return allowedValueless;
1437 if (keyword[0] !=
'=') {
1438 QString msg =
"Expected an assignment [=] when reading PVL, but found [";
1445 keyword = keyword.mid(1).trimmed();
1447 if (keyword.isEmpty()) {
1452 if (keyword[0] ==
'(' || keyword[0] ==
'{') {
1462 char closingParen = ((keyword[0] ==
'(') ?
')' :
'}');
1463 char wrongClosingParen = ((keyword[0] ==
'(') ?
'}' :
')');
1464 bool closedProperly =
false;
1466 vector< pair<char, char> > extraDelims;
1467 extraDelims.push_back(pair<char, char>(
'(',
')'));
1468 extraDelims.push_back(pair<char, char>(
'{',
'}'));
1472 keyword = keyword.mid(1).trimmed();
1475 if (!keyword.isEmpty() && keyword[0] == closingParen) {
1476 closedProperly =
true;
1482 while(!keyword.isEmpty() && keyword[0] != closingParen) {
1485 bool foundComma =
false;
1488 QString nextItem = readValue(keyword, explicitIncomplete, extraDelims);
1490 if (!keyword.isEmpty() && keyword[0] == wrongClosingParen) {
1492 QString msg =
"Incorrect array close when reading PVL; expected [";
1493 msg += closingParen;
1494 msg +=
"] but found [";
1495 msg += wrongClosingParen;
1496 msg +=
"] in keyword named [";
1503 pair<QString, QString> keywordValue;
1506 keywordValue.first = nextItem;
1510 if (!keyword.isEmpty() && keyword[0] ==
'<') {
1511 QString unitsValue = readValue(keyword, explicitIncomplete);
1512 keywordValue.second = unitsValue;
1516 if (!keyword.isEmpty() && keyword[0] ==
',') {
1518 keyword = keyword.mid(1).trimmed();
1524 if (!foundComma && keyword.isEmpty()) {
1528 bool foundCloseParen = (!keyword.isEmpty() && keyword[0] == closingParen);
1530 if (foundCloseParen) {
1531 closedProperly =
true;
1537 if (foundComma && foundCloseParen) {
1538 QString msg =
"Unexpected close of keyword-value array when reading "
1544 if (!foundComma && !foundCloseParen) {
1546 if (explicitIncomplete)
return false;
1549 QString msg =
"Found extra data after [";
1551 msg +=
"] in array when reading PVL";
1556 keywordValues.push_back(keywordValue);
1559 if (!closedProperly) {
1564 if (!keyword.isEmpty()) {
1565 keyword = keyword.mid(1).trimmed();
1570 if (!keyword.isEmpty() && keyword[0] ==
'<') {
1571 QString units = readValue(keyword, explicitIncomplete);
1572 for (
unsigned int val = 0; val < keywordValues.size(); val++) {
1573 if (keywordValues[val].second.isEmpty()) {
1574 keywordValues[val].second = units;
1588 pair<QString, QString> keywordValue;
1589 keywordValue.first = readValue(keyword, explicitIncomplete);
1591 if (!keyword.isEmpty() && keyword[0] ==
'<') {
1592 keywordValue.second = readValue(keyword, explicitIncomplete);
1595 keywordValues.push_back(keywordValue);
1602 if (explicitIncomplete) {
1609 if (!keyword.isEmpty()) {
1611 if (keyword[0] ==
'#' ||
1612 ((keyword.size() > 1 && keyword[0] ==
'/') &&
1613 (keyword[1] ==
'/' || keyword[1] ==
'*'))) {
1614 keywordComments.push_back(keyword);
1616 if (keyword.size() > 1 && keyword.mid(0, 2) ==
"/*") {
1617 if (keyword.mid(keyword.size() - 2, 2) !=
"*/")
1626 QRegularExpression regex(
"^,");
1627 QRegularExpressionMatch match = regex.match(keyword);
1628 if (!keyword.isEmpty() && match.hasMatch()) {
1629 keywordValues.at(0).first += keyword;
1636 if (!keyword.isEmpty()) {
1637 QString msg =
"Keyword has extraneous data [";
1639 msg +=
"] at the end";
1648 QString PvlKeyword::readValue(QString &keyword,
bool "eProblem) {
1649 std::vector< std::pair<char, char> > otherDelims;
1651 return readValue(keyword, quoteProblem, otherDelims);
1670 QString PvlKeyword::readValue(QString &keyword,
bool "eProblem,
1671 const std::vector< std::pair<char, char> > &
1677 keyword = keyword.trimmed();
1679 if (keyword.isEmpty()) {
1687 bool impliedQuote =
true;
1688 QChar quoteEnd =
' ';
1689 bool keepQuotes =
false;
1691 if (keyword[0] ==
'\'' || keyword[0] ==
'"') {
1692 quoteEnd = keyword[0];
1693 impliedQuote =
false;
1695 else if (keyword[0] ==
'<') {
1697 impliedQuote =
false;
1701 char implicitQuotes[] = {
1711 bool foundImplicitQuote =
false;
1714 while(!foundImplicitQuote && currentPos != keyword.size()) {
1715 for (
unsigned int quote = 0;
1716 quote <
sizeof(implicitQuotes) /
sizeof(char);
1718 if (keyword[currentPos] == implicitQuotes[quote]) {
1719 quoteEnd = implicitQuotes[quote];
1720 foundImplicitQuote =
true;
1724 if (!foundImplicitQuote) {
1730 for (
unsigned int delim = 0; delim < otherDelimiters.size(); delim ++) {
1731 if (keyword[0] == otherDelimiters[delim].first) {
1732 quoteEnd = otherDelimiters[delim].second;
1734 impliedQuote =
false;
1742 if (!impliedQuote) {
1743 startQuote += keyword[0];
1744 keyword = keyword.mid(1);
1748 int quoteEndPos = keyword.indexOf(quoteEnd);
1750 if (quoteEndPos != -1) {
1751 value = keyword.mid(0, quoteEndPos);
1757 if (!impliedQuote) {
1758 keyword = keyword.mid(quoteEndPos + 1);
1761 keyword = keyword.mid(quoteEndPos);
1765 keyword = keyword.trimmed();
1768 value = startQuote + value + quoteEnd;
1775 else if (!impliedQuote) {
1777 keyword = startQuote + keyword;
1778 quoteProblem =
true;
1808 while(is.good() && lineOfData.isEmpty()) {
1812 (!lineOfData.size() || lineOfData[lineOfData.size() - 1] !=
'\n')) {
1813 char next = is.get();
1817 is.seekg(0, ios::end);
1828 if (insideComment &&
1829 lineOfData.size() >= 2 && lineOfData[lineOfData.size() - 2] ==
'*' &&
1830 lineOfData[lineOfData.size() - 1] ==
'/') {
1834 else if (lineOfData.size() >= 2 &&
1835 lineOfData[lineOfData.size() - 2] ==
'/' &&
1836 lineOfData[lineOfData.size() - 1] ==
'*') {
1837 insideComment =
true;
1842 lineOfData = lineOfData.trimmed();
1846 (is.peek() ==
' ' ||
1847 is.peek() ==
'\r' ||
1848 is.peek() ==
'\n')) {
1870 bool removeFormatter =
false;
1871 if (tempFormat == NULL) {
1873 removeFormatter =
true;
1877 for (
int i = 0; i < keyword.
comments(); i++) {
1878 for (
int j = 0; j < keyword.
indent(); j++) os <<
" ";
1879 os << keyword.
comment(i) << tempFormat->formatEOL();
1883 int startColumn = 0;
1884 for (
int i = 0; i < keyword.
indent(); i++) {
1888 QString keyname = tempFormat->formatName(keyword);
1890 startColumn += keyname.length();
1893 for (
int i = 0; i < keyword.
width() - (
int)keyname.size(); ++i) {
1901 if (keyword.
size() == 0) {
1902 os << tempFormat->formatValue(keyword);
1906 QString stringToWrite;
1907 for (
int i = 0; i < keyword.
size(); i ++) {
1908 stringToWrite += tempFormat->formatValue(keyword, i);
1916 if (removeFormatter)
delete tempFormat;
1924 if (
this != &other) {
1977 int iSize = pvlKwrd.
size();
1979 QString sType =
m_values[0].toLower();
1982 if (psValueType.length()) {
1983 psValueType = psValueType.toLower();
1986 double dRangeMin=0, dRangeMax=0;
1987 bool bRange =
false;
1988 bool bValue =
false;
1989 if (pvlKwrdValue != NULL) {
1990 QString sValueName = pvlKwrdValue->
name();
1993 if (sValueName.contains(
"__Range")) {
1994 dRangeMin =
toDouble((*pvlKwrdValue)[0]);
1995 dRangeMax =
toDouble((*pvlKwrdValue)[1]);
1998 else if (sValueName.contains(
"__Value")) {
2004 if (sType ==
"integer") {
2005 for (
int i=0; i<iSize; i++) {
2006 QString sValue = pvlKwrd[i].toLower();
2007 if (sValue !=
"null"){
2010 iValue =
toInt(sValue);
2012 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" expects an Integer value";
2015 if (bRange && (iValue < dRangeMin || iValue > dRangeMax)) {
2016 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" is not in the specified Range";
2020 bool bFound =
false;
2021 for (
int j=0; j<pvlKwrdValue->
size(); j++) {
2022 if (iValue ==
toInt((*pvlKwrdValue)[j])) {
2028 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" has value not in the accepted list";
2033 if (psValueType.length()) {
2034 if ((psValueType ==
"positive" && iValue < 0) || (psValueType ==
"negative" && iValue >= 0) ) {
2035 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" has invalid value";
2045 if (sType ==
"double") {
2046 for (
int i=0; i<iSize; i++) {
2047 QString sValue = pvlKwrd[i].toLower();
2048 if (sValue !=
"null"){
2050 if (bRange && (dValue < dRangeMin || dValue > dRangeMax)) {
2051 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" is not in the specified Range";
2055 bool bFound =
false;
2056 for (
int j=0; j<pvlKwrdValue->
size(); j++) {
2057 if (dValue ==
toDouble((*pvlKwrdValue)[j])) {
2063 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" has value not in the accepted list";
2068 if (psValueType.length()) {
2069 if ((psValueType ==
"positive" && dValue < 0) || (psValueType ==
"negative" && dValue >= 0) ) {
2070 QString sErrMsg =
"\"" +pvlKwrd.
name() +
"\" has invalid value";
2080 if (sType ==
"boolean") {
2081 for (
int i=0; i<iSize; i++) {
2082 QString sValue = pvlKwrd[i].toLower();
2083 if (sValue !=
"null" && sValue !=
"true" && sValue !=
"false"){
2084 QString sErrMsg =
"Wrong Type of value in the Keyword \"" +
name() +
"\" \n";
2092 if (sType ==
"string") {
2093 for (
int i=0; i<iSize; i++) {
2094 QString sValue = pvlKwrd[i].toLower();
2096 bool bValFound =
false;
2097 for (
int i=0; i<pvlKwrdValue->
size(); i++) {
2098 if (sValue == (*pvlKwrdValue)[i].toLower()) {
2104 QString sErrMsg =
"Wrong Type of value in the Keyword \"" +
name() +
"\" \n";
@ Unknown
A type of error that cannot be classified as any of the other error types.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
@ Programmer
This error is for when a programmer made an API call that was illegal.
Adds specific functionality to C++ strings.
IString Remove(const std::string &del)
Remove all instances of any character in the string from the IString.
IString UpCase()
Converst any lower case characters in the object IString with uppercase characters.
IString Token(const IString &separator)
Returns the first token in the IString.
IString ConvertWhiteSpace()
Returns the string with all "new lines", "carriage returns", "tabs", "formfeeds", "vertical tabs" and...
Contains multiple PvlContainers.
A single keyword-value pair.
PvlKeyword()
Constructs a blank PvlKeyword object.
std::vector< QString > * m_comments
The comments for the keyword.
QVarLengthArray< QString, 1 > m_values
The values in the keyword.
const QString & operator[](int index) const
Gets value for this object at specified index.
void setName(QString name)
Sets the keyword name.
void setJsonValue(nlohmann::json jsonobj, QString unit="")
Sets new value from Json.
QString toIPvl(const QString &value) const
Converts a value to iPVL format.
int width() const
Returns the current set longest keyword name.
QString name() const
Returns the keyword name.
int size() const
Returns the number of values stored in this keyword.
PvlKeyword & operator+=(QString value)
Adds a value.
std::vector< QString > * m_units
The units for the values.
bool isNull(const int index=0) const
Decides whether a value is null or not at a given index.
char * m_name
The keyword's name... This is a c-string for memory efficiency.
static bool readCleanKeyword(QString keyword, std::vector< QString > &keywordComments, QString &keywordName, std::vector< std::pair< QString, QString > > &keywordValues)
This reads a keyword compressed back to 1 line of data (excluding comments, which are included on sep...
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...
~PvlKeyword()
Destructs a PvlKeyword object.
void setFormat(PvlFormat *formatter)
Set the PvlFormatter used to format the keyword name and value(s)
int comments() const
Returns the number of lines of comments associated with this keyword.
QString comment(const int index) const
Return a comment at the specified index.
PvlFormat * m_formatter
Formatter object.
int indent() const
Returns the current indent level.
QString reform(const QString &value) const
Checks if the value needs to be converted to PVL or iPVL and returns it in the correct format.
void setUnits(QString units)
Sets the unit of measure for all current values if any exist.
static bool stringEqual(const QString &string1, const QString &string2)
Checks to see if two QStrings are equal.
PvlFormat * format()
Get the current PvlFormat or create one.
void addCommentWrapped(QString comment)
Automatically wraps and adds long comments to the PvlKeyword.
QString toPvl(const QString &value) const
Converts a value to PVL format.
void addJsonValue(nlohmann::json jsonobj, QString unit="")
Adds a value with units.
PvlKeyword & operator=(QString value)
Sets new values.
void writeSpaces(std::ostream &, int) const
This writes numSpaces spaces to the ostream.
std::ostream & writeWithWrap(std::ostream &os, const QString &textToWrite, int startColumn, PvlFormat &format) const
Wraps output so that length doesn't exceed the character limit.
void setValue(QString value, QString unit="")
Sets new values.
void addComment(QString comment)
Add a comment to the PvlKeyword.
int m_width
The width of the longest keyword.
bool isEquivalent(QString string1, int index=0) const
Checks to see if a value with a specified index is equivalent to another QString.
void clearComment()
Clears the current comments.
void addComments(const std::vector< QString > &comments)
This method adds multiple comments at once by calling AddComments on each element in the vector.
static QString readLine(std::istream &is, bool insideComment)
This method reads one line of data from the input stream.
int m_indent
The number of indentations to make.
void clear()
Clears all values and units for this PvlKeyword object.
void validateKeyword(PvlKeyword &pvlKwrd, QString psValueType="", PvlKeyword *pvlKwrdRange=NULL)
Validate Keyword for type and required values.
void init()
Clears all PvlKeyword data.
void addValue(QString value, QString unit="")
Adds a value with units.
@ Traverse
Search child objects.
Parse and return elements of a Pvl sequence.
int Size() const
Number of arrays in the sequence.
QString ArraySubscriptNotInRange(int index)
This error should be used when an Isis object or application is checking array bounds and the legal r...
This is free and unencumbered software released into the public domain.
int toInt(const QString &string)
Global function to convert from a string to an integer.
std::istream & operator>>(std::istream &is, CSVReader &csv)
Input read operator for input stream sources.
double toDouble(const QString &string)
Global function to convert from a string to a double.
QDebug operator<<(QDebug debug, const Hillshade &hillshade)
Print this class out to a QDebug object.
Namespace for the standard library.