File:  [ELWIX - Embedded LightWeight unIX -] / gpl / axl / src / axl_error.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 12:50:03 2012 UTC (12 years, 3 months ago) by misho
Branches: axl, MAIN
CVS tags: HEAD, AXL0_6_7
version 0.6.7

/*
 *  LibAxl:  Another XML library
 *  Copyright (C) 2006 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 <axl.h>

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;
}


/* @} */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>