2008-08-06 11:15:24 -07:00
|
|
|
/* EINA - EFL data type library
|
|
|
|
* Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Cedric Bail
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library;
|
|
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2008-09-05 00:58:38 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @page tutorial_error_page Error Tutorial
|
|
|
|
*
|
|
|
|
* @section tutorial_error_introduction Introduction
|
|
|
|
*
|
|
|
|
* The Eina error module provides a way to manage errors in a simple
|
|
|
|
* but powerful way in libraries and modules. It is also used in Eina
|
2009-09-03 18:37:11 -07:00
|
|
|
* itself. Similar to libC's @c errno and strerror() facilities, this
|
|
|
|
* is extensible and recommended for other libraries and applications.
|
2008-09-05 00:58:38 -07:00
|
|
|
*
|
|
|
|
* @section tutorial_error_registering_msg Registering messages
|
|
|
|
*
|
2008-09-06 01:48:36 -07:00
|
|
|
* The error module can provide a system that mimic the errno system
|
|
|
|
* of the C standard library. It consists in 2 parts:
|
|
|
|
*
|
|
|
|
* @li a way of registering new messages with
|
|
|
|
* eina_error_msg_register() and eina_error_msg_get(),
|
|
|
|
* @li a way of setting / getting last error message with
|
|
|
|
* eina_error_set() / eina_error_get().
|
|
|
|
*
|
|
|
|
* So one has to fisrt register all the error messages that a program
|
|
|
|
* or a lib should manage. Then, when an error can occur, use
|
2008-09-06 02:14:54 -07:00
|
|
|
* eina_error_set(), and when errors are managed, use
|
|
|
|
* eina_error_get(). If eina_error_set() is used to set an error, do
|
|
|
|
* not forget to call before eina_error_set0), to remove previous set
|
|
|
|
* errors.
|
2008-09-06 01:48:36 -07:00
|
|
|
*
|
2008-09-06 01:54:22 -07:00
|
|
|
* Here is an example of use:
|
|
|
|
*
|
2008-09-06 01:48:36 -07:00
|
|
|
* @code
|
|
|
|
* #include <stdlib.h>
|
|
|
|
* #include <stdio.h>
|
|
|
|
*
|
|
|
|
* #include <eina_error.h>
|
|
|
|
*
|
|
|
|
* Eina_Error MY_ERROR_NEGATIVE;
|
|
|
|
* Eina_Error MY_ERROR_NULL;
|
|
|
|
*
|
|
|
|
* voi *data_new()
|
|
|
|
* {
|
2008-09-06 02:14:54 -07:00
|
|
|
* eina_error_set(0);
|
|
|
|
*
|
2008-09-06 01:48:36 -07:00
|
|
|
* eina_error_set(MY_ERROR_NULL);
|
|
|
|
* return NULL;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* int test(int n)
|
|
|
|
* {
|
2008-09-06 02:14:54 -07:00
|
|
|
* eina_error_set(0);
|
|
|
|
*
|
2008-09-06 01:48:36 -07:00
|
|
|
* if (n < 0)
|
|
|
|
* {
|
|
|
|
* eina_error_set(MY_ERROR_NEGATIVE);
|
|
|
|
* return 0;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* return 1;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* int main(void)
|
|
|
|
* {
|
|
|
|
* void *data;
|
2008-09-05 00:58:38 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* if (!eina_init())
|
2008-09-06 01:48:36 -07:00
|
|
|
* {
|
|
|
|
* printf ("Error during the initialization of eina_error module\n");
|
|
|
|
* return EXIT_FAILURE;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* MY_ERROR_NEGATIVE = eina_error_msg_register("Negative number");
|
|
|
|
* MY_ERROR_NULL = eina_error_msg_register("NULL pointer");
|
|
|
|
|
|
|
|
* data = data_new();
|
|
|
|
* if (!data)
|
|
|
|
* {
|
|
|
|
* Eina_Error err;
|
|
|
|
*
|
|
|
|
* err = eina_error_get();
|
|
|
|
* if (err)
|
|
|
|
* printf("Error during memory allocation: %s\n",
|
|
|
|
* eina_error_msg_get(err));
|
|
|
|
* }
|
|
|
|
*
|
2008-09-06 02:14:54 -07:00
|
|
|
* if (!test(0))
|
|
|
|
* {
|
|
|
|
* Eina_Error err;
|
|
|
|
*
|
|
|
|
* err = eina_error_get();
|
|
|
|
* if (err)
|
|
|
|
* printf("Error during test function: %s\n",
|
|
|
|
* eina_error_msg_get(err));
|
|
|
|
* }
|
|
|
|
*
|
2008-09-06 01:48:36 -07:00
|
|
|
* if (!test(-1))
|
|
|
|
* {
|
|
|
|
* Eina_Error err;
|
|
|
|
*
|
|
|
|
* err = eina_error_get();
|
|
|
|
* if (err)
|
|
|
|
* printf("Error during test function: %s\n",
|
|
|
|
* eina_error_msg_get(err));
|
|
|
|
* }
|
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* eina_shutdown();
|
2008-09-06 01:48:36 -07:00
|
|
|
*
|
|
|
|
* return EXIT_SUCCESS;
|
|
|
|
* }
|
|
|
|
* @endcode
|
2008-09-06 01:54:22 -07:00
|
|
|
*
|
2009-09-03 18:37:11 -07:00
|
|
|
* Of course, instead of printf(), eina_log_print() can be used to
|
2008-09-06 01:54:22 -07:00
|
|
|
* have beautiful error messages.
|
2008-09-05 00:58:38 -07:00
|
|
|
*/
|
|
|
|
|
2008-08-08 05:29:13 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2008-08-28 00:46:42 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2008-09-30 09:25:11 -07:00
|
|
|
#include <stdlib.h>
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2008-10-16 14:31:51 -07:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_config.h"
|
2008-07-30 05:46:55 -07:00
|
|
|
#include "eina_private.h"
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
|
|
|
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
|
|
|
#include "eina_safety_checks.h"
|
|
|
|
#include "eina_error.h"
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/* TODO
|
2008-09-06 01:48:36 -07:00
|
|
|
* + add a wrapper for assert?
|
2008-07-30 05:46:55 -07:00
|
|
|
* + add common error numbers, messages
|
2008-09-06 01:48:36 -07:00
|
|
|
* + add a calltrace of errors, not only store the last error but a list of them
|
2008-07-30 05:46:55 -07:00
|
|
|
* and also store the function that set it
|
|
|
|
*/
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/*============================================================================*
|
2008-08-28 00:46:42 -07:00
|
|
|
* Local *
|
2008-07-30 05:46:55 -07:00
|
|
|
*============================================================================*/
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2008-09-05 00:58:38 -07:00
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
typedef struct _Eina_Error_Message Eina_Error_Message;
|
|
|
|
struct _Eina_Error_Message
|
|
|
|
{
|
|
|
|
Eina_Bool string_allocated;
|
|
|
|
const char *string;
|
|
|
|
};
|
|
|
|
|
|
|
|
static Eina_Error_Message *_eina_errors = NULL;
|
2009-09-06 15:54:49 -07:00
|
|
|
static size_t _eina_errors_count = 0;
|
|
|
|
static size_t _eina_errors_allocated = 0;
|
|
|
|
static Eina_Error _eina_last_error;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
static Eina_Error_Message *
|
|
|
|
_eina_error_msg_alloc(void)
|
|
|
|
{
|
|
|
|
size_t idx;
|
|
|
|
|
|
|
|
if (_eina_errors_count == _eina_errors_allocated)
|
|
|
|
{
|
|
|
|
void *tmp;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
if (EINA_UNLIKELY(_eina_errors_allocated == 0))
|
|
|
|
size = 24;
|
|
|
|
else
|
|
|
|
size = _eina_errors_allocated + 8;
|
|
|
|
|
|
|
|
tmp = realloc(_eina_errors, sizeof(Eina_Error_Message) * size);
|
|
|
|
if (!tmp)
|
|
|
|
return NULL;
|
|
|
|
_eina_errors = tmp;
|
|
|
|
_eina_errors_allocated = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
idx = _eina_errors_count;
|
|
|
|
_eina_errors_count++;
|
|
|
|
return _eina_errors + idx;
|
|
|
|
}
|
|
|
|
|
2008-09-05 00:58:38 -07:00
|
|
|
/**
|
|
|
|
* @endcond
|
|
|
|
*/
|
|
|
|
|
2008-08-08 03:39:47 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/*============================================================================*
|
2008-08-28 00:46:42 -07:00
|
|
|
* Global *
|
|
|
|
*============================================================================*/
|
|
|
|
|
2008-09-05 00:58:38 -07:00
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
2008-08-28 05:41:58 -07:00
|
|
|
EAPI Eina_Error EINA_ERROR_OUT_OF_MEMORY = 0;
|
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
static const char EINA_ERROR_OUT_OF_MEMORY_STR[] = "Out of memory";
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-05 00:58:38 -07:00
|
|
|
* @endcond
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2009-09-06 15:21:56 -07:00
|
|
|
* @internal
|
2009-06-22 13:03:58 -07:00
|
|
|
* @brief Initialize the error module.
|
2008-09-05 00:58:38 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
2008-08-28 00:46:42 -07:00
|
|
|
*
|
2009-06-22 13:03:58 -07:00
|
|
|
* This function sets up the error module of Eina. It is called by
|
2009-09-06 15:21:56 -07:00
|
|
|
* eina_init().
|
2008-09-05 00:58:38 -07:00
|
|
|
*
|
2009-06-22 13:03:58 -07:00
|
|
|
* This function registers the error #EINA_ERROR_OUT_OF_MEMORY.
|
|
|
|
*
|
|
|
|
* @see eina_init()
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:21:56 -07:00
|
|
|
Eina_Bool
|
|
|
|
eina_error_init(void)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-09-03 17:53:19 -07:00
|
|
|
/* TODO register the eina's basic errors */
|
2009-09-06 20:32:22 -07:00
|
|
|
EINA_ERROR_OUT_OF_MEMORY = eina_error_msg_static_register(EINA_ERROR_OUT_OF_MEMORY_STR);
|
2009-09-06 15:21:56 -07:00
|
|
|
return EINA_TRUE;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-09-05 00:58:38 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2009-09-06 15:21:56 -07:00
|
|
|
* @internal
|
2009-06-22 13:03:58 -07:00
|
|
|
* @brief Shut down the error module.
|
2008-08-28 00:46:42 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
2008-09-05 00:58:38 -07:00
|
|
|
*
|
2009-06-22 13:03:58 -07:00
|
|
|
* This function shuts down the error module set up by
|
2009-09-06 15:21:56 -07:00
|
|
|
* eina_error_init(). It is called by eina_shutdown().
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
|
|
|
* @see eina_shutdown()
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:21:56 -07:00
|
|
|
Eina_Bool
|
|
|
|
eina_error_shutdown(void)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-09-06 20:32:22 -07:00
|
|
|
Eina_Error_Message *eem, *eem_end;
|
|
|
|
|
|
|
|
eem = _eina_errors;
|
|
|
|
eem_end = eem + _eina_errors_count;
|
2009-09-06 15:54:49 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
for (; eem < eem_end; eem++)
|
|
|
|
if (eem->string_allocated)
|
|
|
|
free((char *)eem->string);
|
2009-09-06 15:54:49 -07:00
|
|
|
|
|
|
|
free(_eina_errors);
|
|
|
|
_eina_errors = NULL;
|
|
|
|
_eina_errors_count = 0;
|
|
|
|
_eina_errors_allocated = 0;
|
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
return EINA_TRUE;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
|
|
|
|
2009-12-27 00:45:30 -08:00
|
|
|
/*============================================================================*
|
|
|
|
* API *
|
|
|
|
*============================================================================*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @addtogroup Eina_Error_Group Error
|
|
|
|
*
|
|
|
|
* @brief These functions provide error management for projects.
|
|
|
|
*
|
|
|
|
* To use the error system Eina must be initialized with eina_init()
|
|
|
|
* and later shut down with eina_shutdown(). Error codes are
|
|
|
|
* registered with eina_error_msg_register() and converted from
|
|
|
|
* identifier to original message string with eina_error_msg_get().
|
|
|
|
*
|
|
|
|
* Logging functions are not in eina_error anymore, see
|
|
|
|
* eina_log_print() instead.
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-05 00:58:38 -07:00
|
|
|
* @brief Register a new error type.
|
|
|
|
*
|
2009-09-06 20:32:22 -07:00
|
|
|
* @param msg The description of the error. It will be duplicated using
|
|
|
|
* strdup().
|
2008-09-05 00:58:38 -07:00
|
|
|
* @return The unique number identifier for this error.
|
|
|
|
*
|
|
|
|
* This function stores in a list the error message described by
|
|
|
|
* @p msg. The returned value is a unique identifier greater or equal
|
2009-01-26 08:23:07 -08:00
|
|
|
* than 1. The description can be retrieve later by passing to
|
2008-09-05 00:58:38 -07:00
|
|
|
* eina_error_msg_get() the returned value.
|
2009-09-06 20:32:22 -07:00
|
|
|
*
|
|
|
|
* @see eina_error_msg_static_register()
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:54:49 -07:00
|
|
|
EAPI Eina_Error
|
|
|
|
eina_error_msg_register(const char *msg)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-09-06 20:32:22 -07:00
|
|
|
Eina_Error_Message *eem;
|
|
|
|
|
2009-09-06 15:54:49 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0);
|
2008-12-26 10:31:14 -08:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
eem = _eina_error_msg_alloc();
|
|
|
|
if (!eem)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
eem->string_allocated = EINA_TRUE;
|
|
|
|
eem->string = strdup(msg);
|
|
|
|
if (!eem->string)
|
2009-09-06 15:54:49 -07:00
|
|
|
{
|
2009-09-06 20:32:22 -07:00
|
|
|
_eina_errors_count--;
|
|
|
|
return 0;
|
|
|
|
}
|
2009-09-06 15:54:49 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
return _eina_errors_count; /* identifier = index + 1 (== _count). */
|
|
|
|
}
|
2009-09-06 15:54:49 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
/**
|
|
|
|
* @brief Register a new error type, statically allocated message.
|
|
|
|
*
|
|
|
|
* @param msg The description of the error. This string will not be
|
|
|
|
* duplicated and thus the given pointer should live during
|
|
|
|
* usage of eina_error.
|
|
|
|
* @return The unique number identifier for this error.
|
|
|
|
*
|
|
|
|
* This function stores in a list the error message described by
|
|
|
|
* @p msg. The returned value is a unique identifier greater or equal
|
|
|
|
* than 1. The description can be retrieve later by passing to
|
|
|
|
* eina_error_msg_get() the returned value.
|
|
|
|
*
|
|
|
|
* @see eina_error_msg_register()
|
|
|
|
*/
|
|
|
|
EAPI Eina_Error
|
|
|
|
eina_error_msg_static_register(const char *msg)
|
|
|
|
{
|
|
|
|
Eina_Error_Message *eem;
|
2008-09-30 09:25:11 -07:00
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, 0);
|
|
|
|
|
|
|
|
eem = _eina_error_msg_alloc();
|
|
|
|
if (!eem)
|
2009-09-06 15:54:49 -07:00
|
|
|
return 0;
|
2009-09-06 20:32:22 -07:00
|
|
|
|
|
|
|
eem->string_allocated = EINA_FALSE;
|
|
|
|
eem->string = msg;
|
|
|
|
return _eina_errors_count; /* identifier = index + 1 (== _count). */
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-09-05 00:58:38 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-05 00:58:38 -07:00
|
|
|
* @brief Return the description of the given an error number.
|
2008-08-28 00:46:42 -07:00
|
|
|
*
|
2008-09-05 00:58:38 -07:00
|
|
|
* @param error The error number.
|
|
|
|
* @return The description of the error.
|
|
|
|
*
|
|
|
|
* This function returns the description of an error that has been
|
|
|
|
* registered with eina_error_msg_register(). If an incorrect error is
|
|
|
|
* given, then @c NULL is returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:54:49 -07:00
|
|
|
EAPI const char *
|
|
|
|
eina_error_msg_get(Eina_Error error)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-09-06 15:54:49 -07:00
|
|
|
if (error < 1)
|
|
|
|
return NULL;
|
|
|
|
if ((size_t)error > _eina_errors_count)
|
|
|
|
return NULL;
|
2009-09-06 20:32:22 -07:00
|
|
|
return _eina_errors[error - 1].string;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-09-05 00:58:38 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-05 00:58:38 -07:00
|
|
|
* @brief Return the last set error.
|
2008-08-28 00:46:42 -07:00
|
|
|
*
|
2008-09-05 00:58:38 -07:00
|
|
|
* @return The last error.
|
|
|
|
*
|
2008-09-07 12:12:49 -07:00
|
|
|
* This function returns the last error set by eina_error_set(). The
|
|
|
|
* description of the message is returned by eina_error_msg_get().
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:54:49 -07:00
|
|
|
EAPI Eina_Error
|
|
|
|
eina_error_get(void)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-09-06 15:54:49 -07:00
|
|
|
return _eina_last_error;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-09-05 00:58:38 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-05 00:58:38 -07:00
|
|
|
* @brief Set the last error.
|
|
|
|
*
|
|
|
|
* @param err The error identifier.
|
|
|
|
*
|
|
|
|
* This function sets the last error identifier. The last error can be
|
|
|
|
* retrieved with eina_error_get().
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:54:49 -07:00
|
|
|
EAPI void
|
|
|
|
eina_error_set(Eina_Error err)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-09-06 15:54:49 -07:00
|
|
|
_eina_last_error = err;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-09-05 00:58:38 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|