LCOV - code coverage report
Current view: top level - src/libs/highlevel - elektra_error.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 34 118 28.8 %
Date: 2019-09-12 12:28:41 Functions: 5 14 35.7 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Elektra error codes.
       5             :  *
       6             :  * @copyright BSD License (see doc/LICENSE.md or http://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "elektra/conversion.h"
      10             : #include "elektra/error.h"
      11             : #include "kdberrors.h"
      12             : #include "kdbhelper.h"
      13             : #include "kdbprivate.h"
      14             : #include <string.h>
      15             : 
      16             : #ifdef __cplusplus
      17             : extern "C" {
      18             : #endif
      19             : 
      20             : // kdbprivate.h
      21             : 
      22             : /**
      23             :  * Creates a new ElektraError using the provided values.
      24             :  * The returned value will be allocated with elektraCalloc().
      25             :  *
      26             :  * @param code        The error code of the error. Must be compile-time constant.
      27             :  * @param description The description of the error. Will be copied and stored in the struct.
      28             :  * @param module      The module that raised the error. Must be compile-time constant.
      29             :  * @param file        The file that raised the error. Must be compile-time constant.
      30             :  * @param line        The line in which the error was raised.
      31             :  *
      32             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
      33             :  */
      34          30 : ElektraError * elektraErrorCreate (const char * code, const char * description, const char * module, const char * file, kdb_long_t line)
      35             : {
      36          30 :         ElektraError * const error = elektraCalloc (sizeof (struct _ElektraError));
      37          30 :         error->code = code;
      38          30 :         error->codeFromKey = NULL;
      39          30 :         error->description = elektraStrDup (description);
      40          30 :         error->module = module;
      41          30 :         error->file = file;
      42          30 :         error->line = line;
      43          30 :         error->warningCount = 0;
      44          30 :         error->warningAlloc = 0;
      45          30 :         error->warnings = NULL;
      46          30 :         error->errorKey = NULL;
      47             : 
      48          30 :         return error;
      49             : }
      50             : 
      51             : /**
      52             :  * Adds a warning to an existing ElektraError struct.
      53             :  * If you want to report a warning without an error, create a dummy error with
      54             :  * elektraErrorPureWarning() and then add a warning to it.
      55             :  *
      56             :  * @param error   The error to which @p warning shall be added.
      57             :  * @param warning The warning to add. Once added it is owned by @p error.
      58             :  *                DO NOT call elektraErrorReset() on it afterwards.
      59             :  */
      60           0 : void elektraErrorAddWarning (ElektraError * error, ElektraError * warning)
      61             : {
      62           0 :         if (error->warningAlloc == 0)
      63             :         {
      64           0 :                 error->warningCount = 1;
      65           0 :                 error->warningAlloc = 4;
      66           0 :                 error->warnings = elektraCalloc (error->warningAlloc * sizeof (ElektraError *));
      67             :         }
      68             :         else
      69             :         {
      70           0 :                 ++error->warningCount;
      71           0 :                 if (error->warningCount > error->warningAlloc)
      72             :                 {
      73           0 :                         error->warningAlloc *= 2;
      74           0 :                         elektraRealloc ((void **) &error->warnings, error->warningAlloc * sizeof (ElektraError *));
      75             :                 }
      76             :         }
      77             : 
      78           0 :         error->warnings[error->warningCount - 1] = warning;
      79           0 : }
      80             : 
      81             : /**
      82             :  * Extracts the error and all warnings from the given key.
      83             :  * If no error exists, a pure warning error will be used.
      84             :  * @see elektraErrorPureWarning
      85             :  *
      86             :  * @param key The to extract error and warnings from.
      87             :  *
      88             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
      89             :  */
      90           0 : ElektraError * elektraErrorFromKey (Key * key)
      91             : {
      92           0 :         if (key == NULL)
      93             :         {
      94             :                 return NULL;
      95             :         }
      96             : 
      97             :         ElektraError * error;
      98           0 :         if (keyGetMeta (key, "error") == NULL)
      99             :         {
     100           0 :                 error = elektraErrorPureWarning ();
     101             :         }
     102             :         else
     103             :         {
     104           0 :                 const Key * reasonMeta = keyGetMeta (key, "error/reason");
     105             : 
     106           0 :                 const char * codeFromKey = keyString (keyGetMeta (key, "error/number"));
     107           0 :                 const char * description = keyString (keyGetMeta (key, "error/description"));
     108           0 :                 const char * module = keyString (keyGetMeta (key, "error/module"));
     109           0 :                 const char * file = keyString (keyGetMeta (key, "error/file"));
     110             : 
     111           0 :                 char * fullDescription =
     112           0 :                         reasonMeta != NULL ? elektraFormat ("%s: %s", description, keyString (reasonMeta)) : elektraStrDup (description);
     113             : 
     114           0 :                 kdb_long_t line = 0;
     115           0 :                 elektraKeyToLong (key, &line);
     116           0 :                 error = elektraErrorCreate (NULL, fullDescription, module, file, line);
     117           0 :                 error->codeFromKey = elektraStrDup (codeFromKey);
     118           0 :                 error->errorKey = key;
     119             : 
     120           0 :                 elektraFree (fullDescription);
     121             :         }
     122             : 
     123             : 
     124           0 :         kdb_long_t warningCount = 0;
     125           0 :         const Key * warningsKey = keyGetMeta (key, "warnings"); // TODO: read warning count correctly
     126           0 :         if (warningsKey != NULL)
     127             :         {
     128           0 :                 elektraKeyToLong (warningsKey, &warningCount);
     129             :         }
     130             : 
     131           0 :         if (warningCount > 0)
     132             :         {
     133           0 :                 error->warningAlloc = 4;
     134           0 :                 while (error->warningAlloc < warningCount)
     135             :                 {
     136           0 :                         error->warningAlloc *= 2;
     137             :                 }
     138           0 :                 error->warningCount = warningCount;
     139             : 
     140           0 :                 error->warnings = elektraCalloc (error->warningAlloc * sizeof (ElektraError *));
     141             : 
     142           0 :                 for (int i = 0; i < warningCount; ++i)
     143             :                 {
     144           0 :                         const char * codeFromKey = keyString (keyGetMeta (key, "error/number"));
     145           0 :                         const char * description = keyString (keyGetMeta (key, "error/description"));
     146           0 :                         const char * module = keyString (keyGetMeta (key, "error/module"));
     147           0 :                         const char * file = keyString (keyGetMeta (key, "error/file"));
     148           0 :                         kdb_long_t line = 0;
     149           0 :                         elektraKeyToLong (key, &line);
     150             : 
     151           0 :                         ElektraError * warning = elektraErrorCreate (NULL, description, module, file, line);
     152           0 :                         error->codeFromKey = elektraStrDup (codeFromKey);
     153           0 :                         error->errorKey = key;
     154             : 
     155           0 :                         error->warnings[i] = warning;
     156             :                 }
     157             :         }
     158             :         else
     159             :         {
     160           0 :                 error->warningCount = 0;
     161           0 :                 error->warnings = NULL;
     162             :         }
     163             : 
     164             :         return error;
     165             : }
     166             : 
     167             : /**
     168             :  * Creates a "Key not found" error
     169             :  *
     170             :  * @param keyname The name of the key that wasn't found.
     171             :  *
     172             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     173             :  */
     174           0 : ElektraError * elektraErrorKeyNotFound (const char * keyname)
     175             : {
     176           0 :         char * description = elektraFormat ("The key '%s' could not be found.", keyname);
     177           0 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_INTERNAL, description, "highlevel", "unknown", 0);
     178           0 :         elektraFree (description);
     179           0 :         return error;
     180             : }
     181             : 
     182             : /**
     183             :  * Creates a "Wrong type" error
     184             :  *
     185             :  * @param keyname      The name of the key that had the wrong type.
     186             :  * @param expectedType The type that was expected.
     187             :  * @param actualType   The type that was actually found.
     188             :  *
     189             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     190             :  */
     191           2 : ElektraError * elektraErrorWrongType (const char * keyname, KDBType expectedType, KDBType actualType)
     192             : {
     193           2 :         char * description =
     194             :                 elektraFormat ("The key '%s' has the wrong type (expected '%s' but got '%s').", keyname, expectedType, actualType);
     195           2 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_VALIDATION_SEMANTIC, description, "highlevel", "unknown", 0);
     196           2 :         elektraFree (description);
     197           2 :         return error;
     198             : }
     199             : 
     200             : /**
     201             :  * Creates a "Null error argument" error
     202             :  *
     203             :  * @param function The name of the function that was called with a null pointer error argument.
     204             :  *
     205             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     206             :  */
     207           0 : ElektraError * elektraErrorNullError (const char * function)
     208             : {
     209           0 :         char * description = elektraFormat ("The value passed to the ElektraError ** argument of %s was NULL.", function);
     210           0 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_INTERNAL, description, "highlevel", "unknown", 0);
     211           0 :         elektraFree (description);
     212           0 :         return error;
     213             : }
     214             : 
     215             : /**
     216             :  * Creates a "Conversion to string failed" error
     217             :  *
     218             :  * @param sourceType The type which failed to be converted to string.
     219             :  * @param keyname    The name of the key that couldn't be converted.
     220             :  *
     221             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     222             :  */
     223           0 : ElektraError * elektraErrorConversionToString (KDBType sourceType, const char * keyname)
     224             : {
     225           0 :         char * description = elektraFormat ("The value of key '%s' with type '%s' could not be converted to string.", keyname, sourceType);
     226           0 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_VALIDATION_SEMANTIC, description, "highlevel", "unknown", 0);
     227           0 :         elektraFree (description);
     228           0 :         return error;
     229             : }
     230             : 
     231             : /**
     232             :  * Creates a "Conversion from string failed" error
     233             :  *
     234             :  * @param targetType  The type into which @p sourceValue couldn't be converted.
     235             :  * @param keyname     The name of the key that couldn't be converted.
     236             :  * @param sourceValue The value that couldn't be converted.
     237             :  *
     238             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     239             :  */
     240          28 : ElektraError * elektraErrorConversionFromString (KDBType targetType, const char * keyname, const char * sourceValue)
     241             : {
     242          28 :         char * description =
     243             :                 elektraFormat ("The value '%s' of key '%s' could not be converted to type '%s'.", sourceValue, keyname, targetType);
     244          28 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_VALIDATION_SEMANTIC, description, "highlevel", "unknown", 0);
     245          28 :         elektraFree (description);
     246          28 :         return error;
     247             : }
     248             : 
     249             : /**
     250             :  * Creates a "kdbEnsure failed" error
     251             :  *
     252             :  * This intended for the case when kdbEnsure() returns 1.
     253             :  *
     254             :  * @param reason The error/reason metadata returned by kdbEnsure().
     255             :  *
     256             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     257             :  */
     258           0 : ElektraError * elektraErrorEnsureFailed (const char * reason)
     259             : {
     260           0 :         char * description = elektraFormat ("The given contract could not be ensured: %s", reason);
     261           0 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_VALIDATION_SEMANTIC, description, "highlevel", "unknown", 0);
     262           0 :         elektraFree (description);
     263           0 :         return error;
     264             : }
     265             : 
     266             : /**
     267             :  * Creates a "minimal validation failed" error
     268             :  *
     269             :  * @param application parent key as passed to elektraOpen()
     270             :  *
     271             :  * @return A newly allocated ElektraError (free with elektraErrorReset()).
     272             :  */
     273           0 : ElektraError * elektraErrorMinimalValidationFailed (const char * application)
     274             : {
     275           0 :         char * description = elektraFormat (
     276             :                 "The validation of your KDB has failed. Please ensure that spec%s contains the "
     277             :                 "specification and that 'kdb spec-mount %s' was executed.",
     278             :                 application, application);
     279           0 :         ElektraError * error = elektraErrorCreate (ELEKTRA_ERROR_VALIDATION_SEMANTIC, description, "highlevel", "unknown", 0);
     280           0 :         elektraFree (description);
     281           0 :         return error;
     282             : }
     283             : 
     284             : // elektra/error.h
     285             : 
     286             : /**
     287             :  * \addtogroup highlevel High-level API
     288             :  * @{
     289             :  */
     290             : 
     291             : /**
     292             :  * Creates a dummy ElektraError struct to store warnings in.
     293             :  * If elektraErrorCode() is called on the resulting struct, it will return NULL.
     294             :  *
     295             :  * @return A newly allocated ElektraError (free with elektraFree()).
     296             :  */
     297           0 : ElektraError * elektraErrorPureWarning (void)
     298             : {
     299           0 :         return elektraErrorCreate (NULL, "", NULL, NULL, -1);
     300             : }
     301             : 
     302             : /**
     303             :  * @return the error code of the given error
     304             :  */
     305           0 : const char * elektraErrorCode (const ElektraError * error)
     306             : {
     307           0 :         return error->errorKey == NULL ? error->code : error->codeFromKey;
     308             : }
     309             : 
     310             : /**
     311             :  * @return the description for the given error
     312             :  */
     313          30 : const char * elektraErrorDescription (const ElektraError * error)
     314             : {
     315          30 :         return error->description;
     316             : }
     317             : 
     318             : /**
     319             :  * Frees the memory used by the error and sets
     320             :  * the referenced error variable to NULL.
     321             :  */
     322          30 : void elektraErrorReset (ElektraError ** error)
     323             : {
     324          30 :         if (*error == NULL)
     325             :         {
     326             :                 return;
     327             :         }
     328             : 
     329          30 :         ElektraError * actualError = *error;
     330             : 
     331          30 :         if (actualError->description != NULL)
     332             :         {
     333          30 :                 elektraFree (actualError->description);
     334             :         }
     335             : 
     336          30 :         if (actualError->codeFromKey != NULL)
     337             :         {
     338           0 :                 elektraFree (actualError->codeFromKey);
     339             :         }
     340             : 
     341          30 :         if (actualError->warnings != NULL)
     342             :         {
     343           0 :                 for (int i = 0; i < actualError->warningCount; ++i)
     344             :                 {
     345           0 :                         elektraErrorReset (&actualError->warnings[i]);
     346             :                 }
     347           0 :                 elektraFree (actualError->warnings);
     348             :         }
     349             : 
     350          30 :         elektraFree (actualError);
     351          30 :         *error = NULL;
     352             : }
     353             : 
     354             : /**
     355             :  * @}
     356             :  */
     357             : 
     358             : #ifdef __cplusplus
     359             : };
     360             : #endif

Generated by: LCOV version 1.13