ede/ede-bug-tools/ede-bug-report/xmlrpc-c/include/xmlrpc-c/util.h
2009-07-03 14:23:51 +00:00

329 lines
11 KiB
C

/*=============================================================================
xmlrpc-c/util.h
===============================================================================
This is the interface to the libxmlrpc_util library, which contains
utility routines that have nothing to do with XML-RPC. The library
exists because other Xmlrpc-c libraries use the utilities.
By Bryan Henderson, San Jose, CA 05.09.21.
Contributed to the public domain by its author.
=============================================================================*/
#ifndef XMLRPC_C_UTIL_H_INCLUDED
#define XMLRPC_C_UTIL_H_INCLUDED
#include <sys/types.h>
#include <stdarg.h>
#include <xmlrpc-c/config.h> /* Defines XMLRPC_HAVE_WCHAR */
#include <xmlrpc-c/c_util.h> /* for GNU_PRINTF_ATTR */
#if XMLRPC_HAVE_WCHAR
#include <wchar.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*=========================================================================
** C struct size computations
**=======================================================================*/
/* Use XMLRPC_STRUCT_MEMBER_SIZE() to determine how big a structure is
up to and including a specified member. E.g. if you have
struct mystruct {int red; int green; int blue};, then
XMLRPC_STRUCT_MEMBER_SIZE(mystruct, green) is (8).
*/
#define _XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) \
((size_t)(char*)&((TYPE *)0)->MBRNAME)
#define _XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME) \
sizeof(((TYPE *)0)->MBRNAME)
#define XMLRPC_STRUCTSIZE(TYPE, MBRNAME) \
(_XMLRPC_STRUCT_MEMBER_OFFSET(TYPE, MBRNAME) + \
_XMLRPC_STRUCT_MEMBER_SIZE(TYPE, MBRNAME))
/*=========================================================================
** Assertions and Debugging
**=========================================================================
** Note that an assertion is _not_ a directive to check a condition and
** crash if it isn't true. It is an assertion that the condition _is_
** true. This assertion helps people to read the code. The program
** may also check the assertion as it runs, and if it conflicts with reality,
** recognize that the program is incorrect and abort it. In practice,
** it does this checking when the program was compiled without the NDEBUG
** macro defined.
*/
#ifndef NDEBUG
#define XMLRPC_ASSERT(cond) \
do \
if (!(cond)) \
xmlrpc_assertion_failed(__FILE__, __LINE__); \
while (0)
#else
#define XMLRPC_ASSERT(cond) while (0) {}
#endif
void
xmlrpc_assertion_failed(const char * const fileName,
int const lineNumber);
/* Validate a pointer. */
#define XMLRPC_ASSERT_PTR_OK(ptr) \
XMLRPC_ASSERT((ptr) != NULL)
/*=========================================================================
** xmlrpc_env
**=========================================================================
** XML-RPC represents runtime errors as <fault> elements. These contain
** <faultCode> and <faultString> elements.
**
** Since we need as much thread-safety as possible, we borrow an idea from
** CORBA--we store exception information in an "environment" object.
** You'll pass this to many different functions, and it will get filled
** out appropriately.
**
** For example:
**
** xmlrpc_env env;
**
** xmlrpc_env_init(&env);
**
** xmlrpc_do_something(&env);
** if (env.fault_occurred)
** report_error_appropriately();
**
** xmlrpc_env_clean(&env);
*/
#define XMLRPC_INTERNAL_ERROR (-500)
#define XMLRPC_TYPE_ERROR (-501)
#define XMLRPC_INDEX_ERROR (-502)
#define XMLRPC_PARSE_ERROR (-503)
#define XMLRPC_NETWORK_ERROR (-504)
#define XMLRPC_TIMEOUT_ERROR (-505)
#define XMLRPC_NO_SUCH_METHOD_ERROR (-506)
#define XMLRPC_REQUEST_REFUSED_ERROR (-507)
#define XMLRPC_INTROSPECTION_DISABLED_ERROR (-508)
#define XMLRPC_LIMIT_EXCEEDED_ERROR (-509)
#define XMLRPC_INVALID_UTF8_ERROR (-510)
typedef struct _xmlrpc_env {
int fault_occurred;
int fault_code;
char * fault_string;
} xmlrpc_env;
/* Initialize and destroy the contents of the provided xmlrpc_env object.
** These functions will never fail. */
void xmlrpc_env_init (xmlrpc_env* env);
void xmlrpc_env_clean (xmlrpc_env* const env);
/* Fill out an xmlrpc_fault with the specified values, and set the
** fault_occurred flag. This function will make a private copy of 'string',
** so you retain responsibility for your copy. */
void
xmlrpc_env_set_fault(xmlrpc_env * const env,
int const faultCode,
const char * const faultDescription);
/* The same as the above, but using varargs */
void
xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP,
int const code,
const char * const format,
va_list const args);
/* The same as the above, but using a printf-style format string. */
void
xmlrpc_env_set_fault_formatted(xmlrpc_env * const envP,
int const code,
const char * const format,
...) GNU_PRINTF_ATTR(3,4);
/* This one infers XMLRPC_INTERNAL_ERROR and has a shorter name.
So a call takes up less source code space.
*/
void
xmlrpc_faultf(xmlrpc_env * const envP,
const char * const format,
...) GNU_PRINTF_ATTR(2,3);
/* A simple debugging assertion. */
#define XMLRPC_ASSERT_ENV_OK(envP) \
XMLRPC_ASSERT((envP) != NULL && \
(envP->fault_string == NULL) && \
!(envP)->fault_occurred)
/* This version must *not* interpret 'str' as a format string, to avoid
** several evil attacks. */
#define XMLRPC_FAIL(env,code,str) \
do { xmlrpc_env_set_fault((env),(code),(str)); goto cleanup; } while (0)
#define XMLRPC_FAIL1(env,code,str,arg1) \
do { \
xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1)); \
goto cleanup; \
} while (0)
#define XMLRPC_FAIL2(env,code,str,arg1,arg2) \
do { \
xmlrpc_env_set_fault_formatted((env),(code),(str),(arg1),(arg2)); \
goto cleanup; \
} while (0)
#define XMLRPC_FAIL3(env,code,str,arg1,arg2,arg3) \
do { \
xmlrpc_env_set_fault_formatted((env),(code), \
(str),(arg1),(arg2),(arg3)); \
goto cleanup; \
} while (0)
#if !defined(__cplusplus)
#if defined(__GNUC__)
#define XMLRPC_FAILF( env, code, fmt, ... ) \
do { \
xmlrpc_env_set_fault_formatted((env), (code), (fmt), \
##__VA_ARGS__ ); \
goto cleanup; \
} while (0)
#endif
#endif
#define XMLRPC_FAIL_IF_NULL(ptr,env,code,str) \
do { \
if ((ptr) == NULL) \
XMLRPC_FAIL((env),(code),(str)); \
} while (0)
#define XMLRPC_FAIL_IF_FAULT(env) \
do { if ((env)->fault_occurred) goto cleanup; } while (0)
/*=========================================================================
** xmlrpc_mem_block
**=========================================================================
** A resizable chunk of memory. This is mostly used internally, but it is
** also used by the public API in a few places.
** The struct fields are private!
*/
typedef struct _xmlrpc_mem_block {
size_t _size;
size_t _allocated;
void* _block;
} xmlrpc_mem_block;
/* Allocate a new xmlrpc_mem_block. */
xmlrpc_mem_block* xmlrpc_mem_block_new (xmlrpc_env* const env, size_t const size);
/* Destroy an existing xmlrpc_mem_block, and everything it contains. */
void xmlrpc_mem_block_free (xmlrpc_mem_block* const block);
/* Initialize the contents of the provided xmlrpc_mem_block. */
void xmlrpc_mem_block_init
(xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size);
/* Deallocate the contents of the provided xmlrpc_mem_block, but not the
** block itself. */
void xmlrpc_mem_block_clean (xmlrpc_mem_block* const block);
/* Get the size and contents of the xmlrpc_mem_block. */
size_t
xmlrpc_mem_block_size(const xmlrpc_mem_block * const block);
void *
xmlrpc_mem_block_contents(const xmlrpc_mem_block * const block);
/* Resize an xmlrpc_mem_block, preserving as much of the contents as
** possible. */
void xmlrpc_mem_block_resize
(xmlrpc_env* const env, xmlrpc_mem_block* const block, size_t const size);
/* Append data to an existing xmlrpc_mem_block. */
void xmlrpc_mem_block_append
(xmlrpc_env* const env, xmlrpc_mem_block* const block, const void * const data, size_t const len);
#define XMLRPC_MEMBLOCK_NEW(type,env,size) \
xmlrpc_mem_block_new((env), sizeof(type) * (size))
#define XMLRPC_MEMBLOCK_FREE(type,block) \
xmlrpc_mem_block_free(block)
#define XMLRPC_MEMBLOCK_INIT(type,env,block,size) \
xmlrpc_mem_block_init((env), (block), sizeof(type) * (size))
#define XMLRPC_MEMBLOCK_CLEAN(type,block) \
xmlrpc_mem_block_clean(block)
#define XMLRPC_MEMBLOCK_SIZE(type,block) \
(xmlrpc_mem_block_size(block) / sizeof(type))
#define XMLRPC_MEMBLOCK_CONTENTS(type,block) \
((type*) xmlrpc_mem_block_contents(block))
#define XMLRPC_MEMBLOCK_RESIZE(type,env,block,size) \
xmlrpc_mem_block_resize(env, block, sizeof(type) * (size))
#define XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size) \
xmlrpc_mem_block_append(env, block, data, sizeof(type) * (size))
/* Here are some backward compatibility definitions. These longer names
used to be the only ones and typed memory blocks were considered
special.
*/
#define XMLRPC_TYPED_MEM_BLOCK_NEW(type,env,size) \
XMLRPC_MEMBLOCK_NEW(type,env,size)
#define XMLRPC_TYPED_MEM_BLOCK_FREE(type,block) \
XMLRPC_MEMBLOCK_FREE(type,block)
#define XMLRPC_TYPED_MEM_BLOCK_INIT(type,env,block,size) \
XMLRPC_MEMBLOCK_INIT(type,env,block,size)
#define XMLRPC_TYPED_MEM_BLOCK_CLEAN(type,block) \
XMLRPC_MEMBLOCK_CLEAN(type,block)
#define XMLRPC_TYPED_MEM_BLOCK_SIZE(type,block) \
XMLRPC_MEMBLOCK_SIZE(type,block)
#define XMLRPC_TYPED_MEM_BLOCK_CONTENTS(type,block) \
XMLRPC_MEMBLOCK_CONTENTS(type,block)
#define XMLRPC_TYPED_MEM_BLOCK_RESIZE(type,env,block,size) \
XMLRPC_MEMBLOCK_RESIZE(type,env,block,size)
#define XMLRPC_TYPED_MEM_BLOCK_APPEND(type,env,block,data,size) \
XMLRPC_MEMBLOCK_APPEND(type,env,block,data,size)
/*=========================================================================
** UTF-8 Encoding and Decoding
**=======================================================================*/
void
xmlrpc_validate_utf8(xmlrpc_env * const envP,
const char * const utf8Data,
size_t const utf8Len);
/* Decode a UTF-8 string. */
xmlrpc_mem_block *
xmlrpc_utf8_to_wcs(xmlrpc_env * const envP,
const char * const utf8_data,
size_t const utf8_len);
/* Encode a UTF-8 string. */
#if XMLRPC_HAVE_WCHAR
xmlrpc_mem_block *
xmlrpc_wcs_to_utf8(xmlrpc_env * const envP,
const wchar_t * const wcsData,
size_t const wcsLen);
#endif
void
xmlrpc_force_to_utf8(char * const buffer);
void
xmlrpc_force_to_xml_chars(char * const buffer);
#ifdef __cplusplus
}
#endif
#endif