USGS

Isis 3.0 Object Programmers' Reference

Home

IString.cpp
Go to the documentation of this file.
1 
22 #include "IString.h"
23 
24 #include <algorithm>
25 #include <cmath>
26 #include <cstring>
27 #include <iomanip>
28 #include <iostream>
29 #include <sstream>
30 #include <stdio.h>
31 #include <string>
32 
33 #include <QMap>
34 
35 #include "IException.h"
36 #include "SpecialPixel.h"
37 
38 using namespace std;
39 
40 namespace Isis {
52  bool toBool(const QString &string) {
53  QStringList trues;
54  trues.append("true");
55  trues.append("t");
56  trues.append("yes");
57  trues.append("y");
58  trues.append("on");
59  trues.append("1");
60 
61  QStringList falses;
62  falses.append("false");
63  falses.append("f");
64  falses.append("no");
65  falses.append("n");
66  falses.append("off");
67  falses.append("0");
68 
69  bool result = true;
70  bool foundMatch = false;
71 
72  QListIterator<QString> truesIterator(trues);
73  while (!foundMatch && truesIterator.hasNext()) {
74  foundMatch = (string.compare(truesIterator.next(), Qt::CaseInsensitive) == 0);
75  }
76 
77  if (!foundMatch) {
78  result = false;
79 
80  QListIterator<QString> falsesIterator(falses);
81  while (!foundMatch && falsesIterator.hasNext()) {
82  foundMatch = (string.compare(falsesIterator.next(), Qt::CaseInsensitive) == 0);
83  }
84  }
85 
86  if (!foundMatch) {
87  qSort(trues);
88  qSort(falses);
89  QString message = QObject::tr("Failed to convert string [%1] to a boolean. "
90  "Please specify one of [%2] for true, or one of [%3] for false.")
91  .arg(string).arg(trues.join(", ")).arg(falses.join(", "));
92  throw IException(IException::Unknown, message, _FILEINFO_);
93  }
94 
95  return result;
96  }
97 
98 
107  int toInt(const QString &string) {
108  bool ok = true;
109 
110  int result = string.toInt(&ok);
111 
112  if (!ok) {
113  QString message = QObject::tr("Failed to convert string [%1] to an integer").arg(string);
114  throw IException(IException::Unknown, message, _FILEINFO_);
115  }
116 
117  return result;
118  }
119 
120 
129  BigInt toBigInt(const QString &string) {
130  BigInt result;
131 
132  try {
133  std::stringstream s;
134  s << string.toStdString(); // Put the string into a stream
135  s.seekg(0, std::ios::beg); // Move the input pointer to the beginning
136  s >> result; // read/get "type T" out of the stream
137  std::ios::iostate state = s.rdstate();
138  if((state & std::ios::failbit) || (state & std::ios::badbit) ||
139  (!(state & std::ios::eofbit))) { // Make sure the stream is empty
140  throw (int)-1;
141  }
142  }
143  catch(...) {
144  QString message = QObject::tr("Failed to convert string [%1] to a big integer").arg(string);
145  throw IException(IException::Unknown, message, _FILEINFO_);
146  }
147 
148  return result;
149  }
150 
151 
163  double toDouble(const QString &string) {
164  double result = 0.0;
165 
166  if (string.startsWith("16#") && string.endsWith("#")) {
167  try {
168  stringstream s;
169  s << string.mid(3, string.size() - 3);
170  s.seekg(0, ios::beg);
171 
172  union {
173  unsigned int intData;
174  float floatData;
175  } raw;
176 
177  s >> hex >> raw.intData;
178 
179  ios::iostate state = s.rdstate();
180  if((state & ios::failbit) || (state & ios::badbit)) {
181  throw IException();
182  }
183 
184  result = raw.floatData;
185  }
186  catch(...) {
187  QString message = QObject::tr("Failed to convert HEX string [%1] to a "
188  "double").arg(string);
189  throw IException(IException::Unknown, message, _FILEINFO_);
190  }
191  }
192  else {
193  static QMap<QString, double> knownStrings;
194  if (knownStrings.isEmpty()) {
195  // Special case: user called toDouble(toString(DBL_MAX))
196  knownStrings["1.79769313486232e+308"] = DBL_MAX;
197  knownStrings["-1.79769313486232e+308"] = -DBL_MAX;
198  }
199 
200  bool ok = true;
201  if (!knownStrings.contains(string)) {
202  result = string.toDouble(&ok);
203  }
204  else {
205  result = knownStrings[string];
206  }
207 
208  if (!ok) {
209  QString message = QObject::tr("Failed to convert string [%1] to a double").arg(string);
210  throw IException(IException::Unknown, message, _FILEINFO_);
211  }
212  }
213 
214  return result;
215  }
216 
217 
225  QString toString(bool boolToConvert) {
226  return boolToConvert? "Yes" : "No";
227  }
228 
229 
238  QString toString(char charToConvert) {
239  QString result;
240  result += QChar(charToConvert);
241  return result;
242  }
243 
244 
251  QString toString(const int &intToConvert) {
252  return QString::number(intToConvert);
253  }
254 
255 
262  QString toString(const unsigned int &intToConvert) {
263  return QString::number(intToConvert);
264  }
265 
266 
273  QString toString(const BigInt &intToConvert) {
274  return QString::number(intToConvert);
275  }
276 
277 
291  QString toString(double doubleToConvert, int precision) {
292  // If number is zero, then it is not valid to do a log10 on it. To avoid this,
293  // check for zero ahead of time and handle it.
294  QString result;
295 
296  if(doubleToConvert == 0.0) {
297  result = "0.0";
298  }
299  else if(isnan(doubleToConvert)) {
300  result = "nan";
301  }
302 
303  if(doubleToConvert > DBL_MAX) {
304  doubleToConvert = DBL_MAX;
305  }
306 
307  if(doubleToConvert < -DBL_MAX) {
308  doubleToConvert = -DBL_MAX;
309  }
310 
311  if (result == "") {
312  // First determine the number of digits preceding the decimal point
313  // Numbers of the form 0.ABCDEFG where A is non-zero are assumed to
314  // have a leading digit of zero. Numbers of the form 0.0ABCDEFG,
315  // 0.00ABCEFEG and so on are not considered to have a leading digit
316  // (pre = 0).
317  double temp = qAbs(doubleToConvert);
318  int pre = (int)(log10(temp)) + 1;
319 
320  // If preceding number of digits is too large then we will need to create a
321  // scientific notation string. We will need 14 spaces for numbers, 2 spaces
322  // for exponents, 2 spaces for signs, and 1 for the letter E, 1 for a decimal
323  // place, and 1 extra in case of a leading 0. A grand total
324  // of 21 spaces is required. Therefore our format can be %22e
325 
326  // If the preceding number of digits is zero then we likely have a
327  // really small number (e.g., 0.000331236236). So let's put those in
328  // scientific notation as well
329 
330  // Finally, remove any zeroes before the E and if the exponent is zero
331  // then strip it off as well.
332 
333  char doubleString[23];
334 
335  if((log10(temp) > 13.0) || (log10(temp) < -3.0)) {
336  char format[8], buffer[8];
337  snprintf(buffer, 8, "%de", precision);
338  strcpy(format, "%21.");
339  strcat(format, buffer);
340  snprintf(doubleString, 23, format, doubleToConvert);
341 
342  char *e = strchr(doubleString, 'e');
343  char *sptr = e - 1;
344 
345  while(*sptr == '0') {
346  sptr--;
347  }
348 
349  if(*sptr == '.') {
350  sptr++;
351  }
352 
353  sptr++;
354  char tmp[22];
355  strcpy(tmp, e);
356  strcpy(sptr, tmp);
357 
358  e = strchr(doubleString, 'e');
359  int allzero = 1;
360 
361  for(sptr = e + 2; *sptr; sptr++) {
362  if(*sptr != '0') {
363  allzero = 0;
364  }
365  }
366 
367  if(allzero) {
368  *e = 0;
369  }
370  }
371  else {
372  // Ok it can be presented as a normal floating point num. So we will need
373  // 14 spaces for nums, 1 for the sign, 1 for the decimal, and 1 more
374  // for a possible leading 0. A grand total of 17 spaces. Therefore our
375  // format can be "%17.postf". Finally remove any trailing zeroes.
376 
377  if(temp < 1.0) {
378  pre--;
379  }
380  int post = precision - pre;
381 
382  char tempStr[3], format[8];
383  strcpy(format, "%17.");
384  snprintf(tempStr, 3, "%d", post);
385  strcat(format, tempStr);
386  strcat(format, "f");
387 
388  snprintf(doubleString, 23, format, doubleToConvert);
389 
390  if(post > 0) {
391  char *sptr = doubleString + strlen(doubleString) - 1;
392  while((*sptr == '0') && (*(sptr - 1) != '.')) {
393  *sptr = 0;
394  sptr--;
395  }
396  }
397  }
398 
399  while(doubleString[0] == ' ') {
400  for(unsigned int i = 0; i < strlen(doubleString); i++) {
401  doubleString[i] = doubleString[i + 1];
402  }
403  }
404 
405  result = QString(doubleString);
406  }
407 
408  return result;
409  }
410 
411 
417  IString::IString() : string() {
418  }
419 
428  IString::IString(const std::string &str) : string(str) {
429  }
430 
438  IString::IString(const IString &str) : string(str) {
439  }
440 
448  IString::IString(const char *str) : string(str) {
449  }
450 
460  IString::IString(const int &num) : string() {
461  ostringstream str;
462  str << num;
463  assign(str.str());
464  }
465 
475  IString::IString(const BigInt &num) : string() {
476  ostringstream str;
477  str << num;
478  assign(str.str());
479  }
480 
495  IString::IString(const double &num, const int piPrecision) : string() {
496  SetDouble(num, piPrecision);
497  }
498 
499 
508  void IString::SetDouble(const double &num, const int piPrecision) {
509  *this = toString(num, piPrecision).toStdString();
510  }
511 
518  IString::IString(const QString &str) : string() {
519  assign(str.toStdString());
520  }
521 
528 
539  IString IString::Trim(const std::string &chars) {
540  TrimHead(chars);
541  TrimTail(chars);
542  return *this;
543  }
544 
558  std::string IString::Trim(const std::string &chars, const std::string &str) {
559  //string result = str;
560  //result.replace (0,str.find_first_not_of (chars), "");
561  return TrimTail(chars, TrimHead(chars, str));
562  }
563 
572  IString IString::TrimHead(const std::string &chars) {
573  *this = replace(0, find_first_not_of(chars), "");
574  return *this;
575  }
576 
587  std::string IString::TrimHead(const std::string &chars, const std::string &str) {
588  string result = str;
589  result.replace(0, str.find_first_not_of(chars), "");
590  return result;
591  }
592 
601  IString IString::TrimTail(const std::string &chars) {
602  *this = erase(find_last_not_of(chars) + 1);
603  return *this;
604  }
605 
618  std::string IString::TrimTail(const std::string &chars, const std::string &str) {
619  string result = str;
620  result.erase(str.find_last_not_of(chars) + 1);
621  return result;
622  }
623 
632  string temp = *this;
633  *this = UpCase(temp);
634  return *this;
635  }
636 
646  std::string IString::UpCase(const std::string &str) {
647  string sOut(str);
648  transform(str.begin(), str.end(), sOut.begin(), (int ( *)(int)) toupper);
649  return(sOut);
650  }
651 
659  *this = DownCase((string) * this);
660  return *this;
661  }
662 
673  std::string IString::DownCase(const std::string &str) {
674  string sOut(str);
675  transform(str.begin(), str.end(), sOut.begin(), (int ( *)(int))tolower);
676  return sOut;
677  }
678 
691  static bool nocase_compare(const char c1, const char c2) {
692  return(toupper(c1) == toupper(c2));
693  }
694 
704  bool IString::Equal(const std::string &str) const {
705  string temp = *this;
706  return Equal(str, temp);
707  }
708 
719  bool IString::Equal(const std::string &str1, const std::string &str2) {
720  if(str1.size() != str2.size()) return(false);
721  return(std::equal(str1.begin(), str1.end(), str2.begin(), nocase_compare));
722  }
723 
724 
732  int IString::ToInteger() const {
733  return ToInteger(*this);
734  }
735 
745  int IString::ToInteger(const std::string &str) {
746  int v_out;
747  try {
748  stringstream s;
749  s << str; // Put the string into a stream
750  s.seekg(0, ios::beg); // Move the input pointer to the beginning
751  s >> v_out; // read/get "type T" out of the stream
752  ios::iostate state = s.rdstate();
753  if((state & ios::failbit) || (state & ios::badbit) ||
754  (!(state & ios::eofbit))) { // Make sure the stream is empty
755  throw(int) - 1;
756  }
757  }
758  catch(...) {
759  string message = "Failed to convert string [" + str + "] to an integer";
760  throw IException(IException::Unknown, message, _FILEINFO_);
761  }
762  return(v_out);
763  }
764 
772  BigInt IString::ToBigInteger() const {
773  return ToBigInteger(*this);
774  }
775 
785  BigInt IString::ToBigInteger(const std::string &str) {
786  BigInt v_out;
787  try {
788  stringstream s;
789  s << str; // Put the string into a stream
790  s.seekg(0, ios::beg); // Move the input pointer to the beginning
791  s >> v_out; // read/get "type T" out of the stream
792  ios::iostate state = s.rdstate();
793  if((state & ios::failbit) || (state & ios::badbit) ||
794  (!(state & ios::eofbit))) { // Make sure the stream is empty
795  throw(int) - 1;
796  }
797  }
798  catch(...) {
799  string message = "Failed to convert string [" + str + "] to a big "
800  "integer";
801  throw IException(IException::Unknown, message, _FILEINFO_);
802  }
803  return(v_out);
804  }
805 
813  double IString::ToDouble() const {
814  return ToDouble(*this);
815  }
816 
826  double IString::ToDouble(const std::string &str) {
827 
828  double v_out;
829 
830  // Convert a hex value
831  if(str.substr(0, 3) == "16#" && str.substr(str.length() - 1, 1) == "#") {
832  try {
833  stringstream s;
834  s << str.substr(3, str.find_last_of("#") - 3);
835  s.seekg(0, ios::beg);
836 
837  union {
838  unsigned int i;
839  float f;
840  } u;
841 
842  s >> hex >> u.i;
843 
844  ios::iostate state = s.rdstate();
845  if((state & ios::failbit) || (state & ios::badbit)) {
846  throw(int) - 1;
847  }
848  v_out = u.f;
849  }
850  catch(...) {
851  string message = "Failed to convert HEX string [" + str + "] to a "
852  "double";
853  throw IException(IException::Unknown, message, _FILEINFO_);
854  }
855  }
856  // Convert a decimal value
857  else {
858  try {
859  stringstream s;
860  s << str; // Put the string into a stream
861  s.seekg(0, ios::beg); // Move the input pointer to the beginning
862  s >> v_out; // read/get "type T" out of the stream
863  ios::iostate state = s.rdstate();
864  if((state & ios::failbit) || (state & ios::badbit) ||
865  (!(state & ios::eofbit))) { // Make sure the stream is empty
866  throw(int) - 1;
867  }
868  }
869  catch(...) {
870  string message = "Failed to convert string [" + str + "] to a double";
871  throw IException(IException::Unknown, message, _FILEINFO_);
872  }
873  }
874 
875  return(v_out);
876  }
877 
883  QString IString::ToQt() const {
884  return QString::fromStdString(*this);
885  }
886 
894  QString IString::ToQt(const std::string &s) {
895  return(QString::fromStdString(s));
896  }
897 
911  IString IString::Token(const IString &separator) {
912  IString retstr = "" ;
913 
914  for(unsigned int i = 0; i < size(); i++) {
915  for(unsigned int sep = 0; sep < separator.size(); sep++) {
916  if(separator[sep] == at(i)) {
917  retstr = substr(0, i);
918  replace(0, i + 1, "");
919  return retstr;
920  }
921  }
922  }
923 
924  if(retstr == "") {
925  retstr = (*this);
926  replace(0, size(), "");
927  }
928 
929  return retstr;
930  }
931 
954  int IString::Split(const char separator, const std::string &str,
955  std::vector<std::string> &tokens,
956  bool allowEmptyEntries) {
957  string::size_type idx(0), idx2(0);
958  unsigned int ksize = str.size();
959  tokens.clear();
960 
961  if(ksize > 0) {
962  if(str[idx] == separator) idx++;
963  while((idx2 = str.find(separator, idx)) != string::npos) {
964  if((idx2 == idx)) {
965  if(allowEmptyEntries) tokens.push_back("");
966  }
967  else {
968  string::size_type len(idx2 - idx);
969  tokens.push_back(str.substr(idx, len));
970  }
971  idx = idx2 + 1;
972  }
973  if(idx < ksize) tokens.push_back(str.substr(idx));
974  }
975  return(tokens.size());
976  }
977 
978 
989  *this = Compress((string) * this, force);
990  return *this;
991  }
992 
1004  std::string IString::Compress(const std::string &str, bool force) {
1005  string result(str);
1006  if(force == false) {
1007  int spaces = 0;
1008  int leftquote = result.find_first_of("\"\'");
1009  while((spaces = result.find(" ", spaces)) >= 0) {
1010  int rightquote = result.find_first_of("\"\'", leftquote + 1);
1011  if(spaces < leftquote) { //spaces are before quotation
1012  result.erase(spaces, 1);
1013  leftquote = result.find_first_of("\"\'", spaces);
1014  }
1015  else if((spaces > leftquote) && (spaces < rightquote)) { //spaces are within quotation
1016  spaces = rightquote + 1;
1017  leftquote = result.find_first_of("\"\'", rightquote + 1);
1018  }
1019  else if(leftquote == (int)npos) { //there are no quotations
1020  result.erase(spaces, 1);
1021  }
1022  else { //spaces are after quotation
1023  leftquote = result.find_first_of("\"\'", rightquote + 1);
1024  }
1025  }
1026  return result;
1027  }
1028  else {
1029  int spaces = 0;
1030  while((spaces = result.find(" ", spaces)) >= 0) {
1031  result.erase(spaces, 1);
1032  }
1033  return result;
1034  }
1035  }
1036 
1051  IString IString::Replace(const std::string &from, const std::string &to,
1052  int maxReplaceCount) {
1053  *this = IString(Replace((string) * this, from, to, maxReplaceCount));
1054  return *this;
1055  }
1056 
1105  std::string IString::Replace(const std::string &str, const std::string &from,
1106  const std::string &to, int maxReplaceCount) {
1107  if(str.empty()) return(str);
1108  if(from.empty()) return(str);
1109  string sRet(str);
1110  string::size_type pos;
1111  int nReplaced = 0;
1112  while((nReplaced < maxReplaceCount) &&
1113  (pos = sRet.find(from)) != string::npos) {
1114  sRet.replace(pos, from.size(), to);
1115  nReplaced++;
1116  }
1117  return(sRet);
1118  }
1119 
1120 
1137  IString IString::Replace(const std::string &from, const std::string &to,
1138  bool honorquotes) {
1139  *this = Replace((string) * this, from, to, honorquotes);
1140  return *this;
1141  }
1142 
1161  IString IString::Replace(const std::string &str, const std::string &from,
1162  const std::string &to , bool honorquotes) {
1163 
1164  string result = str;
1165  if(honorquotes == true) {
1166  int instances = 0;
1167  int quote = result.find_first_of("\"\'");
1168  while((instances = result.find(from, instances)) >= 0) {
1169 
1170  int nextquote = result.find_first_of("\"\'", quote + 1);
1171  if(instances < quote) {
1172  result.replace(instances, from.length(), to);
1173  quote = result.find_first_of("\"\'", instances);
1174  }
1175  else if((instances > quote) && (instances < nextquote)) {
1176  instances = nextquote + 1;
1177  quote = result.find_first_of("\"\'", nextquote);
1178  }
1179  else if(quote == (int)npos) {
1180  result.replace(instances, from.length(), to);
1181  }
1182  else {
1183  quote = result.find_first_of("\"\'", nextquote);
1184  }
1185  }
1186  return (IString) result;
1187  }
1188  else {
1189  int instances = 0;
1190  while((instances = result.find(from, instances)) >= 0) {
1191  result.replace(instances, from.length(), to);
1192  }
1193  return (IString) result;
1194  }
1195  }
1196 
1210  IString IString::Convert(const std::string &listofchars, const char &to) {
1211  *this = Convert((string) * this, listofchars, to);
1212  return *this;
1213  }
1214 
1230  string IString::Convert(const std::string &str, const std::string &listofchars,
1231  const char &to) {
1232  std::string::size_type pos = 0;
1233  string result = str;
1234  string tmp;
1235  tmp = to;
1236  while((pos = result.find_first_of(listofchars, pos)) != npos) {
1237  result.replace(pos, 1, tmp);
1238  pos++;
1239  }
1240  return result;
1241  }
1242 
1253  *this = ConvertWhiteSpace((string) * this);
1254  return *this;
1255  }
1256 
1266  std::string IString::ConvertWhiteSpace(const std::string &str) {
1267  return Convert(str, "\n\r\t\f\v\b", ' ');
1268  }
1269 
1280  IString IString::Remove(const std::string &del) {
1281  std::string::size_type pos;
1282  while((pos = find_first_of(del)) != npos) this->erase(pos, 1);
1283  return *this;
1284  }
1285 
1299  std::string IString::Remove(const std::string &str, const std::string &del) {
1300  string::size_type pos;
1301  string result(str);
1302  while((pos = result.find_first_of(del)) != npos) result.erase(pos, 1);
1303  return result;
1304  }
1305 
1315  IString &IString::operator= (const int &value) {
1316  ostringstream str;
1317  str << value;
1318  assign(str.str());
1319  return *this;
1320  }
1321 
1331  IString &IString::operator= (const BigInt &value) {
1332  ostringstream str;
1333  str << value;
1334  assign(str.str());
1335  return *this;
1336  }
1337 
1347  std::string IString::ToStd(const QString &str) {
1348  return(str.toStdString());
1349  }
1350 
1360  QStringList IString::ToQt(const std::vector<std::string> &sl) {
1361  QStringList Qsl;
1362  for(unsigned int i = 0 ; i < sl.size() ; i++) {
1363  Qsl << ToQt(sl[i]);
1364  }
1365  return Qsl;
1366  }
1367 
1377  std::vector<std::string> IString::ToStd(const QStringList &sl) {
1378  std::vector<std::string> Stdsl;
1379  for(int i = 0 ; i < sl.size() ; i++) {
1380  Stdsl.push_back(ToStd(sl.at(i)));
1381  }
1382 
1383  return(Stdsl);
1384  }
1385 
1386 
1398  std::ostream &operator<<(std::ostream &outputStream, const QString &string) {
1399  return (outputStream << string.toAscii().data());
1400  }
1401 
1402 
1414  std::ostream &operator<<(std::ostream &outputStream, const QStringRef &string) {
1415  return (outputStream << string.toString().toAscii().data());
1416  }
1417 }