Helper functions, mainly from lasso.
This commit is contained in:
parent
eca29cd7c7
commit
7efde30caa
|
@ -0,0 +1,163 @@
|
|||
/* $Id$
|
||||
*
|
||||
* cv2extractor - A free implementation of a reader of Carte Vitale 2 cards.
|
||||
*
|
||||
* Copyright (C) 2015 Entr'ouvert
|
||||
* https://dev.entrouvert.org/projects/cv2extractor
|
||||
*
|
||||
* Authors: See AUTHORS file in top-level directory.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include "./utils.h"
|
||||
|
||||
/**
|
||||
* SECTION:utilities
|
||||
* @short_description: Misc functions used internally in Cv2extractor
|
||||
* @stability: Internal
|
||||
* @include: utils.h
|
||||
*/
|
||||
|
||||
/**
|
||||
* cv2extractor_safe_prefix_string:
|
||||
* @str: a C string
|
||||
* @length: the maximum length of an extract of the string
|
||||
*
|
||||
* Produce a limite length safe extract of a string, for debugging purpose. Special characters are
|
||||
* replaced by their C string 'quoting'.
|
||||
*
|
||||
* Return value: a C string, of size < @length where newline, carriage returns and tabs are replaced
|
||||
* by their C quotes.
|
||||
*/
|
||||
gchar*
|
||||
cv2extractor_safe_prefix_string(const gchar *str, gsize length)
|
||||
{
|
||||
GString *output;
|
||||
gchar *ret;
|
||||
gsize outputted = 0, i = 0;
|
||||
|
||||
if (str == NULL) {
|
||||
return strdup("NULL");
|
||||
}
|
||||
output = g_string_sized_new(length);
|
||||
for (i = 0; i < length && str[i] && outputted < length; i++) {
|
||||
gchar c = 0;
|
||||
guint len;
|
||||
|
||||
if ((guchar)str[i] < 128 && (guchar)str[i] > 31) {
|
||||
g_string_append_c(output, str[i]);
|
||||
outputted++;
|
||||
continue;
|
||||
}
|
||||
switch (str[i]) {
|
||||
case '\n':
|
||||
c = 'n';
|
||||
break;
|
||||
case '\t':
|
||||
c = 't';
|
||||
break;
|
||||
case '\r':
|
||||
c = 'r';
|
||||
}
|
||||
if (c) {
|
||||
if (outputted - length > 1) {
|
||||
g_string_append_c(output, '\\');
|
||||
g_string_append_c(output, c);
|
||||
outputted += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (c < 8) {
|
||||
len = 3;
|
||||
} else if (c < 64) {
|
||||
len = 4;
|
||||
} else {
|
||||
len = 5;
|
||||
}
|
||||
if (outputted - length >= len) {
|
||||
g_string_append_c(output, '\\');
|
||||
g_string_append_printf(output, "%o", (guint)str[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ret = output->str;
|
||||
cv2extractor_release_gstring(output, FALSE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cv2extractor_gobject_is_of_type:
|
||||
* @a: a #GObject object
|
||||
* @b: a #GType value
|
||||
*
|
||||
* Return true if object @a is of type @b.
|
||||
*
|
||||
* Return value: whether object @a is of type @b.
|
||||
*/
|
||||
int
|
||||
cv2extractor_gobject_is_of_type(GObject *a, GType b)
|
||||
{
|
||||
GType typeid = (GType)b;
|
||||
|
||||
if (a && G_IS_OBJECT(a)) {
|
||||
return G_OBJECT_TYPE(G_OBJECT(a)) == typeid ? 0 : 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
GObject*
|
||||
cv2extractor_extract_gtype_from_list(GType type, GList *list)
|
||||
{
|
||||
GList *needle;
|
||||
|
||||
needle = g_list_find_custom(list, (gconstpointer)type, (GCompareFunc)cv2extractor_gobject_is_of_type);
|
||||
if (needle) {
|
||||
return needle->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* cv2extractor_extract_gtype_from_list_or_new:
|
||||
* @type: a #GType
|
||||
* @list: a pointer to a #GList pointer variable
|
||||
* @create: whether to look up an object whose #GType is type, or to just create it.
|
||||
*
|
||||
* If create is TRUE, add a new object of type @type to @list and return it.
|
||||
* Otherwise try to look up an object of type @type, and if none is found add a new one and return
|
||||
* it.
|
||||
*
|
||||
* Return value: a #GObject of type @type.
|
||||
*/
|
||||
GObject *
|
||||
cv2extractor_extract_gtype_from_list_or_new(GType type, GList **list, gboolean create)
|
||||
{
|
||||
GObject *result = NULL;
|
||||
g_assert (list);
|
||||
|
||||
if (! create) {
|
||||
result = cv2extractor_extract_gtype_from_list(type, *list);
|
||||
}
|
||||
if (result == NULL) {
|
||||
result = g_object_new(type, NULL);
|
||||
cv2extractor_list_add_new_gobject(*list, result);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,696 @@
|
|||
/* $Id$
|
||||
*
|
||||
* cv2extractor - A free implementation of a reader of Carte Vitale 2 cards.
|
||||
*
|
||||
* Copyright (C) 2015 Entr'ouvert
|
||||
* https://dev.entrouvert.org/projects/cv2extractor
|
||||
*
|
||||
* Authors: See AUTHORS file in top-level directory.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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
|
||||
*/
|
||||
|
||||
#ifndef __CV2EXTRACTOR_UTILS_H__
|
||||
#define __CV2EXTRACTOR_UTILS_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#ifdef CV2EXTRACTOR_DEBUG
|
||||
#ifdef __GNUC__
|
||||
#define cv2extractor_check_type_equality(a,b) \
|
||||
{ \
|
||||
enum { TYPE_MISMATCH = (1 / __builtin_types_compatible_p(typeof(a), typeof(b))) }; \
|
||||
}
|
||||
#else
|
||||
#define cv2extractor_check_type_equality(a,b)
|
||||
#endif
|
||||
#else
|
||||
#define cv2extractor_check_type_equality(a,b)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define cv2extractor_check_type_equality2(a,b,c) \
|
||||
{ \
|
||||
enum { TYPE_MISMATCH = (1 / (__builtin_types_compatible_p(typeof(a), typeof(b))+__builtin_types_compatible_p(typeof(a), typeof(c)))) }; \
|
||||
}
|
||||
#else
|
||||
#define cv2extractor_check_type_equality2(a,b,c)
|
||||
#endif
|
||||
|
||||
#define cv2extractor_private_data(object) ((object)->private_data)
|
||||
|
||||
|
||||
#define cv2extractor_critical(message, args...) \
|
||||
g_log("cv2extractor", G_LOG_LEVEL_CRITICAL, message, ## args)
|
||||
|
||||
#define cv2extractor_warning(message, args...) \
|
||||
g_log("cv2extractor", G_LOG_LEVEL_WARNING, message, ## args)
|
||||
|
||||
#define cv2extractor_message(message, args...) \
|
||||
g_log("cv2extractor", G_LOG_LEVEL_MESSAGE, message, ## args)
|
||||
|
||||
/**
|
||||
* cv2extractor_ref:
|
||||
* @object: an object whose reference count must be incremented.
|
||||
*
|
||||
* Increment the reference count of an object, do not emit warning if it is NULL.
|
||||
*
|
||||
* Return value: the @object.
|
||||
*/
|
||||
#define cv2extractor_ref(object) ((object) != NULL ? (g_object_ref(object), object) : NULL)
|
||||
|
||||
/**
|
||||
* cv2extractor_unref:
|
||||
* @object: an object whose reference count must be decremented.
|
||||
*
|
||||
* Decrement the reference count of an object, do not emit warnings if it is NULL.
|
||||
*
|
||||
* Return value: the @object.
|
||||
*/
|
||||
#define cv2extractor_unref(object) ((object) != NULL ? (g_object_unref(object), object) : NULL)
|
||||
|
||||
/* Freeing */
|
||||
|
||||
/*
|
||||
* cv2extractor_release_xxx are macros which ensure you do not get 'double free' errors, they first check
|
||||
* that the variable is not NULL before calling the deallocation function, and after deallocation
|
||||
* they reset the variable to NULL, preventing 'double free'.
|
||||
*/
|
||||
#define cv2extractor_release(dest) \
|
||||
{ \
|
||||
if (dest) { \
|
||||
g_free(dest); dest = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_release_full(dest, free_function) \
|
||||
{ \
|
||||
if (dest) { \
|
||||
free_function(dest); dest = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_release_full2(dest, free_function, type) \
|
||||
{ \
|
||||
cv2extractor_check_type_equality(dest, type); \
|
||||
if (dest) { \
|
||||
free_function(dest); dest = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_release_gobject(dest) \
|
||||
{ \
|
||||
if (G_IS_OBJECT(dest) || dest == NULL) { \
|
||||
cv2extractor_release_full(dest, g_object_unref); \
|
||||
} else { \
|
||||
g_critical("Trying to unref a non GObject pointer file=%s:%u pointerbybname=%s pointer=%p", __FILE__, __LINE__, #dest, dest); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_release_string(dest) \
|
||||
cv2extractor_release_full(dest, g_free)
|
||||
|
||||
#define cv2extractor_release_list(dest) \
|
||||
cv2extractor_release_full2(dest, g_list_free, GList*)
|
||||
|
||||
#define cv2extractor_release_list_of_full(dest, free_function) \
|
||||
{ \
|
||||
GList **__tmp = &(dest); \
|
||||
if (*__tmp) { \
|
||||
g_list_foreach(*__tmp, (GFunc)free_function, NULL); \
|
||||
cv2extractor_release_list(*__tmp); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_release_list_of_strings(dest) \
|
||||
cv2extractor_release_list_of_full(dest, g_free)
|
||||
|
||||
#define cv2extractor_release_list_of_gobjects(dest) \
|
||||
cv2extractor_release_list_of_full(dest, g_object_unref)
|
||||
|
||||
#define cv2extractor_release_list_of_xml_node(dest) \
|
||||
cv2extractor_release_list_of_full(dest, xmlFreeNode)
|
||||
|
||||
#define cv2extractor_release_list_of_xml_node_list(dest) \
|
||||
cv2extractor_release_list_of_full(dest, xmlFreeNodeList)
|
||||
|
||||
#define cv2extractor_release_xml_node(node) \
|
||||
cv2extractor_release_full2(node, xmlFreeNode, xmlNodePtr)
|
||||
|
||||
#define cv2extractor_release_xml_node_list(node) \
|
||||
cv2extractor_release_full2(node, xmlFreeNodeList, xmlNodePtr)
|
||||
|
||||
#define cv2extractor_release_doc(doc) \
|
||||
cv2extractor_release_full2(doc, xmlFreeDoc, xmlDocPtr)
|
||||
|
||||
#define cv2extractor_release_xml_string(dest) \
|
||||
cv2extractor_release_full2(dest, xmlFree, xmlChar*)
|
||||
|
||||
#define cv2extractor_release_encrypt_context(dest) \
|
||||
cv2extractor_release_full2(dest, xmlSecEncCtxDestroy, xmlSecEncCtxPtr)
|
||||
|
||||
#define cv2extractor_release_signature_context(dest) \
|
||||
cv2extractor_release_full2(dest, xmlSecDSigCtxDestroy,xmlSecDSigCtxPtr)
|
||||
|
||||
#define cv2extractor_release_key_manager(dest) \
|
||||
cv2extractor_release_full2(dest, xmlSecKeysMngrDestroy, xmlSecKeysMngrPtr)
|
||||
|
||||
#define cv2extractor_release_output_buffer(dest) \
|
||||
cv2extractor_release_full2(dest, xmlOutputBufferClose, xmlOutputBufferPtr)
|
||||
|
||||
#define cv2extractor_release_xpath_object(dest) \
|
||||
cv2extractor_release_full2(dest, xmlXPathFreeObject, xmlXPathObjectPtr)
|
||||
|
||||
#define cv2extractor_release_xpath_context(dest) \
|
||||
cv2extractor_release_full2(dest, xmlXPathFreeContext, xmlXPathContextPtr)
|
||||
|
||||
#define cv2extractor_release_xpath_job(xpathObject, xpathContext, xmlDocument) \
|
||||
cv2extractor_release_xpath_object(xpathObject); \
|
||||
cv2extractor_release_xpath_context(xpathContext); \
|
||||
cv2extractor_release_doc(xmlDocument)
|
||||
|
||||
#define cv2extractor_release_sec_key(dest) \
|
||||
cv2extractor_release_full2(dest, xmlSecKeyDestroy, xmlSecKeyPtr)
|
||||
|
||||
#define cv2extractor_release_ghashtable(dest) \
|
||||
cv2extractor_release_full(dest, g_hash_table_destroy)
|
||||
|
||||
#define cv2extractor_release_gstring(dest, b) \
|
||||
{ \
|
||||
GString **__tmp = &(dest); \
|
||||
if (*__tmp) {\
|
||||
g_string_free(*__tmp, (b)); \
|
||||
*__tmp = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Assignment and list appending */
|
||||
/*
|
||||
* cv2extractor_assign_xxx macros ensure that you dot leak previous value of assigned things, they use
|
||||
* cv2extractor_release_xxx macros to deallocate, they also ensure proper reference counting on passed by
|
||||
* references values and proper copying on passed by value values.
|
||||
*/
|
||||
#define cv2extractor_assign_string(dest,src) \
|
||||
{ \
|
||||
char *__tmp = g_strdup(src);\
|
||||
cv2extractor_release_string(dest); \
|
||||
dest = __tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_xml_string(dest,src) \
|
||||
{ \
|
||||
xmlChar *__tmp = xmlStrdup(src); \
|
||||
cv2extractor_release_xml_string(dest); \
|
||||
dest = __tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_string(dest,src) \
|
||||
{ \
|
||||
char *__tmp = src; \
|
||||
if (dest != __tmp) \
|
||||
cv2extractor_release_string(dest); \
|
||||
dest = __tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_gobject(dest,src) \
|
||||
{ \
|
||||
GObject *__tmp = G_OBJECT(src); \
|
||||
if (__tmp) \
|
||||
g_object_ref(__tmp); \
|
||||
cv2extractor_release_gobject(dest); \
|
||||
dest = (void*)(__tmp); \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_gobject(dest,src) \
|
||||
{ \
|
||||
GObject *__tmp = G_OBJECT(src); \
|
||||
if (dest != (void*)__tmp) \
|
||||
cv2extractor_release_gobject(dest); \
|
||||
dest = (void*)(__tmp); \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_xml_node(dest,src) \
|
||||
{ \
|
||||
xmlNode *__tmp = (src); \
|
||||
cv2extractor_check_type_equality(dest, src); \
|
||||
if (dest) \
|
||||
xmlFreeNode(dest); \
|
||||
dest = xmlCopyNode(__tmp, 1); \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_xml_node(dest,src) \
|
||||
{ \
|
||||
xmlNode *__tmp = (src); \
|
||||
cv2extractor_check_type_equality(dest, src); \
|
||||
if (dest) \
|
||||
xmlFreeNode(dest); \
|
||||
dest = __tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_xml_node_list(dest,src) \
|
||||
{ \
|
||||
xmlNode *__tmp = (src); \
|
||||
cv2extractor_check_type_equality(dest, src); \
|
||||
if (dest) \
|
||||
xmlFreeNode(dest); \
|
||||
dest = xmlCopyNodeList(__tmp); \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_xml_node_list(dest,src) \
|
||||
cv2extractor_assign_new_xml(dest, src)
|
||||
|
||||
#define cv2extractor_assign_list(dest, src) \
|
||||
{ \
|
||||
GList **__tmp = &(dest); \
|
||||
if (*__tmp) \
|
||||
g_list_free(*__tmp); \
|
||||
*__tmp = g_list_copy((src)); \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_list_of_gobjects(dest, src) \
|
||||
{ \
|
||||
GList *__tmp = (src); \
|
||||
cv2extractor_release_list_of_gobjects(dest); \
|
||||
dest = (GList*)__tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_list_of_strings(dest, src) \
|
||||
{ \
|
||||
GList *__tmp = (src); \
|
||||
cv2extractor_release_list_of_strings(dest); \
|
||||
dest = (GList*)__tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_list_of_xml_node(dest, src) \
|
||||
{ \
|
||||
GList *__tmp = (src); \
|
||||
cv2extractor_release_list_of_xml_node(dest); \
|
||||
dest = (GList*)__tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_list_of_gobjects(dest, src) \
|
||||
{ \
|
||||
GList *__tmp = (src); \
|
||||
cv2extractor_release_list_of_gobjects(dest); \
|
||||
dest = g_list_copy(__tmp); \
|
||||
for (;__tmp != NULL; __tmp = g_list_next(__tmp)) { \
|
||||
if (G_IS_OBJECT(__tmp->data)) { \
|
||||
g_object_ref(__tmp->data); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_list_of_strings(dest, src) \
|
||||
{ \
|
||||
GList *__tmp = src; \
|
||||
GList *__iter_dest; \
|
||||
cv2extractor_release_list_of_strings(dest); \
|
||||
dest = g_list_copy(__tmp); \
|
||||
for (__iter_dest = dest ; __iter_dest != NULL ; __iter_dest = g_list_next(__iter_dest)) { \
|
||||
__iter_dest->data = g_strdup(__iter_dest->data); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_new_sec_key(dest, src) \
|
||||
{ \
|
||||
xmlSecKey *__tmp = (src); \
|
||||
if (dest) \
|
||||
cv2extractor_release_sec_key(dest); \
|
||||
dest = __tmp; \
|
||||
}
|
||||
|
||||
#define cv2extractor_assign_sec_key(dest, src) \
|
||||
{ \
|
||||
xmlSecKey *__tmp = xmlSecKeyDuplicate(src); \
|
||||
if (dest) \
|
||||
cv2extractor_release_sec_key(dest); \
|
||||
dest = __tmp; \
|
||||
}
|
||||
|
||||
/* List appending */
|
||||
|
||||
/* cv2extractor_list_add_xxx macros, simplify code around list manipulation (g_list_append needs to be
|
||||
* used like this 'l = g_list_appen(l, value)' ) and ensure proper reference count or copying of
|
||||
* values.
|
||||
*/
|
||||
#define cv2extractor_list_add(dest, src) \
|
||||
{ \
|
||||
cv2extractor_check_type_equality((src), void*); \
|
||||
dest = g_list_append(dest, (src)); \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_non_null(dest, src) \
|
||||
{ \
|
||||
void *__tmp_non_null_src = (src); \
|
||||
if (__tmp_non_null_src != NULL) { \
|
||||
dest = g_list_append(dest, __tmp_non_null_src); \
|
||||
} else { \
|
||||
g_critical("Adding a NULL value to a non-NULL content list: dest=%s src=%s", #dest, #src); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_string(dest, src) \
|
||||
{ \
|
||||
cv2extractor_list_add_non_null(dest, g_strdup(src));\
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_new_string(dest, src) \
|
||||
{ \
|
||||
gchar *__tmp = src; \
|
||||
cv2extractor_list_add_non_null(dest, __tmp); \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_xml_string(dest, src) \
|
||||
{\
|
||||
xmlChar *__tmp_src = (src);\
|
||||
cv2extractor_list_add_non_null(dest, (void*)g_strdup((char*)__tmp_src));\
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_gobject(dest, src) \
|
||||
{ \
|
||||
void *__tmp_src = (src); \
|
||||
if (G_IS_OBJECT(__tmp_src)) { \
|
||||
dest = g_list_append(dest, g_object_ref(__tmp_src)); \
|
||||
} else { \
|
||||
g_critical("Trying to add to a GList* a non GObject pointer dest=%s src=%s", #dest, #src); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_new_gobject(dest, src) \
|
||||
{ \
|
||||
void *__tmp_src = (src); \
|
||||
if (G_IS_OBJECT(__tmp_src)) { \
|
||||
dest = g_list_append(dest, __tmp_src); \
|
||||
} else { \
|
||||
g_critical("Trying to add to a GList* a non GObject pointer dest=%s src=%s", #dest, #src); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_xml_node(dest, src) \
|
||||
{ \
|
||||
xmlNode *__tmp_src = xmlCopyNode(src, 1); \
|
||||
cv2extractor_list_add_non_null(dest, __tmp_src); \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_new_xml_node(dest, src) \
|
||||
{ \
|
||||
xmlNode *__tmp_src = src; \
|
||||
cv2extractor_list_add_non_null(dest, __tmp_src); \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_xml_node_list(dest, src) \
|
||||
{ \
|
||||
xmlNode *__tmp_src = xmlCopyNodeList(src); \
|
||||
cv2extractor_list_add_non_null(dest, __tmp_src); \
|
||||
}
|
||||
|
||||
#define cv2extractor_list_add_new_xml_node_list(dest, src) \
|
||||
cv2extractor_list_add_new_xml_node(dest, src)
|
||||
|
||||
#define cv2extractor_list_add_gstrv(dest, src) \
|
||||
{ \
|
||||
GList **__tmp_dest = &(dest); \
|
||||
const char **__iter = (const char**)(src); \
|
||||
while (__iter && *__iter) { \
|
||||
cv2extractor_list_add_string(*__tmp_dest, *__iter); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* List element removal */
|
||||
#define cv2extractor_list_remove_gobject(list, gobject) \
|
||||
do { void *__tmp = gobject; GList **__tmp_list = &(list); \
|
||||
*__tmp_list = g_list_remove(*__tmp_list, __tmp); \
|
||||
cv2extractor_unref(__tmp); } while(0)
|
||||
|
||||
/* Pointer ownership transfer */
|
||||
|
||||
/* cv2extractor_transfer_xxx macros are like cv2extractor_assign_xxx but they do not increment reference count or
|
||||
* copy the source value, instead they steal the value (and set the source to NULL, preventing stale
|
||||
* references).
|
||||
*/
|
||||
#define cv2extractor_transfer_full(dest, src, kind) \
|
||||
{\
|
||||
cv2extractor_release_##kind((dest)); \
|
||||
cv2extractor_check_type_equality(dest, src); \
|
||||
(dest) = (void*)(src); \
|
||||
(src) = NULL; \
|
||||
}
|
||||
|
||||
#define cv2extractor_transfer_xpath_object(dest, src) \
|
||||
cv2extractor_transfer_full(dest, src, xpath_object)
|
||||
|
||||
#define cv2extractor_transfer_string(dest, src) \
|
||||
cv2extractor_transfer_full(dest, src, string)
|
||||
|
||||
#define cv2extractor_transfer_gobject(dest, src) \
|
||||
cv2extractor_transfer_full(dest, src, gobject)
|
||||
|
||||
/* Node extraction */
|
||||
#define cv2extractor_extract_node_or_fail(to, from, kind, error) \
|
||||
{\
|
||||
void *__tmp = (from); \
|
||||
if (CV2EXTRACTOR_IS_##kind(__tmp)) { \
|
||||
to = CV2EXTRACTOR_##kind(__tmp); \
|
||||
} else { \
|
||||
rc = error; \
|
||||
goto cleanup; \
|
||||
}\
|
||||
}
|
||||
|
||||
/* Bad param handling */
|
||||
#define cv2extractor_return_val_if_invalid_param(kind, name, val) \
|
||||
g_return_val_if_fail(CV2EXTRACTOR_IS_##kind(name), val)
|
||||
|
||||
#define cv2extractor_bad_param(kind, name) \
|
||||
cv2extractor_return_val_if_invalid_param(kind, name, \
|
||||
CV2EXTRACTOR_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
|
||||
|
||||
#define cv2extractor_null_param(name) \
|
||||
g_return_val_if_fail(name != NULL, CV2EXTRACTOR_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
|
||||
|
||||
/**
|
||||
* cv2extractor_check_non_empty_string:
|
||||
* @str: a char pointer
|
||||
*
|
||||
* Check that @str is non-NULL and not empty, otherwise jump to cleanup and return
|
||||
* CV2EXTRACTOR_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ.
|
||||
*/
|
||||
#define cv2extractor_check_non_empty_string(str) \
|
||||
goto_cleanup_if_fail_with_rc(! cv2extractor_strisempty(str), \
|
||||
CV2EXTRACTOR_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
|
||||
|
||||
/*
|
||||
* We extensively use goto operator but in a formalized way, i.e. only for error checking code
|
||||
* paths.
|
||||
*
|
||||
* The next macros goto_cleanup_xxxx encapsulate idioms used in cv2extractor, like checking for a condition
|
||||
* or setting the return code which must be called 'rc' and be of an 'int' type.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following macros are made to create some formalism for function's cleanup code.
|
||||
*
|
||||
* The exit label should be called 'cleanup'. And for functions returning an integer error code, the
|
||||
* error code should be named 'rc' and 'return rc;' should be the last statement of the function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* goto_cleanup_with_rc:
|
||||
* @rc_value: integer return value
|
||||
*
|
||||
* This macro jump to the 'cleanup' label and set the return value to @rc_value.
|
||||
*
|
||||
*/
|
||||
#define goto_cleanup_with_rc(rc_value) \
|
||||
do {\
|
||||
rc = (rc_value); \
|
||||
goto cleanup; \
|
||||
} while(0);
|
||||
|
||||
/**
|
||||
* goto_cleanup_if_fail:
|
||||
* @condition: a boolean condition
|
||||
*
|
||||
* Jump to the 'cleanup' label if the @condition is FALSE.
|
||||
*
|
||||
*/
|
||||
#define goto_cleanup_if_fail(condition) \
|
||||
{\
|
||||
if (! (condition) ) {\
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* goto_cleanup_if_fail_with_rc:
|
||||
* @condition: a boolean condition
|
||||
* @rc_value: integer return value
|
||||
*
|
||||
* Jump to the 'cleanup' label if the @condition is FALSE and set the return value to
|
||||
* @rc_value.
|
||||
*
|
||||
*/
|
||||
#define goto_cleanup_if_fail_with_rc(condition, rc_value) \
|
||||
{\
|
||||
if (! (condition) ) {\
|
||||
rc = (rc_value); \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* goto_cleanup_if_fail_with_rc_with_warning:
|
||||
* @condition: a boolean condition
|
||||
* @rc_value: integer return value
|
||||
*
|
||||
* Jump to the 'cleanup' label if the @condition is FALSE and set the return value to
|
||||
* @rc_value. Also emit a warning, showing the condition and the return value.
|
||||
*
|
||||
*/
|
||||
#define goto_cleanup_if_fail_with_rc_with_warning(condition, rc_value) \
|
||||
{\
|
||||
if (! (condition) ) {\
|
||||
g_warning("%s failed, returning %s", #condition, #rc_value);\
|
||||
rc = (rc_value); \
|
||||
goto cleanup; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* goto_cleanup_with_rc_with_critical:
|
||||
* @message: a critical message
|
||||
* @rc_value: integer return value
|
||||
*
|
||||
* Jump to the 'cleanup' label and set the return value to
|
||||
* @rc_value. Also emit a critical, showing the message and the return value.
|
||||
*
|
||||
*/
|
||||
#define goto_cleanup_with_rc_with_critical(message, rc_value) \
|
||||
{\
|
||||
g_critical("%s, returning %s", #message, #rc_value);\
|
||||
rc = (rc_value); \
|
||||
goto cleanup; \
|
||||
}
|
||||
|
||||
/**
|
||||
* check_good_rc:
|
||||
* @what: a call to a function returning a cv2extractor error code
|
||||
*
|
||||
* Check if return code is 0, if not store it in rc and jump to cleanup label.
|
||||
*/
|
||||
#define cv2extractor_check_good_rc(what) \
|
||||
{ \
|
||||
int __rc = (what);\
|
||||
goto_cleanup_if_fail_with_rc(__rc == 0, __rc); \
|
||||
}
|
||||
|
||||
/*#define cv2extractor_mem_debug(who, what, where) \
|
||||
{ \
|
||||
if (cv2extractor_flag_memory_debug) \
|
||||
fprintf(stderr, " freeing %s/%s (at %p)\n", who, what, (void*)where); \
|
||||
}*/
|
||||
|
||||
/**
|
||||
* cv2extractor_foreach:
|
||||
* @_iter: a #GList variable, which will server to traverse @_list
|
||||
* @_list: a #GList value, which we will traverse
|
||||
*
|
||||
* Traverse a #GList list using 'for' construct. It must be followed by a block or a statement.
|
||||
*/
|
||||
#define cv2extractor_foreach(_iter, _list) \
|
||||
for (_iter = (_list); _iter; _iter = g_list_next(_iter))
|
||||
|
||||
/**
|
||||
* cv2extractor_foreach_full_begin:
|
||||
* @_type: the type of the variable @_data
|
||||
* @_data: the name of the variable to define to store data values
|
||||
* @_iter: the name of the variable to define to store the iterator
|
||||
* @_list: the GList* to iterate
|
||||
*
|
||||
* Traverse a GList* @_list, using @_iter as iteration variable extract data field to variable
|
||||
* @_data of type @_type.
|
||||
*/
|
||||
#define cv2extractor_foreach_full_begin(_type, _data, _iter, _list) \
|
||||
{ \
|
||||
_type _data = NULL; \
|
||||
GList *_iter = NULL; \
|
||||
for (_iter = (_list); _iter && ((_data = _iter->data), 1); _iter = g_list_next(_iter)) \
|
||||
{
|
||||
|
||||
#define cv2extractor_foreach_full_end() \
|
||||
} }
|
||||
|
||||
/**
|
||||
* cv2extractor_list_get_first_child:
|
||||
* @list:(allowed-none): a #GList node or NULL.
|
||||
*
|
||||
* Return the first child in a list, or NULL.
|
||||
*/
|
||||
#define cv2extractor_list_get_first_child(list) \
|
||||
((list) ? (list)->data : NULL)
|
||||
|
||||
/* Get a printable extract for error messages */
|
||||
char* cv2extractor_safe_prefix_string(const char *str, gsize length);
|
||||
|
||||
int cv2extractor_gobject_is_of_type(GObject *a, GType b);
|
||||
|
||||
GObject *cv2extractor_extract_gtype_from_list(GType type, GList *list);
|
||||
|
||||
GObject * cv2extractor_extract_gtype_from_list_or_new(GType type, GList **list, gboolean create);
|
||||
|
||||
/* Get first node of this type in a list */
|
||||
/* ex: cv2extractor_extract_node (Cv2extractorNode, CV2EXTRACTOR_TYPE_NODE, list) */
|
||||
#define cv2extractor_extract_gobject_from_list(type, gobjecttype, list) \
|
||||
((type*) cv2extractor_extract_gtype_from_list(gobjecttype, list))
|
||||
|
||||
/*
|
||||
* Simplify simple accessors argument checking.
|
||||
*
|
||||
*/
|
||||
#define cv2extractor_return_val_if_fail(assertion, value) \
|
||||
if (!(assertion)) return (value);
|
||||
|
||||
#define cv2extractor_return_null_if_fail(assertion) \
|
||||
cv2extractor_return_val_if_fail(assertion, NULL)
|
||||
|
||||
#define cv2extractor_return_if_fail(assertion) \
|
||||
if (!(assertion)) return;
|
||||
|
||||
/*#define cv2extractor_trace(args...) \
|
||||
if (cv2extractor_flag_memory_debug) { \
|
||||
fprintf(stderr, ## args); \
|
||||
}*/
|
||||
|
||||
/* Cv2extractor string data helpers */
|
||||
inline static gboolean
|
||||
cv2extractor_strisequal(const char *a, const char *b) {
|
||||
return (g_strcmp0(a,b) == 0);
|
||||
}
|
||||
inline static gboolean
|
||||
cv2extractor_strisnotequal(const char *a, const char *b) {
|
||||
return ! cv2extractor_strisequal(a,b);
|
||||
}
|
||||
inline static gboolean
|
||||
cv2extractor_strisempty(const char *str) {
|
||||
return ((str) == NULL || (str)[0] == '\0');
|
||||
}
|
||||
/*inline static gboolean
|
||||
cv2extractor_xmlstrisnotequal(const xmlChar *a, const xmlChar *b) {
|
||||
return cv2extractor_strisnotequal((char*)a, (char*)b);
|
||||
}*/
|
||||
|
||||
#endif /* __CV2EXTRACTOR_UTILS_H__ */
|
Reference in New Issue