/* * LibAxl: Another XML library * Copyright (C) 2013 Advanced Software Production Line, S.L. * * This program 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 program 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 program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * * You may find a copy of the license under this software is released * at COPYING file. This is LGPL software: you are welcome to * develop proprietary applications using this library without any * royalty or fee but returning back any change, improvement or * addition in the form of source code, project image, documentation * patches, etc. * * For commercial support on build XML enabled solutions contact us: * * Postal address: * Advanced Software Production Line, S.L. * Edificio Alius A, Oficina 102, * C/ Antonio Suarez Nº 10, * Alcalá de Henares 28802 Madrid * Spain * * Email address: * info@aspl.es - http://www.aspl.es/xml */ #include struct _axlError { int code; char * error; int defined; }; /** * \defgroup axl_error_module Axl Error report: Functions to help AXL library to report internal error to the application level. */ /** * \addtogroup axl_error_module * @{ */ /** * @brief Allows to create a new \ref axlError value that contains an * error code and a error string. * * \ref axlError error reporting abstraction is a convenient way for * the developer and the user that makes use of the API to report and * get textual diagnostic errors produced. Many times, API provided do * not allow to get more information if something wrong happen making * it difficult to reach and solve the problem (including the * development phase). * * From a developer's perspective, here is how works \ref axlError, * * \code * void some_public_exported_function (int param, axlError ** error) * { * // do some work, but if it fails call to produce the error * // reporting. * axl_error_new (-2, // reporting an error code * "Something wasn't ok while processing..", * NULL, // a reference to the stream (optional) * error); // variable received. * return; * } * \endcode * * Previous construction makes error reporting optional but at the * same time, available, because the programmer doesn't requires to * check if the user did define the error variable, making it * available at user option. * * Now, if the user defines the \ref axlError reference, by calling to * the function, it can get the error reported as follows: * * \code * // declare the variable and it to null * axlError * error = NULL; * * // call to function * some_pulic_exported_function (10, &error); * if (! axl_error_was_ok (error)) { * // drop the message * printf ("Something has failed: (code: %d) %s\n", * axl_error_get_code (error), * axl_error_get (error)); * // dealloc the reference * axl_error_free (error); * } * \endcode * * Alternatively, the user can just bypass the error reporting * mechanism, without affecting the written code inside the source of * the function supporting the \ref axlError notification (even if the * code calls to \ref axl_error_new): * * \code * // call to the function without error reporting * some_pulic_exported_function (10, NULL); * \endcode * * In most cases, \ref axl_error_new is not used by API consumers but * by API developers. Once returned the \ref axlError reference the * following functions could be checked. * * - \ref axl_error_get returns textual diagnostic reported. * * - \ref axl_error_get_code returns error code reported. * * - \ref axl_error_was_ok allows to check if some error was * reported, base on the value initialization. * * * * @param code The error code to set and the error code string. * * @param error_code String to report. * * @param stream If provided, the error will try to get current stream * position to add more information to the place where the error was * found. * * @param _error The error string to be used to initialize the received \ref axlError. */ void axl_error_new (int code, char * error_code, axlStream * stream, axlError ** _error) { axlError * error; const char * following; /* get a reference to the error to be created */ if (_error == NULL) return; /* create the error to be reported */ error = axl_new (axlError, 1); /* check allocated value */ if (error == NULL) return; error->code = code; error->defined = -346715; if (stream == NULL) { /* allocate enough memory */ error->error = axl_strdup (error_code); } else { /* get the following */ following = axl_stream_get_following (stream, 10); /* alloc enough memory */ error->error = axl_stream_strdup_printf ("Error found (stream size: %d, at byte %d (global index: %d), near to ...%s..., while reading: %s): %s\n", axl_stream_get_size (stream), axl_stream_get_index (stream), axl_stream_get_global_index (stream), axl_stream_get_near_to (stream, 10), (following != NULL) ? following : "", error_code); } axl_log (NULL, AXL_LEVEL_CRITICAL, "(code: %d) %s", code, error_code); /* set the error into the recevied reference */ (* _error ) = error; return; } /** * @brief Allows to report a new error message with an associated * error code on the provided \ref axlError reference. * * This function provides the same function like \ref axl_error_new * but at the same time it provides support for printf-like arguments and * no requires to provide a reference to an \ref axlStream which is * suitable for axl libraries but not applications on top of it. * * @param _error Reference to the axlError to be initialized with the error * to be reported. In the case NULL is received nothing is done. * * @param code The error code to report. * * @param format Printf-like error message to report. */ void axl_error_report (axlError ** _error, int code, char * format, ...) { va_list args; char * string; axlError * error; /* do not operate if null is received */ if (_error == NULL) return; /* open the stdargs */ va_start (args, format); /* build the string */ string = axl_stream_strdup_printfv (format, args); /* close the stdargs */ va_end (args); /* create the error to be reported */ error = axl_new (axlError, 1); /* check reference */ if (error == NULL) { /* free string and clean called variable */ axl_free (string); (* _error) = NULL; return; } error->code = code; error->defined = -346715; /* allocate enough memory */ error->error = string; /* set the error into the recevied reference */ (* _error ) = error; return; } /** * @brief Allows to check if the provided reference was used to report * an error. * * Those APIs that return an \ref axlError reference filled with the * textual error diagnostic, can take advantage of this function. It * Allows to check if the error was used to report an error, instead * of checking a returning value containing a particular error code. * * See \ref axl_error_new for more information. * * @param _error The error that is being checked. * * @return \ref axl_true if the error reference doesn't contains an * "ERROR" (an error wasn't reported), otherwise, \ref axl_false is * returned. */ axl_bool axl_error_was_ok (axlError * _error) { /* check if it was ok */ if (_error == NULL || _error->error == NULL || (_error->defined != -346715)) return axl_true; /* axl error is defined */ return axl_false; } /** * @brief Allows to get current error code from the given \ref axlError value. * * If the provided \ref axlError doesn't not contain a valid error * information, -1 is returned. Otherwise the specific error code is * returned. * * @param _error The \ref axlError to use, while getting error code * inside. * * @return The error code inside or -1 if fails. */ int axl_error_get_code (axlError * _error) { /* check received reference */ if (_error == NULL) return -1; return _error->code; } /** * @brief Allows to get current textual error string inside the given * \ref axlError value. * * @param _error The \ref axlError where the error string value will * be retrieved. * * @return The error code or the string "no string error defined" if * the given error doesn't contain any string information. You must * not deallocate memory returned by this function because it is an * internal copy. */ const char * axl_error_get (axlError * _error) { /* check received reference */ if (_error == NULL) return "no string error defined"; return _error->error; } /** * @brief Allows to release memory allocated by the given \ref * axlError variable. * * @param _error The axlError to deallocate. */ void axl_error_free (axlError * _error) { /* check for null reference received */ if (_error == NULL) return; /* release man with no mercy */ axl_free (_error->error); axl_free (_error); return; } /* @} */