Isis 3 Programmer Reference
IException.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 
8 #include "IsisDebug.h"
9 #include "IException.h"
10 
11 #include <stdlib.h>
12 
13 #include <algorithm>
14 #include <cstring>
15 #include <iostream>
16 #include <sstream>
17 #include <string>
18 
19 #include <QList>
20 
21 #include "Application.h"
22 #include "Preference.h"
23 #include "Pvl.h"
24 
25 using namespace std;
26 
27 namespace Isis {
40  IException::IException() {
41  m_what = NULL;
42  m_errorType = Unknown;
43  m_message = NULL;
44  m_fileName = NULL;
45  m_previousExceptions = NULL;
46  m_lineNumber = -1;
47 
48  m_what = buildWhat();
49  }
50 
51 
72  IException::IException(ErrorType type, const QString &message,
73  const char *fileName, int lineNumber) {
74  m_what = NULL;
75  m_message = NULL;
76  m_fileName = NULL;
77  m_previousExceptions = NULL;
78 
79  m_errorType = type;
80  m_message = new QString(QString(message).trimmed());
81  m_fileName = new QString(fileName);
82  m_lineNumber = lineNumber;
83 
84  deleteEmptyMemberStrings();
85 
86  m_what = buildWhat();
87  }
88 
89 
110  IException::IException(ErrorType type, const char *message,
111  const char *fileName, int lineNumber) {
112  m_what = NULL;
113  m_message = NULL;
114  m_fileName = NULL;
115  m_previousExceptions = NULL;
116 
117  m_errorType = type;
118  m_message = new QString(QString(message).trimmed());
119  m_fileName = new QString(fileName);
120  m_lineNumber = lineNumber;
121 
122  deleteEmptyMemberStrings();
123 
124  m_what = buildWhat();
125  }
126 
127 
148  IException::IException(ErrorType type, const std::string &message,
149  const char *fileName, int lineNumber) {
150  m_what = NULL;
151  m_message = NULL;
152  m_fileName = NULL;
153  m_previousExceptions = NULL;
154 
155  m_errorType = type;
156  m_message = new QString(QString(message.c_str()).trimmed());
157  m_fileName = new QString(fileName);
158  m_lineNumber = lineNumber;
159 
160  deleteEmptyMemberStrings();
161 
162  m_what = buildWhat();
163  }
164 
165 
196  IException::IException(const IException &caughtException,
197  ErrorType type, const char *message,
198  const char *fileName, int lineNumber) {
199  m_what = NULL;
200  m_message = NULL;
201  m_fileName = NULL;
202  m_previousExceptions = NULL;
203 
204  m_errorType = type;
205  m_message = new QString(QString(message).trimmed());
206  m_fileName = new QString(fileName);
207  m_lineNumber = lineNumber;
208 
209  deleteEmptyMemberStrings();
210 
211  append(caughtException);
212  }
213 
214 
244  IException::IException(const IException &caughtException,
245  ErrorType type, const std::string &message,
246  const char *fileName, int lineNumber) {
247  m_what = NULL;
248  m_message = NULL;
249  m_fileName = NULL;
250  m_previousExceptions = NULL;
251 
252  m_errorType = type;
253  m_message = new QString(QString(message.c_str()).trimmed());
254  m_fileName = new QString(fileName);
255  m_lineNumber = lineNumber;
256 
257  deleteEmptyMemberStrings();
258 
259  append(caughtException);
260  }
261 
262 
291  IException::IException(const IException &caughtException,
292  ErrorType type, const QString &message,
293  const char *fileName, int lineNumber) {
294  m_what = NULL;
295  m_message = NULL;
296  m_fileName = NULL;
297  m_previousExceptions = NULL;
298 
299  m_errorType = type;
300  m_message = new QString(message.trimmed());
301  m_fileName = new QString(fileName);
302  m_lineNumber = lineNumber;
303 
304  deleteEmptyMemberStrings();
305 
306  append(caughtException);
307  }
308 
309 
315  IException::IException(const IException &other) : exception(other) {
316  m_what = NULL;
317  m_message = NULL;
318  m_fileName = NULL;
319  m_previousExceptions = NULL;
320 
321  m_errorType = other.m_errorType;
322  m_lineNumber = other.m_lineNumber;
323 
324  if (other.m_what) {
325  int length = strlen(other.m_what);
326  m_what = new char[length + 1];
327  strncpy(m_what, other.m_what, length);
328  m_what[length] = '\0';
329  }
330 
331  if (other.m_message) {
332  m_message = new QString(*other.m_message);
333  }
334 
335  if (other.m_fileName) {
336  m_fileName = new QString(*other.m_fileName);
337  }
338 
339  if (other.m_previousExceptions) {
341  }
342  }
343 
344 
350  delete [] m_what;
351  m_what = NULL;
352 
354 
355  delete m_message;
356  m_message = NULL;
357 
358  delete m_fileName;
359  m_fileName = NULL;
360 
361  m_lineNumber = -1;
362 
363  delete m_previousExceptions;
364  m_previousExceptions = NULL;
365  }
366 
367 
375  const char *IException::what() const throw() {
376  return m_what;
377  }
378 
409  void IException::append(const IException &exceptionSource) {
410  if (!m_previousExceptions) {
412  }
413 
414  if (exceptionSource.m_previousExceptions) {
415  m_previousExceptions->append(*exceptionSource.m_previousExceptions);
416  }
417 
418  m_previousExceptions->append(exceptionSource);
419 
420  delete [] m_what;
421  m_what = NULL;
422  m_what = buildWhat();
423  }
424 
431  return m_errorType;
432  }
433 
434 
445  void IException::print() const {
446  QString errorString = toString();
447  if (errorString != "")
448  cerr << errorString.toLatin1().data() << endl;
449  }
450 
451 
461  void IException::print(bool printFileInfo) const {
462  QString errorString = toString(printFileInfo);
463  if (errorString != "")
464  cerr << errorString.toLatin1().data() << endl;
465  }
466 
467 
476  Pvl errors;
477 
478  QList<IException> exceptionsToConvert;
479 
481  exceptionsToConvert.append(*m_previousExceptions);
482  }
483  exceptionsToConvert.append(*this);
484 
485  for (int exceptionIndex = exceptionsToConvert.size() - 1;
486  exceptionIndex >= 0;
487  exceptionIndex--) {
488  const IException &exception(exceptionsToConvert.at(exceptionIndex));
489 
490  bool exceptionIsBlank = true;
491  PvlGroup errGroup("Error");
492 
493  errGroup += PvlKeyword("Program", Application::Name());
494 
495  if (exception.m_errorType != Unknown) {
496  errGroup += PvlKeyword("Class",
497  errorTypeToString(exception.m_errorType));
498  exceptionIsBlank = false;
499  }
500 
501  errGroup += PvlKeyword("Code", Isis::toString(exception.m_errorType));
502 
503  if (exception.m_message) {
504  exceptionIsBlank = false;
505  QString message(*exception.m_message);
506 
507  if (message.size() && message[message.size() - 1] == '.')
508  message = message.mid(0, message.size() - 1);
509  errGroup += PvlKeyword("Message", message);
510  }
511 
512  if (exception.m_fileName) {
513  exceptionIsBlank = false;
514  errGroup += PvlKeyword("File", *exception.m_fileName);
515 
516  if (exception.m_lineNumber != -1)
517  errGroup += PvlKeyword("Line", Isis::toString(exception.m_lineNumber));
518  }
519 
520  if (!exceptionIsBlank)
521  errors.addGroup(errGroup);
522  }
523 
524  return errors;
525  }
526 
527 
537  QString IException::toString() const {
538  bool reportFileLine = true;
539 
540  if (Preference::Preferences().hasGroup("ErrorFacility")) {
541  PvlGroup &errorFacility =
542  Preference::Preferences().findGroup("ErrorFacility");
543  if (errorFacility.hasKeyword("FileLine")) {
544  QString fileLine = errorFacility["FileLine"][0];
545  reportFileLine = (fileLine.toUpper() == "ON");
546  }
547  }
548 
549  return toString(reportFileLine);
550  }
551 
552 
564  QString IException::toString(bool includeFileInfo) const {
565  QString result;
566 
567  bool usePvlFormat = false;
568 
569  if (Preference::Preferences().hasGroup("ErrorFacility")) {
570  PvlGroup &errorFacility =
571  Preference::Preferences().findGroup("ErrorFacility");
572  if (errorFacility.hasKeyword("Format")) {
573  QString format = errorFacility["Format"][0];
574  usePvlFormat = (format.toUpper() == "PVL");
575  }
576  }
577 
578  if (usePvlFormat) {
579  Pvl errors = toPvl();
580 
581  if (errors.groups() != 0) {
582  stringstream stringStream;
583  stringStream << errors;
584  result = stringStream.str().c_str();
585  }
586  }
587  else {
588  QList<IException> exceptionsToConvert;
589 
591  exceptionsToConvert.append(*m_previousExceptions);
592  }
593  exceptionsToConvert.append(*this);
594 
595  for (int exceptionIndex = exceptionsToConvert.size() - 1;
596  exceptionIndex >= 0;
597  exceptionIndex--) {
598  const IException &exception(exceptionsToConvert.at(exceptionIndex));
599 
600  // Don't put **ERROR** if there is no message or type
601  if (exception.m_errorType != Unknown || exception.m_message) {
602  result += "**" + errorTypeToString(exception.m_errorType) + "**";
603  }
604 
605  bool needsPeriod = false;
606  if (exception.m_message) {
607  QString message(*exception.m_message);
608 
609  if (message.size() && message[message.size() - 1] == '.')
610  message = message.mid(0, message.size() - 1);
611  // There is always a **TYPE** already in the string, so prefix the
612  // message with a space.
613  result += " " + message;
614  needsPeriod = true;
615  }
616 
617  if(includeFileInfo && exception.m_fileName) {
618  result += " in " + *exception.m_fileName;
619  if (exception.m_lineNumber != -1)
620  result += " at " + Isis::toString(exception.m_lineNumber);
621  needsPeriod = true;
622  }
623 
624  if (needsPeriod)
625  result += ".";
626 
627  if (result.size() && result[result.size() - 1] != '\n')
628  result += "\n";
629  }
630  }
631 
632  return result.trimmed();
633  }
634 
635 
643  std::swap(m_what, other.m_what);
644  std::swap(m_errorType, other.m_errorType);
645  std::swap(m_message, other.m_message);
646  std::swap(m_fileName, other.m_fileName);
647  std::swap(m_lineNumber, other.m_lineNumber);
648  std::swap(m_previousExceptions, other.m_previousExceptions);
649  }
650 
651 
660  IException copy(rhs);
661  swap(copy);
662 
663  return *this;
664  }
665 
666 
674  vector<string> theStack;
675  StackTrace::GetStackTrace(&theStack);
676  QString message;
677 
678  for(unsigned int i = 1; i < theStack.size(); i++) {
679  message += (theStack[i] + "\n").c_str();
680  }
681 
682  IException result;
683  if (theStack.size() != 0) {
684  result = IException(Unknown, message, NULL, -1);
685  }
686 
687  return result;
688  }
689 
690 
699  QString result;
700 
701  switch(type) {
702  case User:
703  result = "USER ERROR";
704  break;
705  case Programmer:
706  result = "PROGRAMMER ERROR";
707  break;
708  case Io:
709  result = "I/O ERROR";
710  break;
711  case Unknown:
712  result = "ERROR";
713  break;
714  }
715 
716  return result;
717  }
718 
719 
728  const QString &string) {
729  ErrorType result = Unknown;
730 
731  if(string == "USER ERROR")
732  result = User;
733  else if(string == "PROGRAMMER ERROR")
734  result = Programmer;
735  else if(string == "I/O ERROR")
736  result = Io;
737 
738  return result;
739  }
740 
741 
750  char *IException::buildWhat() const {
751  QString whatStr = toString();
752 
753  char *result = new char[whatStr.size() + 1];
754  strncpy(result, whatStr.toLatin1().data(), whatStr.size());
755  result[whatStr.size()] = '\0';
756 
757  return result;
758  }
759 
760 
767  if (m_message->size() == 0) {
768  delete m_message;
769  m_message = NULL;
770  }
771 
772  if (m_fileName->size() == 0) {
773  delete m_fileName;
774  m_fileName = NULL;
775  }
776  }
777 }
778 
Isis::IException::IException
IException()
The default constructor creates an IException instance with no message, previous exceptions,...
Definition: IException.cpp:40
Isis::IException::errorTypeToString
static QString errorTypeToString(ErrorType t)
Returns the source of the error in string format for the given ErrorType.
Definition: IException.cpp:698
Isis::IException::Io
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:155
Isis::IException::m_what
char * m_what
This is used to store the return value of what() in a way that guarantees the returned data will not ...
Definition: IException.h:213
Isis::IException::print
void print() const
Prints a string representation of this exception to stderr.
Definition: IException.cpp:445
Isis::IException::m_lineNumber
int m_lineNumber
The line in the source code file that threw this exception.
Definition: IException.h:235
Isis::IException::deleteEmptyMemberStrings
void deleteEmptyMemberStrings()
This is a helper method for the constructors.
Definition: IException.cpp:766
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
QList
This is free and unencumbered software released into the public domain.
Definition: BoxcarCachingAlgorithm.h:13
Isis::IException::m_message
QString * m_message
The message associated with this exception.
Definition: IException.h:225
Isis::IException::Unknown
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:118
Isis::PvlObject::groups
int groups() const
Returns the number of groups contained.
Definition: PvlObject.h:75
Isis::IException::toPvl
Pvl toPvl() const
Returns a PVL object representing the contents of this exception.
Definition: IException.cpp:475
Isis::PvlContainer::hasKeyword
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Definition: PvlContainer.cpp:159
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::IException::~IException
~IException()
The destructor frees memory allocated for the message, filename, and list of previous exceptions.
Definition: IException.cpp:349
Isis::IException::stringToErrorType
static ErrorType stringToErrorType(const QString &s)
Given a string, returns the error type associated with it.
Definition: IException.cpp:727
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::IException::what
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:375
Isis::IException::append
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
Definition: IException.cpp:409
Isis::IException::buildWhat
char * buildWhat() const
Returns a C string containing a string representation of this exception.
Definition: IException.cpp:750
Isis::IException::createStackTrace
static IException createStackTrace()
Returns an IException representing the current stack, excluding this method.
Definition: IException.cpp:673
Isis::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::IException::toString
QString toString() const
Returns a string representation of this exception.
Definition: IException.cpp:537
Isis::Application::Name
static QString Name()
Returns the name of the application.
Definition: Application.cpp:729
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::IException::errorType
ErrorType errorType() const
Returns the source of the error for this exception.
Definition: IException.cpp:430
Isis::PvlObject::addGroup
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
Definition: PvlObject.h:186
Isis::IException::Programmer
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:146
std
Namespace for the standard library.
Isis::IException::swap
void swap(IException &other)
Swaps the values of this instance's member data with other.
Definition: IException.cpp:642
Isis::IException::m_errorType
ErrorType m_errorType
This exception's error source.
Definition: IException.h:219
Isis::IException::m_fileName
QString * m_fileName
The source code file that threw this exception.
Definition: IException.h:230
Isis::IException::m_previousExceptions
QList< IException > * m_previousExceptions
A list of exceptions that caused this exception.
Definition: IException.h:240
Isis::IException::ErrorType
ErrorType
Contains a set of exception error types.
Definition: IException.h:111
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::IException::User
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition: IException.h:126
Isis::IException::operator=
IException & operator=(const IException &rhs)
Assign the values of rhs to this instance.
Definition: IException.cpp:659