Prechádzať zdrojové kódy

Merge branch 'exception-message-improvement' of public/ls-standard-library into development

patrick-christopher.mattulat 1 rok pred
rodič
commit
8ac2e09c5c
57 zmenil súbory, kde vykonal 579 pridanie a 131 odobranie
  1. 2 0
      CMakeLists.txt
  2. 3 1
      README.md
  3. 7 1
      include/ls-std/core/exception/EventNotHandledException.hpp
  4. 7 1
      include/ls-std/core/exception/EventNotSubscribedException.hpp
  5. 33 0
      include/ls-std/core/exception/ExceptionMessage.hpp
  6. 6 2
      include/ls-std/core/exception/FileNotFoundException.hpp
  7. 6 1
      include/ls-std/core/exception/FileOperationException.hpp
  8. 7 1
      include/ls-std/core/exception/IllegalArgumentException.hpp
  9. 7 1
      include/ls-std/core/exception/IllegalArithmeticOperationException.hpp
  10. 7 1
      include/ls-std/core/exception/IncompleteJsonException.hpp
  11. 7 1
      include/ls-std/core/exception/NullPointerException.hpp
  12. 2 1
      include/ls-std/ls-std-core.hpp
  13. 2 2
      source/ls-std/boxing/Boolean.cpp
  14. 2 2
      source/ls-std/boxing/Double.cpp
  15. 2 2
      source/ls-std/boxing/Float.cpp
  16. 5 5
      source/ls-std/boxing/Integer.cpp
  17. 5 5
      source/ls-std/boxing/Long.cpp
  18. 1 2
      source/ls-std/boxing/String.cpp
  19. 2 2
      source/ls-std/core/Class.cpp
  20. 17 2
      source/ls-std/core/exception/EventNotHandledException.cpp
  21. 17 2
      source/ls-std/core/exception/EventNotSubscribedException.cpp
  22. 30 0
      source/ls-std/core/exception/ExceptionMessage.cpp
  23. 17 2
      source/ls-std/core/exception/FileNotFoundException.cpp
  24. 17 2
      source/ls-std/core/exception/FileOperationException.cpp
  25. 17 2
      source/ls-std/core/exception/IllegalArgumentException.cpp
  26. 17 2
      source/ls-std/core/exception/IllegalArithmeticOperationException.cpp
  27. 17 2
      source/ls-std/core/exception/IncompleteJsonException.cpp
  28. 17 2
      source/ls-std/core/exception/NullPointerException.cpp
  29. 2 2
      source/ls-std/event/Event.cpp
  30. 2 2
      source/ls-std/event/EventHandler.cpp
  31. 20 10
      source/ls-std/event/EventManager.cpp
  32. 3 3
      source/ls-std/event/Narrator.cpp
  33. 2 2
      source/ls-std/event/serialization/SerializableJsonEvent.cpp
  34. 8 8
      source/ls-std/io/File.cpp
  35. 3 3
      source/ls-std/io/FileOutputStream.cpp
  36. 3 3
      source/ls-std/io/FileReader.cpp
  37. 2 3
      source/ls-std/io/FileWriter.cpp
  38. 3 3
      source/ls-std/io/kv/KvFileReader.cpp
  39. 2 2
      source/ls-std/io/kv/KvPair.cpp
  40. 2 2
      source/ls-std/io/kv/KvParser.cpp
  41. 2 2
      source/ls-std/io/logging/LogLevel.cpp
  42. 2 2
      source/ls-std/io/logging/Logger.cpp
  43. 3 3
      source/ls-std/io/xml/XmlAttribute.cpp
  44. 3 3
      source/ls-std/io/xml/XmlDocument.cpp
  45. 8 8
      source/ls-std/io/xml/XmlNode.cpp
  46. 2 2
      source/ls-std/io/xml/XmlParseParameter.cpp
  47. 2 2
      source/ls-std/io/xml/XmlParser.cpp
  48. 3 3
      source/ls-std/io/xml/XmlReader.cpp
  49. 22 2
      test/cases/core/exception/EventNotHandledExceptionTest.cpp
  50. 22 2
      test/cases/core/exception/EventNotSubscribedExceptionTest.cpp
  51. 47 0
      test/cases/core/exception/ExceptionMessageTest.cpp
  52. 22 2
      test/cases/core/exception/FileNotFoundExceptionTest.cpp
  53. 22 2
      test/cases/core/exception/FileOperationExceptionTest.cpp
  54. 22 2
      test/cases/core/exception/IllegalArgumentExceptionTest.cpp
  55. 22 2
      test/cases/core/exception/IllegalArithmeticOperationExceptionTest.cpp
  56. 22 2
      test/cases/core/exception/IncompleteJsonExceptionTest.cpp
  57. 22 2
      test/cases/core/exception/NullPointerExceptionTest.cpp

+ 2 - 0
CMakeLists.txt

@@ -129,6 +129,7 @@ set(SOURCE_FILES_BOXING
 set(SOURCE_FILES_CORE
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/exception/EventNotHandledException.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/exception/EventNotSubscribedException.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/exception/ExceptionMessage.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/exception/FileNotFoundException.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/exception/FileOperationException.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/exception/IllegalArgumentException.cpp
@@ -205,6 +206,7 @@ if (${LS_STD_BUILD_WITH_TESTS})
     set(TEST_FILES_CORE
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/exception/EventNotHandledExceptionTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/exception/EventNotSubscribedExceptionTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/exception/ExceptionMessageTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/exception/FileNotFoundExceptionTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/exception/FileOperationExceptionTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/exception/IllegalArgumentExceptionTest.cpp

+ 3 - 1
README.md

@@ -34,7 +34,8 @@ A __Date__ class comes with this submodule, which you can use to represent a dat
 
 #### Features ####
 
-- __AppleClang__ compiler is now officially supported 
+- __AppleClang__ compiler is now officially supported
+- exceptions provided by __core__ submodule now offer a constructor for passing dedicated messages
 
 #### Improvements ####
 
@@ -48,6 +49,7 @@ A __Date__ class comes with this submodule, which you can use to represent a dat
 #### Fixes ####
 
 - potential memory leaks have been resolved by strictly splitting prototypes and implementation project-wide, which enabled the usage of virtual or overridden destructors
+- memory leaks inside exception test suite have been fixed
 
 ---
 ### Documentation ###

+ 7 - 1
include/ls-std/core/exception/EventNotHandledException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-27
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <exception>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string>
 
 namespace ls::std::core
 {
@@ -20,9 +21,14 @@ namespace ls::std::core
     public:
 
       EventNotHandledException();
+      explicit EventNotHandledException(::std::string _message);
       ~EventNotHandledException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 7 - 1
include/ls-std/core/exception/EventNotSubscribedException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-27
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <exception>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string>
 
 namespace ls::std::core
 {
@@ -20,9 +21,14 @@ namespace ls::std::core
     public:
 
       EventNotSubscribedException();
+      explicit EventNotSubscribedException(::std::string _message);
       ~EventNotSubscribedException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 33 - 0
include/ls-std/core/exception/ExceptionMessage.hpp

@@ -0,0 +1,33 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-07
+* Changed:         2023-02-07
+*
+* */
+
+#ifndef LS_STD_EXCEPTION_MESSAGE_HPP
+#define LS_STD_EXCEPTION_MESSAGE_HPP
+
+#include <ls-std/os/dynamic-goal.hpp>
+#include <string>
+
+namespace ls::std::core
+{
+  class LS_STD_DYNAMIC_GOAL ExceptionMessage
+  {
+    public:
+
+      explicit ExceptionMessage(::std::string _message);
+      ~ExceptionMessage();
+
+      char *toCharacterPointer();
+
+    private:
+
+      ::std::string message{};
+  };
+}
+
+#endif

+ 6 - 2
include/ls-std/core/exception/FileNotFoundException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-17
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -15,7 +15,6 @@
 #include <ls-std/os/dynamic-goal.hpp>
 #include <string>
 
-//TODO: pass parameters, use class, show class name
 namespace ls::std::core
 {
   class LS_STD_DYNAMIC_GOAL FileNotFoundException : public ::std::exception
@@ -23,9 +22,14 @@ namespace ls::std::core
     public:
 
       FileNotFoundException();
+      explicit FileNotFoundException(::std::string _message);
       ~FileNotFoundException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 6 - 1
include/ls-std/core/exception/FileOperationException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-15
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -21,9 +21,14 @@ namespace ls::std::core
     public:
 
       FileOperationException();
+      explicit FileOperationException(::std::string _message);
       ~FileOperationException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 7 - 1
include/ls-std/core/exception/IllegalArgumentException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-09
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <exception>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string>
 
 namespace ls::std::core
 {
@@ -20,9 +21,14 @@ namespace ls::std::core
     public:
 
       IllegalArgumentException();
+      explicit IllegalArgumentException(::std::string _message);
       ~IllegalArgumentException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 7 - 1
include/ls-std/core/exception/IllegalArithmeticOperationException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-07
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <exception>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string>
 
 namespace ls::std::core
 {
@@ -20,9 +21,14 @@ namespace ls::std::core
     public:
 
       IllegalArithmeticOperationException();
+      explicit IllegalArithmeticOperationException(::std::string _message);
       ~IllegalArithmeticOperationException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 7 - 1
include/ls-std/core/exception/IncompleteJsonException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-04-30
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <exception>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string>
 
 namespace ls::std::core
 {
@@ -20,9 +21,14 @@ namespace ls::std::core
     public:
 
       IncompleteJsonException();
+      explicit IncompleteJsonException(::std::string _message);
       ~IncompleteJsonException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 7 - 1
include/ls-std/core/exception/NullPointerException.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-06
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <exception>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string>
 
 namespace ls::std::core
 {
@@ -20,9 +21,14 @@ namespace ls::std::core
     public:
 
       NullPointerException();
+      explicit NullPointerException(::std::string _message);
       ~NullPointerException() override;
 
       [[nodiscard]] const char *what() const noexcept override;
+
+    private:
+
+      ::std::string message{};
   };
 }
 

+ 2 - 1
include/ls-std/ls-std-core.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2022-05-13
- * Changed:         2023-02-06
+ * Changed:         2023-02-07
  *
  * */
 
@@ -12,6 +12,7 @@
 
 #include <ls-std/core/exception/EventNotHandledException.hpp>
 #include <ls-std/core/exception/EventNotSubscribedException.hpp>
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/FileNotFoundException.hpp>
 #include <ls-std/core/exception/FileOperationException.hpp>
 #include <ls-std/core/exception/IllegalArgumentException.hpp>

+ 2 - 2
source/ls-std/boxing/Boolean.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-09
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -72,7 +72,7 @@ void ls::std::boxing::Boolean::parse(::std::string _parseText)
 
   if (_parseText != this->TRUE_STRING && _parseText != this->FALSE_STRING)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{_parseText + " is not a valid string representation"};
   }
   else
   {

+ 2 - 2
source/ls-std/boxing/Double.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-14
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -226,7 +226,7 @@ void ls::std::boxing::Double::_assignEpsilon(double _epsilon)
 {
   if (_epsilon <= 0.0)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_epsilon is less than or equal zero"};
   }
 
   this->epsilon = _epsilon;

+ 2 - 2
source/ls-std/boxing/Float.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-14
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -222,7 +222,7 @@ void ls::std::boxing::Float::_assignEpsilon(float _epsilon)
 {
   if (_epsilon <= 0.0)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"epsilon is less than or equal zero"};
   }
 
   this->epsilon = _epsilon;

+ 5 - 5
source/ls-std/boxing/Integer.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-07
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -68,7 +68,7 @@ int ls::std::boxing::Integer::operator/(const ls::std::boxing::Integer &_integer
 {
   if (_integer == 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   return this->value / _integer;
@@ -78,7 +78,7 @@ int ls::std::boxing::Integer::operator/(int _value) const
 {
   if (_value == 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   return this->value / _value;
@@ -134,7 +134,7 @@ ls::std::boxing::Integer &ls::std::boxing::Integer::operator/=(const ls::std::bo
 {
   if (_integer == 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   this->value /= _integer;
@@ -145,7 +145,7 @@ ls::std::boxing::Integer &ls::std::boxing::Integer::operator/=(int _value)
 {
   if (_value == 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   this->value /= _value;

+ 5 - 5
source/ls-std/boxing/Long.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-17
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -68,7 +68,7 @@ ls::std::core::type::long_type ls::std::boxing::Long::operator/(const ls::std::b
 {
   if (_long == (ls::std::core::type::long_type) 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   return this->value / _long;
@@ -78,7 +78,7 @@ ls::std::core::type::long_type ls::std::boxing::Long::operator/(ls::std::core::t
 {
   if (_value == 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   return this->value / _value;
@@ -134,7 +134,7 @@ ls::std::boxing::Long &ls::std::boxing::Long::operator/=(const ls::std::boxing::
 {
   if (_long == (ls::std::core::type::long_type) 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   this->value /= _long;
@@ -145,7 +145,7 @@ ls::std::boxing::Long &ls::std::boxing::Long::operator/=(ls::std::core::type::lo
 {
   if (_value == 0)
   {
-    throw ls::std::core::IllegalArithmeticOperationException{};
+    throw ls::std::core::IllegalArithmeticOperationException{"division by zero is not allowed"};
   }
 
   this->value /= _value;

+ 1 - 2
source/ls-std/boxing/String.cpp

@@ -3,13 +3,12 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-14
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <algorithm>
 #include <ls-std/boxing/String.hpp>
-#include <ls-std/core/exception/IllegalArgumentException.hpp>
 
 ls::std::boxing::String::String() : ls::std::core::Class("String")
 {}

+ 2 - 2
source/ls-std/core/Class.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-07
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -26,7 +26,7 @@ void ls::std::core::Class::_assignClassName(const ::std::string &_name)
 {
   if (_name.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_name is empty"};
   }
 
   this->name = _name;

+ 17 - 2
source/ls-std/core/exception/EventNotHandledException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <ls-std/core/exception/EventNotHandledException.hpp>
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 
 ls::std::core::EventNotHandledException::EventNotHandledException() = default;
 
+ls::std::core::EventNotHandledException::EventNotHandledException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::EventNotHandledException::~EventNotHandledException() = default;
 
 const char *ls::std::core::EventNotHandledException::what() const noexcept
 {
-  return "EventNotHandledException thrown - event was not handled - nothing happened!";
+  ::std::string concatenatedMessage = "EventNotHandledException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "event was not handled - nothing happened!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 17 - 2
source/ls-std/core/exception/EventNotSubscribedException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <ls-std/core/exception/EventNotSubscribedException.hpp>
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 
 ls::std::core::EventNotSubscribedException::EventNotSubscribedException() = default;
 
+ls::std::core::EventNotSubscribedException::EventNotSubscribedException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::EventNotSubscribedException::~EventNotSubscribedException() = default;
 
 const char *ls::std::core::EventNotSubscribedException::what() const noexcept
 {
-  return "EventNotSubscribedException thrown - event was not subscribed!";
+  ::std::string concatenatedMessage = "EventNotSubscribedException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "event was not subscribed!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 30 - 0
source/ls-std/core/exception/ExceptionMessage.cpp

@@ -0,0 +1,30 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-07
+* Changed:         2023-02-07
+*
+* */
+
+#include <cstring>
+#include <ls-std/core/exception/ExceptionMessage.hpp>
+
+ls::std::core::ExceptionMessage::ExceptionMessage(::std::string _message) : message(::std::move(_message))
+{}
+
+ls::std::core::ExceptionMessage::~ExceptionMessage() = default;
+
+char *ls::std::core::ExceptionMessage::toCharacterPointer()
+{
+  char *rawPointerMessage{};
+
+  if (!this->message.empty())
+  {
+    rawPointerMessage = new char[this->message.size() + 1];
+    strcpy(rawPointerMessage, this->message.c_str());
+    rawPointerMessage[this->message.size()] = '\0';
+  }
+
+  return rawPointerMessage;
+}

+ 17 - 2
source/ls-std/core/exception/FileNotFoundException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/FileNotFoundException.hpp>
 
 ls::std::core::FileNotFoundException::FileNotFoundException() = default;
 
+ls::std::core::FileNotFoundException::FileNotFoundException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::FileNotFoundException::~FileNotFoundException() = default;
 
 const char *ls::std::core::FileNotFoundException::what() const noexcept
 {
-  return "FileNotFoundException thrown - file not found!";
+  ::std::string concatenatedMessage = "FileNotFoundException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "file not found!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 17 - 2
source/ls-std/core/exception/FileOperationException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/FileOperationException.hpp>
 
 ls::std::core::FileOperationException::FileOperationException() = default;
 
+ls::std::core::FileOperationException::FileOperationException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::FileOperationException::~FileOperationException() = default;
 
 const char *ls::std::core::FileOperationException::what() const noexcept
 {
-  return "FileOperationException thrown - file operation failed!";
+  ::std::string concatenatedMessage = "FileOperationException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "file operation failed!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 17 - 2
source/ls-std/core/exception/IllegalArgumentException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/IllegalArgumentException.hpp>
 
 ls::std::core::IllegalArgumentException::IllegalArgumentException() = default;
 
+ls::std::core::IllegalArgumentException::IllegalArgumentException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::IllegalArgumentException::~IllegalArgumentException() = default;
 
 const char *ls::std::core::IllegalArgumentException::what() const noexcept
 {
-  return "IllegalArgumentException thrown - passed argument is not valid!";
+  ::std::string concatenatedMessage = "IllegalArgumentException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "passed argument is not valid!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 17 - 2
source/ls-std/core/exception/IllegalArithmeticOperationException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/IllegalArithmeticOperationException.hpp>
 
 ls::std::core::IllegalArithmeticOperationException::IllegalArithmeticOperationException() = default;
 
+ls::std::core::IllegalArithmeticOperationException::IllegalArithmeticOperationException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::IllegalArithmeticOperationException::~IllegalArithmeticOperationException() = default;
 
 const char *ls::std::core::IllegalArithmeticOperationException::what() const noexcept
 {
-  return "IllegalArithmeticOperationException thrown - arithmetic operation is not allowed!";
+  ::std::string concatenatedMessage = "IllegalArithmeticOperationException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "arithmetic operation is not allowed!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 17 - 2
source/ls-std/core/exception/IncompleteJsonException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/IncompleteJsonException.hpp>
 
 ls::std::core::IncompleteJsonException::IncompleteJsonException() = default;
 
+ls::std::core::IncompleteJsonException::IncompleteJsonException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::IncompleteJsonException::~IncompleteJsonException() = default;
 
 const char *ls::std::core::IncompleteJsonException::what() const noexcept
 {
-  return "IncompleteJsonException thrown - this JSON string is incomplete.";
+  ::std::string concatenatedMessage = "IncompleteJsonException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "this JSON string is incomplete.";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 17 - 2
source/ls-std/core/exception/NullPointerException.cpp

@@ -3,17 +3,32 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-04
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
+#include <ls-std/core/exception/ExceptionMessage.hpp>
 #include <ls-std/core/exception/NullPointerException.hpp>
 
 ls::std::core::NullPointerException::NullPointerException() = default;
 
+ls::std::core::NullPointerException::NullPointerException(::std::string _message) : message(::std::move(_message))
+{}
+
 ls::std::core::NullPointerException::~NullPointerException() = default;
 
 const char *ls::std::core::NullPointerException::what() const noexcept
 {
-  return "NullPointerException thrown - reference is null!";
+  ::std::string concatenatedMessage = "NullPointerException thrown - ";
+
+  if (this->message.empty())
+  {
+    concatenatedMessage = concatenatedMessage + "reference is null!";
+  }
+  else
+  {
+    concatenatedMessage = concatenatedMessage + this->message;
+  }
+
+  return ExceptionMessage{concatenatedMessage}.toCharacterPointer();
 }

+ 2 - 2
source/ls-std/event/Event.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-26
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -58,7 +58,7 @@ void ls::std::event::Event::_assignId(const ls::std::core::type::event_id &_id)
 {
   if (_id.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_id is empty"};
   }
 
   this->id = _id;

+ 2 - 2
source/ls-std/event/EventHandler.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-27
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -26,7 +26,7 @@ void ls::std::event::EventHandler::_assignId(const ls::std::core::type::event_id
 {
   if (_id.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_id is empty"};
   }
 
   this->id = _id;

+ 20 - 10
source/ls-std/event/EventManager.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-27
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -19,9 +19,14 @@ ls::std::event::EventManager::~EventManager() = default;
 
 void ls::std::event::EventManager::subscribe(const ls::std::core::type::event_id &_id, const ::std::shared_ptr<ls::std::core::interface_type::IListener> &_listener)
 {
-  if (_id.empty() || _listener == nullptr)
+  if (_id.empty())
+  {
+    throw ls::std::core::IllegalArgumentException{"_id is empty"};
+  }
+
+  if (_listener == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_listener is null"};
   }
 
   if (this->_hasEventHandler(_id))
@@ -30,15 +35,20 @@ void ls::std::event::EventManager::subscribe(const ls::std::core::type::event_id
   }
   else
   {
-    throw ls::std::core::EventNotSubscribedException{};
+    throw ls::std::core::EventNotSubscribedException{"id: " + _id};
   }
 }
 
 void ls::std::event::EventManager::unsubscribe(const ls::std::core::type::event_id &_id, const ::std::shared_ptr<ls::std::core::interface_type::IListener> &_listener)
 {
-  if (_id.empty() || _listener == nullptr)
+  if (_id.empty())
+  {
+    throw ls::std::core::IllegalArgumentException{"_id is empty"};
+  }
+
+  if (_listener == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_listener is null"};
   }
 
   if (this->_hasEventHandler(_id))
@@ -53,7 +63,7 @@ bool ls::std::event::EventManager::addEventHandler(const ::std::shared_ptr<ls::s
 
   if (_eventHandler == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_eventHandler is null"};
   }
 
   if (!this->_hasEventHandler(_eventHandler->getId()))
@@ -73,7 +83,7 @@ void ls::std::event::EventManager::fire(ls::std::event::Event _event)
   }
   else
   {
-    throw ls::std::core::EventNotHandledException{};
+    throw ls::std::core::EventNotHandledException{"id: " + _event.getId()};
   }
 }
 
@@ -81,7 +91,7 @@ bool ls::std::event::EventManager::hasEventHandler(const ls::std::core::type::ev
 {
   if (_id.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_id is empty"};
   }
 
   return this->_hasEventHandler(_id);
@@ -91,7 +101,7 @@ bool ls::std::event::EventManager::removeEventHandler(const ::std::shared_ptr<ls
 {
   if (_eventHandler == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_eventHandler is null"};
   }
 
   return this->_removeEventHandler(_eventHandler);

+ 3 - 3
source/ls-std/event/Narrator.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-14
- * Changed:         2023-02-06
+ * Changed:         2023-02-07
  *
  * */
 
@@ -22,7 +22,7 @@ bool ls::std::event::Narrator::addListener(const ::std::shared_ptr<ls::std::core
 
   if (_listener == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_listener is null"};
   }
   else
   {
@@ -52,7 +52,7 @@ bool ls::std::event::Narrator::removeListener(const ::std::shared_ptr<ls::std::c
 
   if (_listener == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_listener is null"};
   }
   else
   {

+ 2 - 2
source/ls-std/event/serialization/SerializableJsonEvent.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-12-07
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -45,7 +45,7 @@ void ls::std::event::SerializableJsonEvent::_assignValue(const ::std::shared_ptr
 {
   if (_value == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_value is null"};
   }
 
   this->value = _value;

+ 8 - 8
source/ls-std/io/File.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-15
- * Changed:         2023-02-06
+ * Changed:         2023-02-07
  *
  * */
 
@@ -75,7 +75,7 @@ void ls::std::io::File::createNewFile()
   }
   else
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: create new file"};
   }
 }
 
@@ -184,7 +184,7 @@ void ls::std::io::File::makeDirectory()
 {
   if (!ls::std::io::File::_makeDirectory(this->absoluteFilePath))
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: create directory"};
   }
 }
 
@@ -202,7 +202,7 @@ void ls::std::io::File::makeDirectories()
     {
       if (!ls::std::io::File::_makeDirectory(currentHierarchy))
       {
-        throw ls::std::core::FileOperationException{}; // TODO: add missing test
+        throw ls::std::core::FileOperationException{"operation: create directory"}; // TODO: add missing test
       }
     }
 
@@ -330,7 +330,7 @@ bool ls::std::io::File::_exists(const ::std::string &_path)
 
   if (getcwd(buffer, sizeof(buffer)) == nullptr)
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: get working directory"};
   }
   else
   {
@@ -351,7 +351,7 @@ bool ls::std::io::File::_exists(const ::std::string &_path)
 
   if (!GetCurrentDirectory(MAX_PATH, buffer))
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: get working directory"};
   }
   else
   {
@@ -431,7 +431,7 @@ bool ls::std::io::File::_isReadableUnix(const ::std::string &_path)
   }
   else
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: fetch permissions"};
   }
 
   return readable;
@@ -453,7 +453,7 @@ bool ls::std::io::File::_isReadableWindows(const ::std::string &_path)
   }
   else
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: fetch permissions"};
   }
 
   return readable;

+ 3 - 3
source/ls-std/io/FileOutputStream.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-20
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -44,7 +44,7 @@ bool ls::std::io::FileOutputStream::write(const ls::std::core::type::byte_field
   }
   else
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: write"};
   }
 
   return succeeded;
@@ -62,7 +62,7 @@ void ls::std::io::FileOutputStream::_init()
 {
   if (!this->file.exists())
   {
-    throw ls::std::core::FileNotFoundException{};
+    throw ls::std::core::FileNotFoundException{"name: " + this->file.getAbsoluteFilePath()};
   }
   else
   {

+ 3 - 3
source/ls-std/io/FileReader.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-17
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -29,7 +29,7 @@ ls::std::core::type::byte_field ls::std::io::FileReader::read()
 
   if (inputStream.fail())
   {
-    throw ls::std::core::FileOperationException{};
+    throw ls::std::core::FileOperationException{"operation: read"};
   }
 
   inputStream.close();
@@ -49,6 +49,6 @@ void ls::std::io::FileReader::_init(ls::std::io::File &_file)
 {
   if (!_file.exists())
   {
-    throw ls::std::core::FileNotFoundException{};
+    throw ls::std::core::FileNotFoundException{"name: " + _file.getAbsoluteFilePath()};
   }
 }

+ 2 - 3
source/ls-std/io/FileWriter.cpp

@@ -3,13 +3,12 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-17
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <fstream>
 #include <ls-std/core/exception/FileNotFoundException.hpp>
-#include <ls-std/core/exception/FileOperationException.hpp>
 #include <ls-std/io/FileWriter.hpp>
 
 ls::std::io::FileWriter::FileWriter(ls::std::io::File &_file) : ls::std::core::Class("FileWriter"), file(_file)
@@ -38,6 +37,6 @@ void ls::std::io::FileWriter::_init(ls::std::io::File &_file)
 {
   if (!_file.exists())
   {
-    throw ls::std::core::FileNotFoundException{};
+    throw ls::std::core::FileNotFoundException{"name: " + _file.getAbsoluteFilePath()};
   }
 }

+ 3 - 3
source/ls-std/io/kv/KvFileReader.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-12-25
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -47,7 +47,7 @@ void ls::std::io::KvFileReader::_assignDocument(const ::std::shared_ptr<ls::std:
 {
   if (_document == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_document is null"};
   }
 
   this->document = _document;
@@ -57,7 +57,7 @@ void ls::std::io::KvFileReader::_assignFile(ls::std::io::File _kvFile)
 {
   if (!_kvFile.exists())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"file does not exist: " + _kvFile.getAbsoluteFilePath()};
   }
 
   this->kvFile = _kvFile;

+ 2 - 2
source/ls-std/io/kv/KvPair.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-12-25
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -36,7 +36,7 @@ void ls::std::io::KvPair::_assignKey(const ls::std::core::type::kv_key &_key)
 {
   if (_key.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_key is empty"};
   }
 
   this->key = _key;

+ 2 - 2
source/ls-std/io/kv/KvParser.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-12-25
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -37,7 +37,7 @@ void ls::std::io::KvParser::_assignDocument(const ::std::shared_ptr<ls::std::io:
 {
   if (_document == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_document is null"};
   }
 
   this->document = _document;

+ 2 - 2
source/ls-std/io/logging/LogLevel.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-20
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -71,7 +71,7 @@ void ls::std::io::LogLevel::setLogLevel(const ::std::string &_value)
   }
   else
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{_value + " is not a valid log level string"};
   }
 }
 

+ 2 - 2
source/ls-std/io/logging/Logger.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-08-20
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -85,7 +85,7 @@ void ls::std::io::Logger::_assignWriter(const ::std::shared_ptr<ls::std::core::i
 {
   if (_writer == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_writer is null"};
   }
 
   this->writer = _writer;

+ 3 - 3
source/ls-std/io/xml/XmlAttribute.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-09-23
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -46,7 +46,7 @@ void ls::std::io::XmlAttribute::_assignName(const ::std::string &_name)
 {
   if (_name.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_name is empty"};
   }
 
   this->name = _name;
@@ -56,7 +56,7 @@ void ls::std::io::XmlAttribute::_assignValue(const ::std::string &_value)
 {
   if (_value.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_value is empty"};
   }
 
   this->value = _value;

+ 3 - 3
source/ls-std/io/xml/XmlDocument.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-09-30
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -56,7 +56,7 @@ void ls::std::io::XmlDocument::_assignDeclaration(const ::std::shared_ptr<ls::st
 {
   if (_declaration == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_declaration is null"};
   }
 
   this->declaration = _declaration;
@@ -66,7 +66,7 @@ void ls::std::io::XmlDocument::_assignRootElement(const ::std::shared_ptr<ls::st
 {
   if (_rootElement == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_rootElement is null"};
   }
 
   this->rootElement = _rootElement;

+ 8 - 8
source/ls-std/io/xml/XmlNode.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-09-24
- * Changed:         2023-02-06
+ * Changed:         2023-02-07
  *
  * */
 
@@ -312,7 +312,7 @@ void ls::std::io::XmlNode::_assignName(const ::std::string &_name)
 {
   if (_name.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_name is empty"};
   }
 
   this->name = _name;
@@ -322,7 +322,7 @@ void ls::std::io::XmlNode::_assignValue(const ::std::string &_value)
 {
   if (_value.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_value is empty"};
   }
 
   this->value = _value;
@@ -332,7 +332,7 @@ void ls::std::io::XmlNode::_checkIfAttributeReferenceIsValid(const ::std::shared
 {
   if (_attribute == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_attribute is null"};
   }
 }
 
@@ -340,7 +340,7 @@ void ls::std::io::XmlNode::_checkIfNameIsNotEmpty(const ::std::string &_name)
 {
   if (_name.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_name is empty"};
   }
 }
 
@@ -348,7 +348,7 @@ void ls::std::io::XmlNode::_checkIfNodeReferenceIsValid(const ::std::shared_ptr<
 {
   if (_child == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_child is null"};
   }
 }
 
@@ -370,7 +370,7 @@ bool ls::std::io::XmlNode::_hasAttribute(const ::std::string &_name)
 
   if (_name.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_name is empty"};
   }
   else
   {
@@ -399,7 +399,7 @@ bool ls::std::io::XmlNode::_hasChild(const ::std::string &_name)
 
   if (_name.empty())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_name is empty"};
   }
   else
   {

+ 2 - 2
source/ls-std/io/xml/XmlParseParameter.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-05
-* Changed:         2023-02-05
+* Changed:         2023-02-07
 *
 * */
 
@@ -38,7 +38,7 @@ void ls::std::io::XmlParseParameter::_setNode(const ::std::shared_ptr<ls::std::i
 {
   if (_node == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_node is null"};
   }
 
   this->node = _node;

+ 2 - 2
source/ls-std/io/xml/XmlParser.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-26
- * Changed:         2023-02-05
+ * Changed:         2023-02-07
  *
  * */
 
@@ -57,7 +57,7 @@ void ls::std::io::XmlParser::_assignDocument(const ::std::shared_ptr<ls::std::io
 {
   if (_document == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_document is null"};
   }
 
   this->document = _document;

+ 3 - 3
source/ls-std/io/xml/XmlReader.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-10-10
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
@@ -47,7 +47,7 @@ void ls::std::io::XmlReader::_assignDocument(const ::std::shared_ptr<ls::std::io
 {
   if (_document == nullptr)
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"_document is null"};
   }
 
   this->document = _document;
@@ -57,7 +57,7 @@ void ls::std::io::XmlReader::_assignFile(ls::std::io::File _xmlFile)
 {
   if (!_xmlFile.exists())
   {
-    throw ls::std::core::IllegalArgumentException{};
+    throw ls::std::core::IllegalArgumentException{"file does not exist: " + _xmlFile.getAbsoluteFilePath()};
   }
 
   this->xmlFile = _xmlFile;

+ 22 - 2
test/cases/core/exception/EventNotHandledExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-27
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const EventNotHandledException &_exception)
           {
-            EXPECT_STREQ("EventNotHandledException thrown - event was not handled - nothing happened!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("EventNotHandledException thrown - event was not handled - nothing happened!", message.c_str());
+            throw;
+          }
+        },
+        EventNotHandledException);
+  }
+
+  TEST_F(EventNotHandledExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw EventNotHandledException{"id: OPEN_DOOR"};
+          }
+          catch (const EventNotHandledException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("EventNotHandledException thrown - id: OPEN_DOOR", message.c_str());
             throw;
           }
         },

+ 22 - 2
test/cases/core/exception/EventNotSubscribedExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-27
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const EventNotSubscribedException &_exception)
           {
-            EXPECT_STREQ("EventNotSubscribedException thrown - event was not subscribed!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("EventNotSubscribedException thrown - event was not subscribed!", message.c_str());
+            throw;
+          }
+        },
+        EventNotSubscribedException);
+  }
+
+  TEST_F(EventNotSubscribedExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw EventNotSubscribedException{"id: OPEN_DOOR"};
+          }
+          catch (const EventNotSubscribedException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("EventNotSubscribedException thrown - id: OPEN_DOOR", message.c_str());
             throw;
           }
         },

+ 47 - 0
test/cases/core/exception/ExceptionMessageTest.cpp

@@ -0,0 +1,47 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-07
+* Changed:         2023-02-07
+*
+* */
+
+#include <gtest/gtest.h>
+#include <ls-std/ls-std-core.hpp>
+
+using namespace ls::std::core;
+
+namespace
+{
+  class ExceptionMessageTest : public ::testing::Test
+  {
+    protected:
+
+      ExceptionMessageTest() = default;
+      ~ExceptionMessageTest() override = default;
+
+      void SetUp() override
+      {}
+
+      void TearDown() override
+      {}
+  };
+
+  TEST_F(ExceptionMessageTest, toCharacterPointer)
+  {
+    ::std::string text = "hello!";
+
+    ExceptionMessage message{text};
+    char *characterPointer = message.toCharacterPointer();
+    ASSERT_STREQ(text.c_str(), characterPointer);
+
+    delete characterPointer;
+  }
+
+  TEST_F(ExceptionMessageTest, toCharacterPointer_empty)
+  {
+    ExceptionMessage message{""};
+    ASSERT_TRUE(message.toCharacterPointer() == nullptr);
+  }
+}

+ 22 - 2
test/cases/core/exception/FileNotFoundExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-01
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const FileNotFoundException &_exception)
           {
-            EXPECT_STREQ("FileNotFoundException thrown - file not found!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("FileNotFoundException thrown - file not found!", message.c_str());
+            throw;
+          }
+        },
+        FileNotFoundException);
+  }
+
+  TEST_F(FileNotFoundExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw FileNotFoundException{R"("settings.txt" not found!)"};
+          }
+          catch (const FileNotFoundException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ(R"(FileNotFoundException thrown - "settings.txt" not found!)", message.c_str());
             throw;
           }
         },

+ 22 - 2
test/cases/core/exception/FileOperationExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-01
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const FileOperationException &_exception)
           {
-            EXPECT_STREQ("FileOperationException thrown - file operation failed!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("FileOperationException thrown - file operation failed!", message.c_str());
+            throw;
+          }
+        },
+        FileOperationException);
+  }
+
+  TEST_F(FileOperationExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw FileOperationException{R"(creating directory "tmp")"};
+          }
+          catch (const FileOperationException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ(R"(FileOperationException thrown - creating directory "tmp")", message.c_str());
             throw;
           }
         },

+ 22 - 2
test/cases/core/exception/IllegalArgumentExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-01
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const IllegalArgumentException &_exception)
           {
-            EXPECT_STREQ("IllegalArgumentException thrown - passed argument is not valid!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("IllegalArgumentException thrown - passed argument is not valid!", message.c_str());
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(IllegalArgumentExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw IllegalArgumentException{"value is empty"};
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("IllegalArgumentException thrown - value is empty", message.c_str());
             throw;
           }
         },

+ 22 - 2
test/cases/core/exception/IllegalArithmeticOperationExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-01
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const IllegalArithmeticOperationException &_exception)
           {
-            EXPECT_STREQ("IllegalArithmeticOperationException thrown - arithmetic operation is not allowed!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("IllegalArithmeticOperationException thrown - arithmetic operation is not allowed!", message.c_str());
+            throw;
+          }
+        },
+        IllegalArithmeticOperationException);
+  }
+
+  TEST_F(IllegalArithmeticOperationExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw IllegalArithmeticOperationException{"division by zero"};
+          }
+          catch (const IllegalArithmeticOperationException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("IllegalArithmeticOperationException thrown - division by zero", message.c_str());
             throw;
           }
         },

+ 22 - 2
test/cases/core/exception/IncompleteJsonExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-01
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const IncompleteJsonException &_exception)
           {
-            EXPECT_STREQ("IncompleteJsonException thrown - this JSON string is incomplete.", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("IncompleteJsonException thrown - this JSON string is incomplete.", message.c_str());
+            throw;
+          }
+        },
+        IncompleteJsonException);
+  }
+
+  TEST_F(IncompleteJsonExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw IncompleteJsonException{"incomplete: {\"name\":\"}"};
+          }
+          catch (const IncompleteJsonException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("IncompleteJsonException thrown - incomplete: {\"name\":\"}", message.c_str());
             throw;
           }
         },

+ 22 - 2
test/cases/core/exception/NullPointerExceptionTest.cpp

@@ -3,12 +3,13 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2021-05-01
- * Changed:         2023-02-04
+ * Changed:         2023-02-07
  *
  * */
 
 #include <gtest/gtest.h>
 #include <ls-std/ls-std-core.hpp>
+#include <string>
 
 using namespace ls::std::core;
 
@@ -38,7 +39,26 @@ namespace
           }
           catch (const NullPointerException &_exception)
           {
-            EXPECT_STREQ("NullPointerException thrown - reference is null!", _exception.what());
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("NullPointerException thrown - reference is null!", message.c_str());
+            throw;
+          }
+        },
+        NullPointerException);
+  }
+
+  TEST_F(NullPointerExceptionTest, constructor_dedicated_message)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            throw NullPointerException{"_value is null"};
+          }
+          catch (const NullPointerException &_exception)
+          {
+            ::std::string message = _exception.what();
+            EXPECT_STREQ("NullPointerException thrown - _value is null", message.c_str());
             throw;
           }
         },