gnucash/libgnucash/engine/qofutil.cpp
Geert Janssens 1238b9d8cd Prevent gcc from searching config.h in the current directory
This will avoid a ninja-build from picking up a config.h generated by the autotools build
(in the root build directory). Picking up the wrong config.h may lead to all kinds of
subtle issues if the autotools run was done with different options than the cmake run.
2017-10-26 14:05:17 +02:00

279 lines
7.4 KiB
C++

/********************************************************************\
* qofutil.c -- QOF utility functions *
* Copyright (C) 1997 Robin D. Clark *
* Copyright (C) 1997-2001,2004 Linas Vepstas <linas@linas.org> *
* Copyright 2006 Neil Williams <linux@codehelp.co.uk> *
* *
* 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 2 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, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
* Author: Rob Clark (rclark@cs.hmc.edu) *
* Author: Linas Vepstas (linas@linas.org) *
\********************************************************************/
#include <config.h>
#include <ctype.h>
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "qof.h"
#include "qof-backend.hpp"
G_GNUC_UNUSED static QofLogModule log_module = QOF_MOD_UTIL;
void
g_hash_table_foreach_sorted(GHashTable *hash_table, GHFunc func, gpointer user_data, GCompareFunc compare_func)
{
GList *iter;
GList *keys = g_list_sort(g_hash_table_get_keys(hash_table), compare_func);
for (iter = keys; iter; iter = iter->next)
{
func(iter->data, g_hash_table_lookup(hash_table, iter->data), user_data);
}
g_list_free(keys);
}
gboolean
qof_utf8_substr_nocase (const gchar *haystack, const gchar *needle)
{
gchar *haystack_casefold, *haystack_normalized;
gchar *needle_casefold, *needle_normalized;
gchar *p;
g_return_val_if_fail (haystack && needle, FALSE);
haystack_casefold = g_utf8_casefold (haystack, -1);
haystack_normalized = g_utf8_normalize (haystack_casefold, -1,
G_NORMALIZE_ALL);
g_free (haystack_casefold);
needle_casefold = g_utf8_casefold (needle, -1);
needle_normalized = g_utf8_normalize (needle_casefold, -1, G_NORMALIZE_ALL);
g_free (needle_casefold);
p = strstr (haystack_normalized, needle_normalized);
g_free (haystack_normalized);
g_free (needle_normalized);
return p != NULL;
}
/** Use g_utf8_casefold and g_utf8_collate to compare two utf8 strings,
* ignore case. Return < 0 if da compares before db, 0 if they compare
* equal, > 0 if da compares after db. */
static gint
qof_utf8_strcasecmp (const gchar *da, const gchar *db)
{
gchar *da_casefold, *db_casefold;
gint retval;
g_return_val_if_fail (da != NULL, 0);
g_return_val_if_fail (db != NULL, 0);
da_casefold = g_utf8_casefold (da, -1);
db_casefold = g_utf8_casefold (db, -1);
retval = g_utf8_collate (da_casefold, db_casefold);
g_free (da_casefold);
g_free (db_casefold);
return retval;
}
gint
safe_strcasecmp (const gchar * da, const gchar * db)
{
if ((da) && (db))
{
if ((da) != (db))
{
gint retval = qof_utf8_strcasecmp ((da), (db));
/* if strings differ, return */
if (retval) return retval;
}
}
else if ((!(da)) && (db))
{
return -1;
}
else if ((da) && (!(db)))
{
return +1;
}
return 0;
}
gint
null_strcmp (const gchar * da, const gchar * db)
{
if (da && db) return strcmp (da, db);
if (!da && db && 0 == db[0]) return 0;
if (!db && da && 0 == da[0]) return 0;
if (!da && db) return -1;
if (da && !db) return +1;
return 0;
}
#define MAX_DIGITS 50
/* inverse of strtoul */
gchar *
ultostr (gulong val, gint base)
{
gchar buf[MAX_DIGITS];
gulong broke[MAX_DIGITS];
gint i;
gulong places = 0, reval;
if ((2 > base) || (36 < base)) return NULL;
/* count digits */
places = 0;
for (i = 0; i < MAX_DIGITS; i++)
{
broke[i] = val;
places ++;
val /= base;
if (0 == val) break;
}
/* normalize */
reval = 0;
for (i = places - 2; i >= 0; i--)
{
reval += broke[i+1];
reval *= base;
broke[i] -= reval;
}
/* print */
for (i = 0; i < (gint)places; i++)
{
if (10 > broke[i])
{
buf[places-1-i] = 0x30 + broke[i]; /* ascii digit zero */
}
else
{
buf[places-1-i] = 0x41 - 10 + broke[i]; /* ascii capital A */
}
}
buf[places] = 0x0;
return g_strdup (buf);
}
/* =================================================================== */
/* returns TRUE if the string is a number, possibly with whitespace */
/* =================================================================== */
gboolean
gnc_strisnum(const gchar *s)
{
if (s == NULL) return FALSE;
if (*s == 0) return FALSE;
while (*s && isspace(*s))
s++;
if (*s == 0) return FALSE;
if (!isdigit(*s)) return FALSE;
while (*s && isdigit(*s))
s++;
if (*s == 0) return TRUE;
while (*s && isspace(*s))
s++;
if (*s == 0) return TRUE;
return FALSE;
}
/* =================================================================== */
/* Return NULL if the field is whitespace (blank, tab, formfeed etc.)
* Else return pointer to first non-whitespace character. */
/* =================================================================== */
G_GNUC_UNUSED static const gchar *
qof_util_whitespace_filter (const gchar * val)
{
size_t len;
if (!val) return NULL;
len = strspn (val, "\a\b\t\n\v\f\r ");
if (0 == val[len]) return NULL;
return val + len;
}
#ifdef THESE_CAN_BE_USEFUL_FOR_DEGUGGING
static guint g_str_hash_KEY(gconstpointer v)
{
return g_str_hash(v);
}
static guint g_str_hash_VAL(gconstpointer v)
{
return g_str_hash(v);
}
static gpointer g_strdup_VAL(gpointer v)
{
return g_strdup(v);
}
static gpointer g_strdup_KEY(gpointer v)
{
return g_strdup(v);
}
static void g_free_VAL(gpointer v)
{
return g_free(v);
}
static void g_free_KEY(gpointer v)
{
return g_free(v);
}
static gboolean qof_util_str_equal(gconstpointer v, gconstpointer v2)
{
return (v && v2) ? g_str_equal(v, v2) : FALSE;
}
#endif
void
qof_init (void)
{
qof_log_init();
qof_string_cache_init();
qof_object_initialize ();
qof_query_init ();
qof_book_register ();
}
void
qof_close(void)
{
qof_query_shutdown ();
qof_object_shutdown ();
QofBackend::release_backends();
qof_string_cache_destroy ();
qof_log_shutdown();
}
/* ************************ END OF FILE ***************************** */