mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
[ Very late checkin ]
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com> * Released 1.2.10 * NEWS: Update * configure.in: Up micro/interface-age/binary-age to 10.
This commit is contained in:
parent
05693cc388
commit
1f2b1ef109
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
@ -1,3 +1,11 @@
|
||||
Thu Mar 15 10:37:49 2001 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* Released 1.2.10
|
||||
|
||||
* NEWS: Update
|
||||
|
||||
* configure.in: Up micro/interface-age/binary-age to 10.
|
||||
|
||||
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
|
||||
|
2
HACKING
2
HACKING
@ -31,5 +31,3 @@ options like --prefix=/usr to configure you can give those options
|
||||
to autogen.sh and they will be passed on to configure.
|
||||
|
||||
For information about submitting patches see the README file.
|
||||
|
||||
|
||||
|
4
INSTALL
4
INSTALL
@ -1,8 +1,8 @@
|
||||
Simple install procedure
|
||||
========================
|
||||
|
||||
% gzip -cd glib-1.2.9.tar.gz | tar xvf - # unpack the sources
|
||||
% cd glib-1.2.9 # change to the toplevel directory
|
||||
% gzip -cd glib-1.2.10.tar.gz | tar xvf - # unpack the sources
|
||||
% cd glib-1.2.10 # change to the toplevel directory
|
||||
% ./configure # run the `configure' script
|
||||
% make # build GLIB
|
||||
|
||||
|
5
NEWS
5
NEWS
@ -1,3 +1,8 @@
|
||||
Overview of Changes in GLib 1.2.10:
|
||||
|
||||
* Fix compilation problem on some compilers where
|
||||
g_log_domain_gmodule was not being declared properly.
|
||||
|
||||
Overview of Changes in GLib 1.2.9:
|
||||
|
||||
* Move include files into a glib-1-2/ subdir to support parallel
|
||||
|
2
README
2
README
@ -1,7 +1,7 @@
|
||||
General Information
|
||||
===================
|
||||
|
||||
This is GLib version 1.2.9. GLib is a library which includes support
|
||||
This is GLib version 1.2.10. GLib is a library which includes support
|
||||
routines for C such as lists, trees, hashes, memory allocation, and
|
||||
many other things.
|
||||
|
||||
|
@ -33,9 +33,9 @@ AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl
|
||||
#
|
||||
GLIB_MAJOR_VERSION=1
|
||||
GLIB_MINOR_VERSION=2
|
||||
GLIB_MICRO_VERSION=9
|
||||
GLIB_INTERFACE_AGE=9
|
||||
GLIB_BINARY_AGE=9
|
||||
GLIB_MICRO_VERSION=10
|
||||
GLIB_INTERFACE_AGE=10
|
||||
GLIB_BINARY_AGE=10
|
||||
GLIB_VERSION=$GLIB_MAJOR_VERSION.$GLIB_MINOR_VERSION.$GLIB_MICRO_VERSION
|
||||
dnl
|
||||
AC_DIVERT_POP()dnl
|
||||
|
130
glib/Makefile.am
130
glib/Makefile.am
@ -1,130 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
# require automake 1.4
|
||||
AUTOMAKE_OPTIONS = 1.4
|
||||
|
||||
SUBDIRS = . gmodule gthread docs tests
|
||||
|
||||
configincludedir = $(pkglibdir)/include
|
||||
|
||||
bin_SCRIPTS=glib-config
|
||||
BUILT_SOURCES=glib-config
|
||||
glib-config: glib-config.in
|
||||
|
||||
INCLUDES = -DG_LOG_DOMAIN=g_log_domain_glib @GLIB_DEBUG_FLAGS@
|
||||
|
||||
EXTRA_DIST = \
|
||||
glib.m4 \
|
||||
glib.spec.in \
|
||||
acglib.m4 \
|
||||
sanity_check \
|
||||
README.win32 \
|
||||
glib.def \
|
||||
makefile.msc.in \
|
||||
makefile.msc \
|
||||
giowin32.c \
|
||||
glibconfig.h.win32 \
|
||||
glibconfig.h.win32.in \
|
||||
config.h.win32 \
|
||||
config.h.win32.in \
|
||||
glib.pc.in \
|
||||
gmodule.pc.in \
|
||||
gthread.pc.in
|
||||
|
||||
|
||||
lib_LTLIBRARIES = libglib.la
|
||||
|
||||
libglib_la_SOURCES = \
|
||||
garray.c \
|
||||
gcache.c \
|
||||
gcompletion.c \
|
||||
gdataset.c \
|
||||
gdate.c \
|
||||
gerror.c \
|
||||
ghash.c \
|
||||
ghook.c \
|
||||
giochannel.c \
|
||||
giounix.c \
|
||||
glist.c \
|
||||
gmain.c \
|
||||
gmem.c \
|
||||
gmessages.c \
|
||||
gmutex.c \
|
||||
gnode.c \
|
||||
gprimes.c \
|
||||
grel.c \
|
||||
gscanner.c \
|
||||
gslist.c \
|
||||
gstrfuncs.c \
|
||||
gstring.c \
|
||||
gtimer.c \
|
||||
gtree.c \
|
||||
gutils.c
|
||||
|
||||
glibincludedir=$(includedir)/glib-1.2
|
||||
glibinclude_HEADERS = \
|
||||
glib.h
|
||||
|
||||
configinclude_DATA = \
|
||||
glibconfig.h
|
||||
|
||||
CONFIGURE_DEPENDENCIES = acglib.m4
|
||||
|
||||
BUILT_SOURCES = stamp-gc-h #note: not glibconfig.h
|
||||
glibconfig.h: stamp-gc-h
|
||||
@:
|
||||
stamp-gc-h: config.status
|
||||
CONFIG_FILES= CONFIG_HEADERS= CONFIG_OTHER=glibconfig.h ./config.status
|
||||
echo timestamp > stamp-gc-h
|
||||
|
||||
libglib_la_LDFLAGS = \
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
|
||||
-release $(LT_RELEASE) \
|
||||
-export-dynamic
|
||||
|
||||
noinst_PROGRAMS = testglib testgdate testgdateparser
|
||||
testglib_LDADD = libglib.la
|
||||
testgdate_LDADD = libglib.la
|
||||
testgdateparser_LDADD = libglib.la
|
||||
|
||||
m4datadir = $(datadir)/aclocal
|
||||
m4data_DATA = glib.m4
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = glib.pc gmodule.pc gthread.pc
|
||||
|
||||
glibconfig.h.win32: $(top_builddir)/config.status $(top_srcdir)/glibconfig.h.win32.in
|
||||
cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
config.h.win32: $(top_builddir)/config.status $(top_srcdir)/config.h.win32.in
|
||||
cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
makefile.msc: $(top_builddir)/config.status $(top_srcdir)/makefile.msc.in
|
||||
cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
.PHONY: files release sanity snapshot
|
||||
|
||||
files:
|
||||
@files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
|
||||
echo $$p; \
|
||||
done
|
||||
|
||||
release:
|
||||
rm -rf .deps */.deps
|
||||
cd docs && make glib.html
|
||||
$(MAKE) distcheck
|
||||
|
||||
sanity:
|
||||
./sanity_check $(VERSION)
|
||||
|
||||
snapshot:
|
||||
$(MAKE) dist distdir=$(PACKAGE)`date +"%y%m%d"`
|
||||
|
||||
dist-hook: glib.spec
|
||||
if test -e $(srcdir)/INSTALL.in && test -e $(srcdir)/README.in ; then \
|
||||
CONFIG_FILES="INSTALL:$(srcdir)/INSTALL.in README:$(srcdir)/README.in" \
|
||||
CONFIG_HEADERS= \
|
||||
$(SHELL) config.status \
|
||||
&& cp INSTALL README $(distdir) ; \
|
||||
fi \
|
||||
&& cp glib.spec $(distdir)
|
490
glib/garray.c
490
glib/garray.c
@ -1,490 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
#define MIN_ARRAY_SIZE 16
|
||||
|
||||
|
||||
typedef struct _GRealArray GRealArray;
|
||||
|
||||
struct _GRealArray
|
||||
{
|
||||
guint8 *data;
|
||||
guint len;
|
||||
guint alloc;
|
||||
guint elt_size;
|
||||
guint zero_terminated : 1;
|
||||
guint clear : 1;
|
||||
};
|
||||
|
||||
|
||||
static gint g_nearest_pow (gint num);
|
||||
static void g_array_maybe_expand (GRealArray *array,
|
||||
gint len);
|
||||
|
||||
static GMemChunk *array_mem_chunk = NULL;
|
||||
G_LOCK_DEFINE_STATIC (array_mem_chunk);
|
||||
|
||||
GArray*
|
||||
g_array_new (gboolean zero_terminated,
|
||||
gboolean clear,
|
||||
guint elt_size)
|
||||
{
|
||||
GRealArray *array;
|
||||
|
||||
G_LOCK (array_mem_chunk);
|
||||
if (!array_mem_chunk)
|
||||
array_mem_chunk = g_mem_chunk_new ("array mem chunk",
|
||||
sizeof (GRealArray),
|
||||
1024, G_ALLOC_AND_FREE);
|
||||
|
||||
array = g_chunk_new (GRealArray, array_mem_chunk);
|
||||
G_UNLOCK (array_mem_chunk);
|
||||
|
||||
array->data = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
array->zero_terminated = (zero_terminated ? 1 : 0);
|
||||
array->clear = (clear ? 1 : 0);
|
||||
array->elt_size = elt_size;
|
||||
|
||||
return (GArray*) array;
|
||||
}
|
||||
|
||||
void
|
||||
g_array_free (GArray *array,
|
||||
gboolean free_segment)
|
||||
{
|
||||
if (free_segment)
|
||||
g_free (array->data);
|
||||
|
||||
G_LOCK (array_mem_chunk);
|
||||
g_mem_chunk_free (array_mem_chunk, array);
|
||||
G_UNLOCK (array_mem_chunk);
|
||||
}
|
||||
|
||||
GArray*
|
||||
g_array_append_vals (GArray *farray,
|
||||
gconstpointer data,
|
||||
guint len)
|
||||
{
|
||||
GRealArray *array = (GRealArray*) farray;
|
||||
|
||||
g_array_maybe_expand (array, len);
|
||||
|
||||
memcpy (array->data + array->elt_size * array->len, data, array->elt_size * len);
|
||||
|
||||
array->len += len;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
GArray*
|
||||
g_array_prepend_vals (GArray *farray,
|
||||
gconstpointer data,
|
||||
guint len)
|
||||
{
|
||||
GRealArray *array = (GRealArray*) farray;
|
||||
|
||||
g_array_maybe_expand (array, len);
|
||||
|
||||
g_memmove (array->data + array->elt_size * len, array->data, array->elt_size * array->len);
|
||||
|
||||
memcpy (array->data, data, len * array->elt_size);
|
||||
|
||||
array->len += len;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
GArray*
|
||||
g_array_insert_vals (GArray *farray,
|
||||
guint index,
|
||||
gconstpointer data,
|
||||
guint len)
|
||||
{
|
||||
GRealArray *array = (GRealArray*) farray;
|
||||
|
||||
g_array_maybe_expand (array, len);
|
||||
|
||||
g_memmove (array->data + array->elt_size * (len + index),
|
||||
array->data + array->elt_size * index,
|
||||
array->elt_size * (array->len - index));
|
||||
|
||||
memcpy (array->data + array->elt_size * index, data, len * array->elt_size);
|
||||
|
||||
array->len += len;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
GArray*
|
||||
g_array_set_size (GArray *farray,
|
||||
guint length)
|
||||
{
|
||||
GRealArray *array = (GRealArray*) farray;
|
||||
|
||||
if (array->len < length)
|
||||
g_array_maybe_expand (array, length - array->len);
|
||||
|
||||
array->len = length;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
GArray*
|
||||
g_array_remove_index (GArray* farray,
|
||||
guint index)
|
||||
{
|
||||
GRealArray* array = (GRealArray*) farray;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
g_return_val_if_fail (index < array->len, NULL);
|
||||
|
||||
if (index != array->len - 1)
|
||||
g_memmove (array->data + array->elt_size * index,
|
||||
array->data + array->elt_size * (index + 1),
|
||||
array->elt_size * (array->len - index - 1));
|
||||
|
||||
if (array->zero_terminated)
|
||||
memset (array->data + array->elt_size * (array->len - 1), 0,
|
||||
array->elt_size);
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
GArray*
|
||||
g_array_remove_index_fast (GArray* farray,
|
||||
guint index)
|
||||
{
|
||||
GRealArray* array = (GRealArray*) farray;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
g_return_val_if_fail (index < array->len, NULL);
|
||||
|
||||
if (index != array->len - 1)
|
||||
g_memmove (array->data + array->elt_size * index,
|
||||
array->data + array->elt_size * (array->len - 1),
|
||||
array->elt_size);
|
||||
|
||||
if (array->zero_terminated)
|
||||
memset (array->data + array->elt_size * (array->len - 1), 0,
|
||||
array->elt_size);
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
static gint
|
||||
g_nearest_pow (gint num)
|
||||
{
|
||||
gint n = 1;
|
||||
|
||||
while (n < num)
|
||||
n <<= 1;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
g_array_maybe_expand (GRealArray *array,
|
||||
gint len)
|
||||
{
|
||||
guint want_alloc = (array->len + len + array->zero_terminated) * array->elt_size;
|
||||
|
||||
if (want_alloc > array->alloc)
|
||||
{
|
||||
guint old_alloc = array->alloc;
|
||||
|
||||
array->alloc = g_nearest_pow (want_alloc);
|
||||
array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
|
||||
|
||||
array->data = g_realloc (array->data, array->alloc);
|
||||
|
||||
if (array->clear || array->zero_terminated)
|
||||
memset (array->data + old_alloc, 0, array->alloc - old_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pointer Array
|
||||
*/
|
||||
|
||||
typedef struct _GRealPtrArray GRealPtrArray;
|
||||
|
||||
struct _GRealPtrArray
|
||||
{
|
||||
gpointer *pdata;
|
||||
guint len;
|
||||
guint alloc;
|
||||
};
|
||||
|
||||
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
|
||||
gint len);
|
||||
|
||||
static GMemChunk *ptr_array_mem_chunk = NULL;
|
||||
G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
|
||||
|
||||
|
||||
GPtrArray*
|
||||
g_ptr_array_new (void)
|
||||
{
|
||||
GRealPtrArray *array;
|
||||
|
||||
G_LOCK (ptr_array_mem_chunk);
|
||||
if (!ptr_array_mem_chunk)
|
||||
ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
|
||||
sizeof (GRealPtrArray),
|
||||
1024, G_ALLOC_AND_FREE);
|
||||
|
||||
array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
|
||||
G_UNLOCK (ptr_array_mem_chunk);
|
||||
|
||||
array->pdata = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
|
||||
return (GPtrArray*) array;
|
||||
}
|
||||
|
||||
void
|
||||
g_ptr_array_free (GPtrArray *array,
|
||||
gboolean free_segment)
|
||||
{
|
||||
g_return_if_fail (array);
|
||||
|
||||
if (free_segment)
|
||||
g_free (array->pdata);
|
||||
|
||||
G_LOCK (ptr_array_mem_chunk);
|
||||
g_mem_chunk_free (ptr_array_mem_chunk, array);
|
||||
G_UNLOCK (ptr_array_mem_chunk);
|
||||
}
|
||||
|
||||
static void
|
||||
g_ptr_array_maybe_expand (GRealPtrArray *array,
|
||||
gint len)
|
||||
{
|
||||
guint old_alloc;
|
||||
|
||||
if ((array->len + len) > array->alloc)
|
||||
{
|
||||
old_alloc = array->alloc;
|
||||
|
||||
array->alloc = g_nearest_pow (array->len + len);
|
||||
array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
|
||||
if (array->pdata)
|
||||
array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc);
|
||||
else
|
||||
array->pdata = g_new0 (gpointer, array->alloc);
|
||||
|
||||
memset (array->pdata + old_alloc, 0,
|
||||
sizeof (gpointer) * (array->alloc - old_alloc));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_ptr_array_set_size (GPtrArray *farray,
|
||||
gint length)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
|
||||
g_return_if_fail (array);
|
||||
|
||||
if (length > array->len)
|
||||
g_ptr_array_maybe_expand (array, (length - array->len));
|
||||
|
||||
array->len = length;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_ptr_array_remove_index (GPtrArray* farray,
|
||||
guint index)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
gpointer result;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
g_return_val_if_fail (index < array->len, NULL);
|
||||
|
||||
result = array->pdata[index];
|
||||
|
||||
if (index != array->len - 1)
|
||||
g_memmove (array->pdata + index, array->pdata + index + 1,
|
||||
sizeof (gpointer) * (array->len - index - 1));
|
||||
|
||||
array->pdata[array->len - 1] = NULL;
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_ptr_array_remove_index_fast (GPtrArray* farray,
|
||||
guint index)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
gpointer result;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
g_return_val_if_fail (index < array->len, NULL);
|
||||
|
||||
result = array->pdata[index];
|
||||
|
||||
if (index != array->len - 1)
|
||||
array->pdata[index] = array->pdata[array->len - 1];
|
||||
|
||||
array->pdata[array->len - 1] = NULL;
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_ptr_array_remove (GPtrArray* farray,
|
||||
gpointer data)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (array, FALSE);
|
||||
|
||||
for (i = 0; i < array->len; i += 1)
|
||||
{
|
||||
if (array->pdata[i] == data)
|
||||
{
|
||||
g_ptr_array_remove_index (farray, i);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_ptr_array_remove_fast (GPtrArray* farray,
|
||||
gpointer data)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (array, FALSE);
|
||||
|
||||
for (i = 0; i < array->len; i += 1)
|
||||
{
|
||||
if (array->pdata[i] == data)
|
||||
{
|
||||
g_ptr_array_remove_index_fast (farray, i);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_ptr_array_add (GPtrArray* farray,
|
||||
gpointer data)
|
||||
{
|
||||
GRealPtrArray* array = (GRealPtrArray*) farray;
|
||||
|
||||
g_return_if_fail (array);
|
||||
|
||||
g_ptr_array_maybe_expand (array, 1);
|
||||
|
||||
array->pdata[array->len++] = data;
|
||||
}
|
||||
|
||||
/* Byte arrays
|
||||
*/
|
||||
|
||||
GByteArray* g_byte_array_new (void)
|
||||
{
|
||||
return (GByteArray*) g_array_new (FALSE, FALSE, 1);
|
||||
}
|
||||
|
||||
void g_byte_array_free (GByteArray *array,
|
||||
gboolean free_segment)
|
||||
{
|
||||
g_array_free ((GArray*) array, free_segment);
|
||||
}
|
||||
|
||||
GByteArray* g_byte_array_append (GByteArray *array,
|
||||
const guint8 *data,
|
||||
guint len)
|
||||
{
|
||||
g_array_append_vals ((GArray*) array, (guint8*)data, len);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
GByteArray* g_byte_array_prepend (GByteArray *array,
|
||||
const guint8 *data,
|
||||
guint len)
|
||||
{
|
||||
g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
GByteArray* g_byte_array_set_size (GByteArray *array,
|
||||
guint length)
|
||||
{
|
||||
g_array_set_size ((GArray*) array, length);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
||||
guint index)
|
||||
{
|
||||
g_array_remove_index((GArray*) array, index);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
||||
guint index)
|
||||
{
|
||||
g_array_remove_index_fast((GArray*) array, index);
|
||||
|
||||
return array;
|
||||
}
|
230
glib/gcache.c
230
glib/gcache.c
@ -1,230 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
typedef struct _GCacheNode GCacheNode;
|
||||
typedef struct _GRealCache GRealCache;
|
||||
|
||||
struct _GCacheNode
|
||||
{
|
||||
/* A reference counted node */
|
||||
gpointer value;
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
struct _GRealCache
|
||||
{
|
||||
/* Called to create a value from a key */
|
||||
GCacheNewFunc value_new_func;
|
||||
|
||||
/* Called to destroy a value */
|
||||
GCacheDestroyFunc value_destroy_func;
|
||||
|
||||
/* Called to duplicate a key */
|
||||
GCacheDupFunc key_dup_func;
|
||||
|
||||
/* Called to destroy a key */
|
||||
GCacheDestroyFunc key_destroy_func;
|
||||
|
||||
/* Associates keys with nodes */
|
||||
GHashTable *key_table;
|
||||
|
||||
/* Associates nodes with keys */
|
||||
GHashTable *value_table;
|
||||
};
|
||||
|
||||
|
||||
static GCacheNode* g_cache_node_new (gpointer value);
|
||||
static void g_cache_node_destroy (GCacheNode *node);
|
||||
|
||||
|
||||
static GMemChunk *node_mem_chunk = NULL;
|
||||
G_LOCK_DEFINE_STATIC (node_mem_chunk);
|
||||
|
||||
GCache*
|
||||
g_cache_new (GCacheNewFunc value_new_func,
|
||||
GCacheDestroyFunc value_destroy_func,
|
||||
GCacheDupFunc key_dup_func,
|
||||
GCacheDestroyFunc key_destroy_func,
|
||||
GHashFunc hash_key_func,
|
||||
GHashFunc hash_value_func,
|
||||
GCompareFunc key_compare_func)
|
||||
{
|
||||
GRealCache *cache;
|
||||
|
||||
g_return_val_if_fail (value_new_func != NULL, NULL);
|
||||
g_return_val_if_fail (value_destroy_func != NULL, NULL);
|
||||
g_return_val_if_fail (key_dup_func != NULL, NULL);
|
||||
g_return_val_if_fail (key_destroy_func != NULL, NULL);
|
||||
g_return_val_if_fail (hash_key_func != NULL, NULL);
|
||||
g_return_val_if_fail (hash_value_func != NULL, NULL);
|
||||
g_return_val_if_fail (key_compare_func != NULL, NULL);
|
||||
|
||||
cache = g_new (GRealCache, 1);
|
||||
cache->value_new_func = value_new_func;
|
||||
cache->value_destroy_func = value_destroy_func;
|
||||
cache->key_dup_func = key_dup_func;
|
||||
cache->key_destroy_func = key_destroy_func;
|
||||
cache->key_table = g_hash_table_new (hash_key_func, key_compare_func);
|
||||
cache->value_table = g_hash_table_new (hash_value_func, NULL);
|
||||
|
||||
return (GCache*) cache;
|
||||
}
|
||||
|
||||
void
|
||||
g_cache_destroy (GCache *cache)
|
||||
{
|
||||
GRealCache *rcache;
|
||||
|
||||
g_return_if_fail (cache != NULL);
|
||||
|
||||
rcache = (GRealCache*) cache;
|
||||
g_hash_table_destroy (rcache->key_table);
|
||||
g_hash_table_destroy (rcache->value_table);
|
||||
g_free (rcache);
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_cache_insert (GCache *cache,
|
||||
gpointer key)
|
||||
{
|
||||
GRealCache *rcache;
|
||||
GCacheNode *node;
|
||||
gpointer value;
|
||||
|
||||
g_return_val_if_fail (cache != NULL, NULL);
|
||||
|
||||
rcache = (GRealCache*) cache;
|
||||
|
||||
node = g_hash_table_lookup (rcache->key_table, key);
|
||||
if (node)
|
||||
{
|
||||
node->ref_count += 1;
|
||||
return node->value;
|
||||
}
|
||||
|
||||
key = (* rcache->key_dup_func) (key);
|
||||
value = (* rcache->value_new_func) (key);
|
||||
node = g_cache_node_new (value);
|
||||
|
||||
g_hash_table_insert (rcache->key_table, key, node);
|
||||
g_hash_table_insert (rcache->value_table, value, key);
|
||||
|
||||
return node->value;
|
||||
}
|
||||
|
||||
void
|
||||
g_cache_remove (GCache *cache,
|
||||
gpointer value)
|
||||
{
|
||||
GRealCache *rcache;
|
||||
GCacheNode *node;
|
||||
gpointer key;
|
||||
|
||||
g_return_if_fail (cache != NULL);
|
||||
|
||||
rcache = (GRealCache*) cache;
|
||||
|
||||
key = g_hash_table_lookup (rcache->value_table, value);
|
||||
node = g_hash_table_lookup (rcache->key_table, key);
|
||||
|
||||
g_return_if_fail (node != NULL);
|
||||
|
||||
node->ref_count -= 1;
|
||||
if (node->ref_count == 0)
|
||||
{
|
||||
g_hash_table_remove (rcache->value_table, value);
|
||||
g_hash_table_remove (rcache->key_table, key);
|
||||
|
||||
(* rcache->key_destroy_func) (key);
|
||||
(* rcache->value_destroy_func) (node->value);
|
||||
g_cache_node_destroy (node);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_cache_key_foreach (GCache *cache,
|
||||
GHFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GRealCache *rcache;
|
||||
|
||||
g_return_if_fail (cache != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
rcache = (GRealCache*) cache;
|
||||
|
||||
g_hash_table_foreach (rcache->value_table, func, user_data);
|
||||
}
|
||||
|
||||
void
|
||||
g_cache_value_foreach (GCache *cache,
|
||||
GHFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GRealCache *rcache;
|
||||
|
||||
g_return_if_fail (cache != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
rcache = (GRealCache*) cache;
|
||||
|
||||
g_hash_table_foreach (rcache->key_table, func, user_data);
|
||||
}
|
||||
|
||||
|
||||
static GCacheNode*
|
||||
g_cache_node_new (gpointer value)
|
||||
{
|
||||
GCacheNode *node;
|
||||
|
||||
G_LOCK (node_mem_chunk);
|
||||
if (!node_mem_chunk)
|
||||
node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode),
|
||||
1024, G_ALLOC_AND_FREE);
|
||||
|
||||
node = g_chunk_new (GCacheNode, node_mem_chunk);
|
||||
G_UNLOCK (node_mem_chunk);
|
||||
|
||||
node->value = value;
|
||||
node->ref_count = 1;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
g_cache_node_destroy (GCacheNode *node)
|
||||
{
|
||||
G_LOCK (node_mem_chunk);
|
||||
g_mem_chunk_free (node_mem_chunk, node);
|
||||
G_UNLOCK (node_mem_chunk);
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
#include <string.h>
|
||||
|
||||
static void completion_check_cache (GCompletion* cmp,
|
||||
gchar** new_prefix);
|
||||
|
||||
GCompletion*
|
||||
g_completion_new (GCompletionFunc func)
|
||||
{
|
||||
GCompletion* gcomp;
|
||||
|
||||
gcomp = g_new (GCompletion, 1);
|
||||
gcomp->items = NULL;
|
||||
gcomp->cache = NULL;
|
||||
gcomp->prefix = NULL;
|
||||
gcomp->func = func;
|
||||
|
||||
return gcomp;
|
||||
}
|
||||
|
||||
void
|
||||
g_completion_add_items (GCompletion* cmp,
|
||||
GList* items)
|
||||
{
|
||||
GList* it;
|
||||
|
||||
g_return_if_fail (cmp != NULL);
|
||||
g_return_if_fail (items != NULL);
|
||||
|
||||
/* optimize adding to cache? */
|
||||
if (cmp->cache)
|
||||
{
|
||||
g_list_free (cmp->cache);
|
||||
cmp->cache = NULL;
|
||||
}
|
||||
|
||||
if (cmp->prefix)
|
||||
{
|
||||
g_free (cmp->prefix);
|
||||
cmp->prefix = NULL;
|
||||
}
|
||||
|
||||
it = items;
|
||||
while (it)
|
||||
{
|
||||
cmp->items = g_list_prepend (cmp->items, it->data);
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_completion_remove_items (GCompletion* cmp,
|
||||
GList* items)
|
||||
{
|
||||
GList* it;
|
||||
|
||||
g_return_if_fail (cmp != NULL);
|
||||
g_return_if_fail (items != NULL);
|
||||
|
||||
it = items;
|
||||
while (cmp->items && it)
|
||||
{
|
||||
cmp->items = g_list_remove (cmp->items, it->data);
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
it = items;
|
||||
while (cmp->cache && it)
|
||||
{
|
||||
cmp->cache = g_list_remove(cmp->cache, it->data);
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_completion_clear_items (GCompletion* cmp)
|
||||
{
|
||||
g_return_if_fail (cmp != NULL);
|
||||
|
||||
g_list_free (cmp->items);
|
||||
cmp->items = NULL;
|
||||
g_list_free (cmp->cache);
|
||||
cmp->cache = NULL;
|
||||
g_free (cmp->prefix);
|
||||
cmp->prefix = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
completion_check_cache (GCompletion* cmp,
|
||||
gchar** new_prefix)
|
||||
{
|
||||
register GList* list;
|
||||
register gint len;
|
||||
register gint i;
|
||||
register gint plen;
|
||||
gchar* postfix;
|
||||
gchar* s;
|
||||
|
||||
if (!new_prefix)
|
||||
return;
|
||||
if (!cmp->cache)
|
||||
{
|
||||
*new_prefix = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(cmp->prefix);
|
||||
list = cmp->cache;
|
||||
s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
|
||||
postfix = s + len;
|
||||
plen = strlen (postfix);
|
||||
list = list->next;
|
||||
|
||||
while (list && plen)
|
||||
{
|
||||
s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
|
||||
s += len;
|
||||
for (i = 0; i < plen; ++i)
|
||||
{
|
||||
if (postfix[i] != s[i])
|
||||
break;
|
||||
}
|
||||
plen = i;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
*new_prefix = g_new0 (gchar, len + plen + 1);
|
||||
strncpy (*new_prefix, cmp->prefix, len);
|
||||
strncpy (*new_prefix + len, postfix, plen);
|
||||
}
|
||||
|
||||
GList*
|
||||
g_completion_complete (GCompletion* cmp,
|
||||
gchar* prefix,
|
||||
gchar** new_prefix)
|
||||
{
|
||||
gint plen, len;
|
||||
gint done = 0;
|
||||
GList* list;
|
||||
|
||||
g_return_val_if_fail (cmp != NULL, NULL);
|
||||
g_return_val_if_fail (prefix != NULL, NULL);
|
||||
|
||||
len = strlen (prefix);
|
||||
if (cmp->prefix && cmp->cache)
|
||||
{
|
||||
plen = strlen (cmp->prefix);
|
||||
if (plen <= len && !strncmp (prefix, cmp->prefix, plen))
|
||||
{
|
||||
/* use the cache */
|
||||
list = cmp->cache;
|
||||
while (list)
|
||||
{
|
||||
if (strncmp (prefix,
|
||||
cmp->func ? cmp->func (list->data) : (gchar*) list->data,
|
||||
len))
|
||||
{
|
||||
list = g_list_remove_link (cmp->cache, list);
|
||||
if (list != cmp->cache)
|
||||
cmp->cache = list;
|
||||
}
|
||||
else
|
||||
list = list->next;
|
||||
}
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
{
|
||||
/* normal code */
|
||||
g_list_free (cmp->cache);
|
||||
cmp->cache = NULL;
|
||||
list = cmp->items;
|
||||
while (*prefix && list)
|
||||
{
|
||||
if (!strncmp (prefix,
|
||||
cmp->func ? cmp->func (list->data) : (gchar*) list->data,
|
||||
len))
|
||||
cmp->cache = g_list_prepend (cmp->cache, list->data);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
if (cmp->prefix)
|
||||
{
|
||||
g_free (cmp->prefix);
|
||||
cmp->prefix = NULL;
|
||||
}
|
||||
if (cmp->cache)
|
||||
cmp->prefix = g_strdup (prefix);
|
||||
completion_check_cache (cmp, new_prefix);
|
||||
|
||||
return *prefix ? cmp->cache : cmp->items;
|
||||
}
|
||||
|
||||
void
|
||||
g_completion_free (GCompletion* cmp)
|
||||
{
|
||||
g_return_if_fail (cmp != NULL);
|
||||
|
||||
g_completion_clear_items (cmp);
|
||||
g_free (cmp);
|
||||
}
|
||||
|
||||
#ifdef TEST_COMPLETION
|
||||
#include <stdio.h>
|
||||
int
|
||||
main (int argc,
|
||||
char* argv[])
|
||||
{
|
||||
FILE *file;
|
||||
gchar buf[1024];
|
||||
GList *list;
|
||||
GList *result;
|
||||
GList *tmp;
|
||||
GCompletion *cmp;
|
||||
gint i;
|
||||
gchar *longp = NULL;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
g_warning ("Usage: %s filename prefix1 [prefix2 ...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
file = fopen (argv[1], "r");
|
||||
if (!file)
|
||||
{
|
||||
g_warning ("Cannot open %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmp = g_completion_new (NULL);
|
||||
list = g_list_alloc ();
|
||||
while (fgets (buf, 1024, file))
|
||||
{
|
||||
list->data = g_strdup (buf);
|
||||
g_completion_add_items (cmp, list);
|
||||
}
|
||||
fclose (file);
|
||||
|
||||
for (i = 2; i < argc; ++i)
|
||||
{
|
||||
printf ("COMPLETING: %s\n", argv[i]);
|
||||
result = g_completion_complete (cmp, argv[i], &longp);
|
||||
g_list_foreach (result, (GFunc) printf, NULL);
|
||||
printf ("LONG MATCH: %s\n", longp);
|
||||
g_free (longp);
|
||||
longp = NULL;
|
||||
}
|
||||
|
||||
g_list_foreach (cmp->items, (GFunc) g_free, NULL);
|
||||
g_completion_free (cmp);
|
||||
g_list_free (list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
611
glib/gdataset.c
611
glib/gdataset.c
@ -1,611 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* gdataset.c: Generic dataset mechanism, similar to GtkObject data.
|
||||
* Copyright (C) 1998 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe ; FIXME: might still freeze, watch out, not thoroughly
|
||||
* looked at yet.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
|
||||
/* --- defines --- */
|
||||
#define G_QUARK_BLOCK_SIZE (512)
|
||||
#define G_DATA_MEM_CHUNK_PREALLOC (128)
|
||||
#define G_DATA_CACHE_MAX (512)
|
||||
#define G_DATASET_MEM_CHUNK_PREALLOC (32)
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
typedef struct _GDataset GDataset;
|
||||
struct _GData
|
||||
{
|
||||
GData *next;
|
||||
GQuark id;
|
||||
gpointer data;
|
||||
GDestroyNotify destroy_func;
|
||||
};
|
||||
|
||||
struct _GDataset
|
||||
{
|
||||
gconstpointer location;
|
||||
GData *datalist;
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
|
||||
static inline void g_datalist_clear_i (GData **datalist);
|
||||
static void g_dataset_destroy_internal (GDataset *dataset);
|
||||
static inline void g_data_set_internal (GData **datalist,
|
||||
GQuark key_id,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_func,
|
||||
GDataset *dataset);
|
||||
static void g_data_initialize (void);
|
||||
static inline GQuark g_quark_new (gchar *string);
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
G_LOCK_DEFINE_STATIC (g_dataset_global);
|
||||
static GHashTable *g_dataset_location_ht = NULL;
|
||||
static GDataset *g_dataset_cached = NULL; /* should this be
|
||||
threadspecific? */
|
||||
static GMemChunk *g_dataset_mem_chunk = NULL;
|
||||
static GMemChunk *g_data_mem_chunk = NULL;
|
||||
static GData *g_data_cache = NULL;
|
||||
static guint g_data_cache_length = 0;
|
||||
|
||||
G_LOCK_DEFINE_STATIC (g_quark_global);
|
||||
static GHashTable *g_quark_ht = NULL;
|
||||
static gchar **g_quarks = NULL;
|
||||
static GQuark g_quark_seq_id = 0;
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
|
||||
/* HOLDS: g_dataset_global_lock */
|
||||
static inline void
|
||||
g_datalist_clear_i (GData **datalist)
|
||||
{
|
||||
register GData *list;
|
||||
|
||||
/* unlink *all* items before walking their destructors
|
||||
*/
|
||||
list = *datalist;
|
||||
*datalist = NULL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
register GData *prev;
|
||||
|
||||
prev = list;
|
||||
list = prev->next;
|
||||
|
||||
if (prev->destroy_func)
|
||||
{
|
||||
G_UNLOCK (g_dataset_global);
|
||||
prev->destroy_func (prev->data);
|
||||
G_LOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
if (g_data_cache_length < G_DATA_CACHE_MAX)
|
||||
{
|
||||
prev->next = g_data_cache;
|
||||
g_data_cache = prev;
|
||||
g_data_cache_length++;
|
||||
}
|
||||
else
|
||||
g_mem_chunk_free (g_data_mem_chunk, prev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_datalist_clear (GData **datalist)
|
||||
{
|
||||
g_return_if_fail (datalist != NULL);
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (!g_dataset_location_ht)
|
||||
g_data_initialize ();
|
||||
|
||||
while (*datalist)
|
||||
g_datalist_clear_i (datalist);
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
/* HOLDS: g_dataset_global_lock */
|
||||
static inline GDataset*
|
||||
g_dataset_lookup (gconstpointer dataset_location)
|
||||
{
|
||||
register GDataset *dataset;
|
||||
|
||||
if (g_dataset_cached && g_dataset_cached->location == dataset_location)
|
||||
return g_dataset_cached;
|
||||
|
||||
dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
|
||||
if (dataset)
|
||||
g_dataset_cached = dataset;
|
||||
|
||||
return dataset;
|
||||
}
|
||||
|
||||
/* HOLDS: g_dataset_global_lock */
|
||||
static void
|
||||
g_dataset_destroy_internal (GDataset *dataset)
|
||||
{
|
||||
register gconstpointer dataset_location;
|
||||
|
||||
dataset_location = dataset->location;
|
||||
while (dataset)
|
||||
{
|
||||
if (!dataset->datalist)
|
||||
{
|
||||
if (dataset == g_dataset_cached)
|
||||
g_dataset_cached = NULL;
|
||||
g_hash_table_remove (g_dataset_location_ht, dataset_location);
|
||||
g_mem_chunk_free (g_dataset_mem_chunk, dataset);
|
||||
break;
|
||||
}
|
||||
|
||||
g_datalist_clear_i (&dataset->datalist);
|
||||
dataset = g_dataset_lookup (dataset_location);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_dataset_destroy (gconstpointer dataset_location)
|
||||
{
|
||||
g_return_if_fail (dataset_location != NULL);
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (g_dataset_location_ht)
|
||||
{
|
||||
register GDataset *dataset;
|
||||
|
||||
dataset = g_dataset_lookup (dataset_location);
|
||||
if (dataset)
|
||||
g_dataset_destroy_internal (dataset);
|
||||
}
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
/* HOLDS: g_dataset_global_lock */
|
||||
static inline void
|
||||
g_data_set_internal (GData **datalist,
|
||||
GQuark key_id,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_func,
|
||||
GDataset *dataset)
|
||||
{
|
||||
register GData *list;
|
||||
|
||||
list = *datalist;
|
||||
if (!data)
|
||||
{
|
||||
register GData *prev;
|
||||
|
||||
prev = NULL;
|
||||
while (list)
|
||||
{
|
||||
if (list->id == key_id)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = list->next;
|
||||
else
|
||||
{
|
||||
*datalist = list->next;
|
||||
|
||||
/* the dataset destruction *must* be done
|
||||
* prior to invokation of the data destroy function
|
||||
*/
|
||||
if (!*datalist && dataset)
|
||||
g_dataset_destroy_internal (dataset);
|
||||
}
|
||||
|
||||
/* the GData struct *must* already be unlinked
|
||||
* when invoking the destroy function.
|
||||
* we use (data==NULL && destroy_func!=NULL) as
|
||||
* a special hint combination to "steal"
|
||||
* data without destroy notification
|
||||
*/
|
||||
if (list->destroy_func && !destroy_func)
|
||||
{
|
||||
G_UNLOCK (g_dataset_global);
|
||||
list->destroy_func (list->data);
|
||||
G_LOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
if (g_data_cache_length < G_DATA_CACHE_MAX)
|
||||
{
|
||||
list->next = g_data_cache;
|
||||
g_data_cache = list;
|
||||
g_data_cache_length++;
|
||||
}
|
||||
else
|
||||
g_mem_chunk_free (g_data_mem_chunk, list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
prev = list;
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
if (list->id == key_id)
|
||||
{
|
||||
if (!list->destroy_func)
|
||||
{
|
||||
list->data = data;
|
||||
list->destroy_func = destroy_func;
|
||||
}
|
||||
else
|
||||
{
|
||||
register GDestroyNotify dfunc;
|
||||
register gpointer ddata;
|
||||
|
||||
dfunc = list->destroy_func;
|
||||
ddata = list->data;
|
||||
list->data = data;
|
||||
list->destroy_func = destroy_func;
|
||||
|
||||
/* we need to have updated all structures prior to
|
||||
* invokation of the destroy function
|
||||
*/
|
||||
G_UNLOCK (g_dataset_global);
|
||||
dfunc (ddata);
|
||||
G_LOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (g_data_cache)
|
||||
{
|
||||
list = g_data_cache;
|
||||
g_data_cache = list->next;
|
||||
g_data_cache_length--;
|
||||
}
|
||||
else
|
||||
list = g_chunk_new (GData, g_data_mem_chunk);
|
||||
list->next = *datalist;
|
||||
list->id = key_id;
|
||||
list->data = data;
|
||||
list->destroy_func = destroy_func;
|
||||
*datalist = list;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_dataset_id_set_data_full (gconstpointer dataset_location,
|
||||
GQuark key_id,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_func)
|
||||
{
|
||||
register GDataset *dataset;
|
||||
|
||||
g_return_if_fail (dataset_location != NULL);
|
||||
if (!data)
|
||||
g_return_if_fail (destroy_func == NULL);
|
||||
if (!key_id)
|
||||
{
|
||||
if (data)
|
||||
g_return_if_fail (key_id > 0);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (!g_dataset_location_ht)
|
||||
g_data_initialize ();
|
||||
|
||||
dataset = g_dataset_lookup (dataset_location);
|
||||
if (!dataset)
|
||||
{
|
||||
dataset = g_chunk_new (GDataset, g_dataset_mem_chunk);
|
||||
dataset->location = dataset_location;
|
||||
g_datalist_init (&dataset->datalist);
|
||||
g_hash_table_insert (g_dataset_location_ht,
|
||||
(gpointer) dataset->location,
|
||||
dataset);
|
||||
}
|
||||
|
||||
g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
void
|
||||
g_datalist_id_set_data_full (GData **datalist,
|
||||
GQuark key_id,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_func)
|
||||
{
|
||||
g_return_if_fail (datalist != NULL);
|
||||
if (!data)
|
||||
g_return_if_fail (destroy_func == NULL);
|
||||
if (!key_id)
|
||||
{
|
||||
if (data)
|
||||
g_return_if_fail (key_id > 0);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (!g_dataset_location_ht)
|
||||
g_data_initialize ();
|
||||
|
||||
g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
void
|
||||
g_dataset_id_remove_no_notify (gconstpointer dataset_location,
|
||||
GQuark key_id)
|
||||
{
|
||||
g_return_if_fail (dataset_location != NULL);
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (key_id && g_dataset_location_ht)
|
||||
{
|
||||
GDataset *dataset;
|
||||
|
||||
dataset = g_dataset_lookup (dataset_location);
|
||||
if (dataset)
|
||||
g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
|
||||
}
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
void
|
||||
g_datalist_id_remove_no_notify (GData **datalist,
|
||||
GQuark key_id)
|
||||
{
|
||||
g_return_if_fail (datalist != NULL);
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (key_id && g_dataset_location_ht)
|
||||
g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_dataset_id_get_data (gconstpointer dataset_location,
|
||||
GQuark key_id)
|
||||
{
|
||||
g_return_val_if_fail (dataset_location != NULL, NULL);
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (key_id && g_dataset_location_ht)
|
||||
{
|
||||
register GDataset *dataset;
|
||||
|
||||
dataset = g_dataset_lookup (dataset_location);
|
||||
if (dataset)
|
||||
{
|
||||
register GData *list;
|
||||
|
||||
for (list = dataset->datalist; list; list = list->next)
|
||||
if (list->id == key_id)
|
||||
{
|
||||
G_UNLOCK (g_dataset_global);
|
||||
return list->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
G_UNLOCK (g_dataset_global);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_datalist_id_get_data (GData **datalist,
|
||||
GQuark key_id)
|
||||
{
|
||||
g_return_val_if_fail (datalist != NULL, NULL);
|
||||
|
||||
if (key_id)
|
||||
{
|
||||
register GData *list;
|
||||
|
||||
for (list = *datalist; list; list = list->next)
|
||||
if (list->id == key_id)
|
||||
return list->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
g_dataset_foreach (gconstpointer dataset_location,
|
||||
GDataForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
register GDataset *dataset;
|
||||
|
||||
g_return_if_fail (dataset_location != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
G_LOCK (g_dataset_global);
|
||||
if (g_dataset_location_ht)
|
||||
{
|
||||
dataset = g_dataset_lookup (dataset_location);
|
||||
G_UNLOCK (g_dataset_global);
|
||||
if (dataset)
|
||||
{
|
||||
register GData *list;
|
||||
|
||||
for (list = dataset->datalist; list; list = list->next)
|
||||
func (list->id, list->data, user_data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
G_UNLOCK (g_dataset_global);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_datalist_foreach (GData **datalist,
|
||||
GDataForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
register GData *list;
|
||||
|
||||
g_return_if_fail (datalist != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
for (list = *datalist; list; list = list->next)
|
||||
func (list->id, list->data, user_data);
|
||||
}
|
||||
|
||||
void
|
||||
g_datalist_init (GData **datalist)
|
||||
{
|
||||
g_return_if_fail (datalist != NULL);
|
||||
|
||||
*datalist = NULL;
|
||||
}
|
||||
|
||||
/* HOLDS: g_dataset_global_lock */
|
||||
static void
|
||||
g_data_initialize (void)
|
||||
{
|
||||
g_return_if_fail (g_dataset_location_ht == NULL);
|
||||
|
||||
g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
|
||||
g_dataset_cached = NULL;
|
||||
g_dataset_mem_chunk =
|
||||
g_mem_chunk_new ("GDataset MemChunk",
|
||||
sizeof (GDataset),
|
||||
sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC,
|
||||
G_ALLOC_AND_FREE);
|
||||
g_data_mem_chunk =
|
||||
g_mem_chunk_new ("GData MemChunk",
|
||||
sizeof (GData),
|
||||
sizeof (GData) * G_DATA_MEM_CHUNK_PREALLOC,
|
||||
G_ALLOC_AND_FREE);
|
||||
}
|
||||
|
||||
GQuark
|
||||
g_quark_try_string (const gchar *string)
|
||||
{
|
||||
GQuark quark = 0;
|
||||
g_return_val_if_fail (string != NULL, 0);
|
||||
|
||||
G_LOCK (g_quark_global);
|
||||
if (g_quark_ht)
|
||||
quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
|
||||
G_UNLOCK (g_quark_global);
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
GQuark
|
||||
g_quark_from_string (const gchar *string)
|
||||
{
|
||||
GQuark quark;
|
||||
|
||||
g_return_val_if_fail (string != NULL, 0);
|
||||
|
||||
G_LOCK (g_quark_global);
|
||||
if (g_quark_ht)
|
||||
quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
|
||||
else
|
||||
{
|
||||
g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
quark = 0;
|
||||
}
|
||||
|
||||
if (!quark)
|
||||
quark = g_quark_new (g_strdup (string));
|
||||
G_UNLOCK (g_quark_global);
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
GQuark
|
||||
g_quark_from_static_string (const gchar *string)
|
||||
{
|
||||
GQuark quark;
|
||||
|
||||
g_return_val_if_fail (string != NULL, 0);
|
||||
|
||||
G_LOCK (g_quark_global);
|
||||
if (g_quark_ht)
|
||||
quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
|
||||
else
|
||||
{
|
||||
g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
quark = 0;
|
||||
}
|
||||
|
||||
if (!quark)
|
||||
quark = g_quark_new ((gchar*) string);
|
||||
G_UNLOCK (g_quark_global);
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_quark_to_string (GQuark quark)
|
||||
{
|
||||
gchar* result = NULL;
|
||||
G_LOCK (g_quark_global);
|
||||
if (quark > 0 && quark <= g_quark_seq_id)
|
||||
result = g_quarks[quark - 1];
|
||||
G_UNLOCK (g_quark_global);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* HOLDS: g_quark_global_lock */
|
||||
static inline GQuark
|
||||
g_quark_new (gchar *string)
|
||||
{
|
||||
GQuark quark;
|
||||
|
||||
if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
|
||||
g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
|
||||
|
||||
g_quarks[g_quark_seq_id] = string;
|
||||
g_quark_seq_id++;
|
||||
quark = g_quark_seq_id;
|
||||
g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
|
||||
|
||||
return quark;
|
||||
}
|
1294
glib/gdate.c
1294
glib/gdate.c
File diff suppressed because it is too large
Load Diff
293
glib/gerror.c
293
glib/gerror.c
@ -1,293 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe ; except for g_on_error_stack_trace, but who wants thread safety
|
||||
* then
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "glib.h"
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIMES_H
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif /* HAVE_SYS_SELECT_H */
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
#include <string.h> /* for bzero on BSD systems */
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <process.h> /* For _getpid() */
|
||||
#endif
|
||||
|
||||
#ifndef NO_FD_SET
|
||||
# define SELECT_MASK fd_set
|
||||
#else
|
||||
# ifndef _AIX
|
||||
typedef long fd_mask;
|
||||
# endif
|
||||
# if defined(_IBMR2)
|
||||
# define SELECT_MASK void
|
||||
# else
|
||||
# define SELECT_MASK int
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
static void stack_trace (char **args);
|
||||
|
||||
extern volatile gboolean glib_on_error_halt;
|
||||
volatile gboolean glib_on_error_halt = TRUE;
|
||||
|
||||
void
|
||||
g_on_error_query (const gchar *prg_name)
|
||||
{
|
||||
static const gchar *query1 = "[E]xit, [H]alt";
|
||||
static const gchar *query2 = ", show [S]tack trace";
|
||||
static const gchar *query3 = " or [P]roceed";
|
||||
gchar buf[16];
|
||||
|
||||
if (!prg_name)
|
||||
prg_name = g_get_prgname ();
|
||||
|
||||
retry:
|
||||
|
||||
if (prg_name)
|
||||
fprintf (stdout,
|
||||
"%s (pid:%u): %s%s%s: ",
|
||||
prg_name,
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query2,
|
||||
query3);
|
||||
else
|
||||
fprintf (stdout,
|
||||
"(process:%u): %s%s: ",
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query3);
|
||||
fflush (stdout);
|
||||
|
||||
#ifndef NATIVE_WIN32
|
||||
if (isatty(0) && isatty(1))
|
||||
fgets (buf, 8, stdin);
|
||||
else
|
||||
strcpy (buf, "E\n");
|
||||
#else
|
||||
fgets (buf, 8, stdin);
|
||||
#endif
|
||||
|
||||
if ((buf[0] == 'E' || buf[0] == 'e')
|
||||
&& buf[1] == '\n')
|
||||
_exit (0);
|
||||
else if ((buf[0] == 'P' || buf[0] == 'p')
|
||||
&& buf[1] == '\n')
|
||||
return;
|
||||
else if (prg_name
|
||||
&& (buf[0] == 'S' || buf[0] == 's')
|
||||
&& buf[1] == '\n')
|
||||
{
|
||||
g_on_error_stack_trace (prg_name);
|
||||
goto retry;
|
||||
}
|
||||
else if ((buf[0] == 'H' || buf[0] == 'h')
|
||||
&& buf[1] == '\n')
|
||||
{
|
||||
while (glib_on_error_halt)
|
||||
;
|
||||
glib_on_error_halt = TRUE;
|
||||
return;
|
||||
}
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
void
|
||||
g_on_error_stack_trace (const gchar *prg_name)
|
||||
{
|
||||
#ifndef NATIVE_WIN32
|
||||
pid_t pid;
|
||||
gchar buf[16];
|
||||
gchar *args[4] = { "gdb", NULL, NULL, NULL };
|
||||
|
||||
if (!prg_name)
|
||||
return;
|
||||
|
||||
sprintf (buf, "%u", (guint) getpid ());
|
||||
|
||||
args[1] = (gchar*) prg_name;
|
||||
args[2] = buf;
|
||||
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
stack_trace (args);
|
||||
_exit (0);
|
||||
}
|
||||
else if (pid == (pid_t) -1)
|
||||
{
|
||||
perror ("unable to fork gdb");
|
||||
return;
|
||||
}
|
||||
|
||||
while (glib_on_error_halt)
|
||||
;
|
||||
glib_on_error_halt = TRUE;
|
||||
#else
|
||||
abort ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean stack_trace_done = FALSE;
|
||||
|
||||
static void
|
||||
stack_trace_sigchld (int signum)
|
||||
{
|
||||
stack_trace_done = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
stack_trace (char **args)
|
||||
{
|
||||
#ifndef NATIVE_WIN32
|
||||
pid_t pid;
|
||||
int in_fd[2];
|
||||
int out_fd[2];
|
||||
SELECT_MASK fdset;
|
||||
SELECT_MASK readset;
|
||||
struct timeval tv;
|
||||
int sel, index, state;
|
||||
char buffer[256];
|
||||
char c;
|
||||
|
||||
stack_trace_done = FALSE;
|
||||
signal (SIGCHLD, stack_trace_sigchld);
|
||||
|
||||
if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
|
||||
{
|
||||
perror ("unable to open pipe");
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
close (0); dup (in_fd[0]); /* set the stdin to the in pipe */
|
||||
close (1); dup (out_fd[1]); /* set the stdout to the out pipe */
|
||||
close (2); dup (out_fd[1]); /* set the stderr to the out pipe */
|
||||
|
||||
execvp (args[0], args); /* exec gdb */
|
||||
perror ("exec failed");
|
||||
_exit (0);
|
||||
}
|
||||
else if (pid == (pid_t) -1)
|
||||
{
|
||||
perror ("unable to fork");
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (out_fd[0], &fdset);
|
||||
|
||||
write (in_fd[1], "backtrace\n", 10);
|
||||
write (in_fd[1], "p x = 0\n", 8);
|
||||
write (in_fd[1], "quit\n", 5);
|
||||
|
||||
index = 0;
|
||||
state = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
readset = fdset;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
|
||||
if (sel == -1)
|
||||
break;
|
||||
|
||||
if ((sel > 0) && (FD_ISSET (out_fd[0], &readset)))
|
||||
{
|
||||
if (read (out_fd[0], &c, 1))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case 0:
|
||||
if (c == '#')
|
||||
{
|
||||
state = 1;
|
||||
index = 0;
|
||||
buffer[index++] = c;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
buffer[index++] = c;
|
||||
if ((c == '\n') || (c == '\r'))
|
||||
{
|
||||
buffer[index] = 0;
|
||||
fprintf (stdout, "%s", buffer);
|
||||
state = 0;
|
||||
index = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stack_trace_done)
|
||||
break;
|
||||
}
|
||||
|
||||
close (in_fd[0]);
|
||||
close (in_fd[1]);
|
||||
close (out_fd[0]);
|
||||
close (out_fd[1]);
|
||||
_exit (0);
|
||||
#else
|
||||
abort ();
|
||||
#endif
|
||||
}
|
404
glib/ghash.c
404
glib/ghash.c
@ -1,404 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
#define HASH_TABLE_MIN_SIZE 11
|
||||
#define HASH_TABLE_MAX_SIZE 13845163
|
||||
|
||||
|
||||
typedef struct _GHashNode GHashNode;
|
||||
|
||||
struct _GHashNode
|
||||
{
|
||||
gpointer key;
|
||||
gpointer value;
|
||||
GHashNode *next;
|
||||
};
|
||||
|
||||
struct _GHashTable
|
||||
{
|
||||
gint size;
|
||||
gint nnodes;
|
||||
guint frozen;
|
||||
GHashNode **nodes;
|
||||
GHashFunc hash_func;
|
||||
GCompareFunc key_compare_func;
|
||||
};
|
||||
|
||||
|
||||
static void g_hash_table_resize (GHashTable *hash_table);
|
||||
static GHashNode** g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
gconstpointer key);
|
||||
static GHashNode* g_hash_node_new (gpointer key,
|
||||
gpointer value);
|
||||
static void g_hash_node_destroy (GHashNode *hash_node);
|
||||
static void g_hash_nodes_destroy (GHashNode *hash_node);
|
||||
|
||||
|
||||
G_LOCK_DEFINE_STATIC (g_hash_global);
|
||||
|
||||
static GMemChunk *node_mem_chunk = NULL;
|
||||
static GHashNode *node_free_list = NULL;
|
||||
|
||||
|
||||
GHashTable*
|
||||
g_hash_table_new (GHashFunc hash_func,
|
||||
GCompareFunc key_compare_func)
|
||||
{
|
||||
GHashTable *hash_table;
|
||||
guint i;
|
||||
|
||||
hash_table = g_new (GHashTable, 1);
|
||||
hash_table->size = HASH_TABLE_MIN_SIZE;
|
||||
hash_table->nnodes = 0;
|
||||
hash_table->frozen = FALSE;
|
||||
hash_table->hash_func = hash_func ? hash_func : g_direct_hash;
|
||||
hash_table->key_compare_func = key_compare_func;
|
||||
hash_table->nodes = g_new (GHashNode*, hash_table->size);
|
||||
|
||||
for (i = 0; i < hash_table->size; i++)
|
||||
hash_table->nodes[i] = NULL;
|
||||
|
||||
return hash_table;
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_destroy (GHashTable *hash_table)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
for (i = 0; i < hash_table->size; i++)
|
||||
g_hash_nodes_destroy (hash_table->nodes[i]);
|
||||
|
||||
g_free (hash_table->nodes);
|
||||
g_free (hash_table);
|
||||
}
|
||||
|
||||
static inline GHashNode**
|
||||
g_hash_table_lookup_node (GHashTable *hash_table,
|
||||
gconstpointer key)
|
||||
{
|
||||
GHashNode **node;
|
||||
|
||||
node = &hash_table->nodes
|
||||
[(* hash_table->hash_func) (key) % hash_table->size];
|
||||
|
||||
/* Hash table lookup needs to be fast.
|
||||
* We therefore remove the extra conditional of testing
|
||||
* whether to call the key_compare_func or not from
|
||||
* the inner loop.
|
||||
*/
|
||||
if (hash_table->key_compare_func)
|
||||
while (*node && !(*hash_table->key_compare_func) ((*node)->key, key))
|
||||
node = &(*node)->next;
|
||||
else
|
||||
while (*node && (*node)->key != key)
|
||||
node = &(*node)->next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_hash_table_lookup (GHashTable *hash_table,
|
||||
gconstpointer key)
|
||||
{
|
||||
GHashNode *node;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, NULL);
|
||||
|
||||
node = *g_hash_table_lookup_node (hash_table, key);
|
||||
|
||||
return node ? node->value : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_insert (GHashTable *hash_table,
|
||||
gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
GHashNode **node;
|
||||
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
node = g_hash_table_lookup_node (hash_table, key);
|
||||
|
||||
if (*node)
|
||||
{
|
||||
/* do not reset node->key in this place, keeping
|
||||
* the old key might be intended.
|
||||
* a g_hash_table_remove/g_hash_table_insert pair
|
||||
* can be used otherwise.
|
||||
*
|
||||
* node->key = key; */
|
||||
(*node)->value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
*node = g_hash_node_new (key, value);
|
||||
hash_table->nnodes++;
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_remove (GHashTable *hash_table,
|
||||
gconstpointer key)
|
||||
{
|
||||
GHashNode **node, *dest;
|
||||
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
node = g_hash_table_lookup_node (hash_table, key);
|
||||
|
||||
if (*node)
|
||||
{
|
||||
dest = *node;
|
||||
(*node) = dest->next;
|
||||
g_hash_node_destroy (dest);
|
||||
hash_table->nnodes--;
|
||||
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_hash_table_lookup_extended (GHashTable *hash_table,
|
||||
gconstpointer lookup_key,
|
||||
gpointer *orig_key,
|
||||
gpointer *value)
|
||||
{
|
||||
GHashNode *node;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, FALSE);
|
||||
|
||||
node = *g_hash_table_lookup_node (hash_table, lookup_key);
|
||||
|
||||
if (node)
|
||||
{
|
||||
if (orig_key)
|
||||
*orig_key = node->key;
|
||||
if (value)
|
||||
*value = node->value;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_freeze (GHashTable *hash_table)
|
||||
{
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
hash_table->frozen++;
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_thaw (GHashTable *hash_table)
|
||||
{
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
|
||||
if (hash_table->frozen)
|
||||
if (!(--hash_table->frozen))
|
||||
g_hash_table_resize (hash_table);
|
||||
}
|
||||
|
||||
guint
|
||||
g_hash_table_foreach_remove (GHashTable *hash_table,
|
||||
GHRFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashNode *node, *prev;
|
||||
guint i;
|
||||
guint deleted = 0;
|
||||
|
||||
g_return_val_if_fail (hash_table != NULL, 0);
|
||||
g_return_val_if_fail (func != NULL, 0);
|
||||
|
||||
for (i = 0; i < hash_table->size; i++)
|
||||
{
|
||||
restart:
|
||||
|
||||
prev = NULL;
|
||||
|
||||
for (node = hash_table->nodes[i]; node; prev = node, node = node->next)
|
||||
{
|
||||
if ((* func) (node->key, node->value, user_data))
|
||||
{
|
||||
deleted += 1;
|
||||
|
||||
hash_table->nnodes -= 1;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->next = node->next;
|
||||
g_hash_node_destroy (node);
|
||||
node = prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_table->nodes[i] = node->next;
|
||||
g_hash_node_destroy (node);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hash_table->frozen)
|
||||
g_hash_table_resize (hash_table);
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
void
|
||||
g_hash_table_foreach (GHashTable *hash_table,
|
||||
GHFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashNode *node;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (hash_table != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
for (i = 0; i < hash_table->size; i++)
|
||||
for (node = hash_table->nodes[i]; node; node = node->next)
|
||||
(* func) (node->key, node->value, user_data);
|
||||
}
|
||||
|
||||
/* Returns the number of elements contained in the hash table. */
|
||||
guint
|
||||
g_hash_table_size (GHashTable *hash_table)
|
||||
{
|
||||
g_return_val_if_fail (hash_table != NULL, 0);
|
||||
|
||||
return hash_table->nnodes;
|
||||
}
|
||||
|
||||
static void
|
||||
g_hash_table_resize (GHashTable *hash_table)
|
||||
{
|
||||
GHashNode **new_nodes;
|
||||
GHashNode *node;
|
||||
GHashNode *next;
|
||||
gfloat nodes_per_list;
|
||||
guint hash_val;
|
||||
gint new_size;
|
||||
gint i;
|
||||
|
||||
nodes_per_list = (gfloat) hash_table->nnodes / (gfloat) hash_table->size;
|
||||
|
||||
if ((nodes_per_list > 0.3 || hash_table->size <= HASH_TABLE_MIN_SIZE) &&
|
||||
(nodes_per_list < 3.0 || hash_table->size >= HASH_TABLE_MAX_SIZE))
|
||||
return;
|
||||
|
||||
new_size = CLAMP(g_spaced_primes_closest (hash_table->nnodes),
|
||||
HASH_TABLE_MIN_SIZE,
|
||||
HASH_TABLE_MAX_SIZE);
|
||||
new_nodes = g_new0 (GHashNode*, new_size);
|
||||
|
||||
for (i = 0; i < hash_table->size; i++)
|
||||
for (node = hash_table->nodes[i]; node; node = next)
|
||||
{
|
||||
next = node->next;
|
||||
|
||||
hash_val = (* hash_table->hash_func) (node->key) % new_size;
|
||||
|
||||
node->next = new_nodes[hash_val];
|
||||
new_nodes[hash_val] = node;
|
||||
}
|
||||
|
||||
g_free (hash_table->nodes);
|
||||
hash_table->nodes = new_nodes;
|
||||
hash_table->size = new_size;
|
||||
}
|
||||
|
||||
static GHashNode*
|
||||
g_hash_node_new (gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
GHashNode *hash_node;
|
||||
|
||||
G_LOCK (g_hash_global);
|
||||
if (node_free_list)
|
||||
{
|
||||
hash_node = node_free_list;
|
||||
node_free_list = node_free_list->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!node_mem_chunk)
|
||||
node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
|
||||
sizeof (GHashNode),
|
||||
1024, G_ALLOC_ONLY);
|
||||
|
||||
hash_node = g_chunk_new (GHashNode, node_mem_chunk);
|
||||
}
|
||||
G_UNLOCK (g_hash_global);
|
||||
|
||||
hash_node->key = key;
|
||||
hash_node->value = value;
|
||||
hash_node->next = NULL;
|
||||
|
||||
return hash_node;
|
||||
}
|
||||
|
||||
static void
|
||||
g_hash_node_destroy (GHashNode *hash_node)
|
||||
{
|
||||
G_LOCK (g_hash_global);
|
||||
hash_node->next = node_free_list;
|
||||
node_free_list = hash_node;
|
||||
G_UNLOCK (g_hash_global);
|
||||
}
|
||||
|
||||
static void
|
||||
g_hash_nodes_destroy (GHashNode *hash_node)
|
||||
{
|
||||
if (hash_node)
|
||||
{
|
||||
GHashNode *node = hash_node;
|
||||
|
||||
while (node->next)
|
||||
node = node->next;
|
||||
|
||||
G_LOCK (g_hash_global);
|
||||
node->next = node_free_list;
|
||||
node_free_list = hash_node;
|
||||
G_UNLOCK (g_hash_global);
|
||||
}
|
||||
}
|
633
glib/ghook.c
633
glib/ghook.c
@ -1,633 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* GHook: Callback maintenance functions
|
||||
* Copyright (C) 1998 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
/* --- defines --- */
|
||||
#define G_HOOKS_PREALLOC (16)
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
void
|
||||
g_hook_list_init (GHookList *hook_list,
|
||||
guint hook_size)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_size >= sizeof (GHook));
|
||||
|
||||
hook_list->seq_id = 1;
|
||||
hook_list->hook_size = hook_size;
|
||||
hook_list->is_setup = TRUE;
|
||||
hook_list->hooks = NULL;
|
||||
hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk",
|
||||
hook_size,
|
||||
hook_size * G_HOOKS_PREALLOC,
|
||||
G_ALLOC_AND_FREE);
|
||||
hook_list->hook_free = NULL;
|
||||
hook_list->hook_destroy = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_list_clear (GHookList *hook_list)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
|
||||
if (hook_list->is_setup)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
hook_list->is_setup = FALSE;
|
||||
|
||||
hook = hook_list->hooks;
|
||||
if (!hook)
|
||||
{
|
||||
g_mem_chunk_destroy (hook_list->hook_memchunk);
|
||||
hook_list->hook_memchunk = NULL;
|
||||
}
|
||||
else
|
||||
do
|
||||
{
|
||||
GHook *tmp;
|
||||
|
||||
g_hook_ref (hook_list, hook);
|
||||
g_hook_destroy_link (hook_list, hook);
|
||||
tmp = hook->next;
|
||||
g_hook_unref (hook_list, hook);
|
||||
hook = tmp;
|
||||
}
|
||||
while (hook);
|
||||
}
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_alloc (GHookList *hook_list)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
g_return_val_if_fail (hook_list->is_setup, NULL);
|
||||
|
||||
hook = g_chunk_new0 (GHook, hook_list->hook_memchunk);
|
||||
hook->data = NULL;
|
||||
hook->next = NULL;
|
||||
hook->prev = NULL;
|
||||
hook->flags = G_HOOK_FLAG_ACTIVE;
|
||||
hook->ref_count = 0;
|
||||
hook->hook_id = 0;
|
||||
hook->func = NULL;
|
||||
hook->destroy = NULL;
|
||||
|
||||
return hook;
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_free (GHookList *hook_list,
|
||||
GHook *hook)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
g_return_if_fail (hook != NULL);
|
||||
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
|
||||
|
||||
if (hook_list->hook_free)
|
||||
hook_list->hook_free (hook_list, hook);
|
||||
|
||||
g_chunk_free (hook, hook_list->hook_memchunk);
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_destroy_link (GHookList *hook_list,
|
||||
GHook *hook)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook != NULL);
|
||||
|
||||
if (hook->hook_id)
|
||||
{
|
||||
hook->hook_id = 0;
|
||||
hook->flags &= ~G_HOOK_FLAG_ACTIVE;
|
||||
if (hook_list->hook_destroy)
|
||||
{
|
||||
if (hook_list->hook_destroy != G_HOOK_DEFERRED_DESTROY)
|
||||
hook_list->hook_destroy (hook_list, hook);
|
||||
}
|
||||
else if (hook->destroy)
|
||||
{
|
||||
hook->destroy (hook->data);
|
||||
hook->data = NULL;
|
||||
hook->func = NULL;
|
||||
hook->destroy = NULL;
|
||||
}
|
||||
g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_hook_destroy (GHookList *hook_list,
|
||||
guint hook_id)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, FALSE);
|
||||
g_return_val_if_fail (hook_id > 0, FALSE);
|
||||
|
||||
hook = g_hook_get (hook_list, hook_id);
|
||||
if (hook)
|
||||
{
|
||||
g_hook_destroy_link (hook_list, hook);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_unref (GHookList *hook_list,
|
||||
GHook *hook)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->hook_memchunk != NULL);
|
||||
g_return_if_fail (hook != NULL);
|
||||
g_return_if_fail (hook->ref_count > 0);
|
||||
|
||||
hook->ref_count--;
|
||||
if (!hook->ref_count)
|
||||
{
|
||||
g_return_if_fail (hook->hook_id == 0);
|
||||
g_return_if_fail (!G_HOOK_IN_CALL (hook));
|
||||
|
||||
if (hook->prev)
|
||||
hook->prev->next = hook->next;
|
||||
else
|
||||
hook_list->hooks = hook->next;
|
||||
if (hook->next)
|
||||
{
|
||||
hook->next->prev = hook->prev;
|
||||
hook->next = NULL;
|
||||
}
|
||||
hook->prev = NULL;
|
||||
|
||||
if (!hook_list->is_setup)
|
||||
{
|
||||
hook_list->is_setup = TRUE;
|
||||
g_hook_free (hook_list, hook);
|
||||
hook_list->is_setup = FALSE;
|
||||
|
||||
if (!hook_list->hooks)
|
||||
{
|
||||
g_mem_chunk_destroy (hook_list->hook_memchunk);
|
||||
hook_list->hook_memchunk = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
g_hook_free (hook_list, hook);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_ref (GHookList *hook_list,
|
||||
GHook *hook)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook != NULL);
|
||||
g_return_if_fail (hook->ref_count > 0);
|
||||
|
||||
hook->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_prepend (GHookList *hook_list,
|
||||
GHook *hook)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
|
||||
g_hook_insert_before (hook_list, hook_list->hooks, hook);
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_insert_before (GHookList *hook_list,
|
||||
GHook *sibling,
|
||||
GHook *hook)
|
||||
{
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
g_return_if_fail (hook != NULL);
|
||||
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
|
||||
g_return_if_fail (hook->func != NULL);
|
||||
|
||||
hook->hook_id = hook_list->seq_id++;
|
||||
hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
|
||||
|
||||
if (sibling)
|
||||
{
|
||||
if (sibling->prev)
|
||||
{
|
||||
hook->prev = sibling->prev;
|
||||
hook->prev->next = hook;
|
||||
hook->next = sibling;
|
||||
sibling->prev = hook;
|
||||
}
|
||||
else
|
||||
{
|
||||
hook_list->hooks = hook;
|
||||
hook->next = sibling;
|
||||
sibling->prev = hook;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hook_list->hooks)
|
||||
{
|
||||
sibling = hook_list->hooks;
|
||||
while (sibling->next)
|
||||
sibling = sibling->next;
|
||||
hook->prev = sibling;
|
||||
sibling->next = hook;
|
||||
}
|
||||
else
|
||||
hook_list->hooks = hook;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_list_invoke (GHookList *hook_list,
|
||||
gboolean may_recurse)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
|
||||
hook = g_hook_first_valid (hook_list, may_recurse);
|
||||
while (hook)
|
||||
{
|
||||
GHookFunc func;
|
||||
gboolean was_in_call;
|
||||
|
||||
func = (GHookFunc) hook->func;
|
||||
|
||||
was_in_call = G_HOOK_IN_CALL (hook);
|
||||
hook->flags |= G_HOOK_FLAG_IN_CALL;
|
||||
func (hook->data);
|
||||
if (!was_in_call)
|
||||
hook->flags &= ~G_HOOK_FLAG_IN_CALL;
|
||||
|
||||
hook = g_hook_next_valid (hook_list, hook, may_recurse);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_list_invoke_check (GHookList *hook_list,
|
||||
gboolean may_recurse)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
|
||||
hook = g_hook_first_valid (hook_list, may_recurse);
|
||||
while (hook)
|
||||
{
|
||||
GHookCheckFunc func;
|
||||
gboolean was_in_call;
|
||||
gboolean need_destroy;
|
||||
|
||||
func = (GHookCheckFunc) hook->func;
|
||||
|
||||
was_in_call = G_HOOK_IN_CALL (hook);
|
||||
hook->flags |= G_HOOK_FLAG_IN_CALL;
|
||||
need_destroy = !func (hook->data);
|
||||
if (!was_in_call)
|
||||
hook->flags &= ~G_HOOK_FLAG_IN_CALL;
|
||||
if (need_destroy)
|
||||
g_hook_destroy_link (hook_list, hook);
|
||||
|
||||
hook = g_hook_next_valid (hook_list, hook, may_recurse);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_list_marshal_check (GHookList *hook_list,
|
||||
gboolean may_recurse,
|
||||
GHookCheckMarshaller marshaller,
|
||||
gpointer data)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
g_return_if_fail (marshaller != NULL);
|
||||
|
||||
hook = g_hook_first_valid (hook_list, may_recurse);
|
||||
while (hook)
|
||||
{
|
||||
gboolean was_in_call;
|
||||
gboolean need_destroy;
|
||||
|
||||
was_in_call = G_HOOK_IN_CALL (hook);
|
||||
hook->flags |= G_HOOK_FLAG_IN_CALL;
|
||||
need_destroy = !marshaller (hook, data);
|
||||
if (!was_in_call)
|
||||
hook->flags &= ~G_HOOK_FLAG_IN_CALL;
|
||||
if (need_destroy)
|
||||
g_hook_destroy_link (hook_list, hook);
|
||||
|
||||
hook = g_hook_next_valid (hook_list, hook, may_recurse);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_list_marshal (GHookList *hook_list,
|
||||
gboolean may_recurse,
|
||||
GHookMarshaller marshaller,
|
||||
gpointer data)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
g_return_if_fail (marshaller != NULL);
|
||||
|
||||
hook = g_hook_first_valid (hook_list, may_recurse);
|
||||
while (hook)
|
||||
{
|
||||
gboolean was_in_call;
|
||||
|
||||
was_in_call = G_HOOK_IN_CALL (hook);
|
||||
hook->flags |= G_HOOK_FLAG_IN_CALL;
|
||||
marshaller (hook, data);
|
||||
if (!was_in_call)
|
||||
hook->flags &= ~G_HOOK_FLAG_IN_CALL;
|
||||
|
||||
hook = g_hook_next_valid (hook_list, hook, may_recurse);
|
||||
}
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_first_valid (GHookList *hook_list,
|
||||
gboolean may_be_in_call)
|
||||
{
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
|
||||
if (hook_list->is_setup)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
hook = hook_list->hooks;
|
||||
if (hook)
|
||||
{
|
||||
g_hook_ref (hook_list, hook);
|
||||
if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
|
||||
return hook;
|
||||
else
|
||||
return g_hook_next_valid (hook_list, hook, may_be_in_call);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_next_valid (GHookList *hook_list,
|
||||
GHook *hook,
|
||||
gboolean may_be_in_call)
|
||||
{
|
||||
GHook *ohook = hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
|
||||
if (!hook)
|
||||
return NULL;
|
||||
|
||||
hook = hook->next;
|
||||
while (hook)
|
||||
{
|
||||
if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
|
||||
{
|
||||
g_hook_ref (hook_list, hook);
|
||||
g_hook_unref (hook_list, ohook);
|
||||
|
||||
return hook;
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
g_hook_unref (hook_list, ohook);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_get (GHookList *hook_list,
|
||||
guint hook_id)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
g_return_val_if_fail (hook_id > 0, NULL);
|
||||
|
||||
hook = hook_list->hooks;
|
||||
while (hook)
|
||||
{
|
||||
if (hook->hook_id == hook_id)
|
||||
return hook;
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_find (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
GHookFindFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
g_return_val_if_fail (func != NULL, NULL);
|
||||
|
||||
hook = hook_list->hooks;
|
||||
while (hook)
|
||||
{
|
||||
GHook *tmp;
|
||||
|
||||
/* test only non-destroyed hooks */
|
||||
if (!hook->hook_id)
|
||||
{
|
||||
hook = hook->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
g_hook_ref (hook_list, hook);
|
||||
|
||||
if (func (hook, data) && hook->hook_id && (!need_valids || G_HOOK_ACTIVE (hook)))
|
||||
{
|
||||
g_hook_unref (hook_list, hook);
|
||||
|
||||
return hook;
|
||||
}
|
||||
|
||||
tmp = hook->next;
|
||||
g_hook_unref (hook_list, hook);
|
||||
hook = tmp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_find_data (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
gpointer data)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
|
||||
hook = hook_list->hooks;
|
||||
while (hook)
|
||||
{
|
||||
/* test only non-destroyed hooks */
|
||||
if (hook->data == data &&
|
||||
hook->hook_id &&
|
||||
(!need_valids || G_HOOK_ACTIVE (hook)))
|
||||
return hook;
|
||||
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_find_func (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
gpointer func)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
g_return_val_if_fail (func != NULL, NULL);
|
||||
|
||||
hook = hook_list->hooks;
|
||||
while (hook)
|
||||
{
|
||||
/* test only non-destroyed hooks */
|
||||
if (hook->func == func &&
|
||||
hook->hook_id &&
|
||||
(!need_valids || G_HOOK_ACTIVE (hook)))
|
||||
return hook;
|
||||
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHook*
|
||||
g_hook_find_func_data (GHookList *hook_list,
|
||||
gboolean need_valids,
|
||||
gpointer func,
|
||||
gpointer data)
|
||||
{
|
||||
GHook *hook;
|
||||
|
||||
g_return_val_if_fail (hook_list != NULL, NULL);
|
||||
g_return_val_if_fail (func != NULL, NULL);
|
||||
|
||||
hook = hook_list->hooks;
|
||||
while (hook)
|
||||
{
|
||||
/* test only non-destroyed hooks */
|
||||
if (hook->data == data &&
|
||||
hook->func == func &&
|
||||
hook->hook_id &&
|
||||
(!need_valids || G_HOOK_ACTIVE (hook)))
|
||||
return hook;
|
||||
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
g_hook_insert_sorted (GHookList *hook_list,
|
||||
GHook *hook,
|
||||
GHookCompareFunc func)
|
||||
{
|
||||
GHook *sibling;
|
||||
|
||||
g_return_if_fail (hook_list != NULL);
|
||||
g_return_if_fail (hook_list->is_setup);
|
||||
g_return_if_fail (hook != NULL);
|
||||
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
|
||||
g_return_if_fail (hook->func != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
/* first non-destroyed hook */
|
||||
sibling = hook_list->hooks;
|
||||
while (sibling && !sibling->hook_id)
|
||||
sibling = sibling->next;
|
||||
|
||||
while (sibling)
|
||||
{
|
||||
GHook *tmp;
|
||||
|
||||
g_hook_ref (hook_list, sibling);
|
||||
if (func (hook, sibling) <= 0 && sibling->hook_id)
|
||||
{
|
||||
g_hook_unref (hook_list, sibling);
|
||||
break;
|
||||
}
|
||||
|
||||
/* next non-destroyed hook */
|
||||
tmp = sibling->next;
|
||||
while (tmp && !tmp->hook_id)
|
||||
tmp = tmp->next;
|
||||
|
||||
g_hook_unref (hook_list, sibling);
|
||||
sibling = tmp;
|
||||
}
|
||||
|
||||
g_hook_insert_before (hook_list, sibling, hook);
|
||||
}
|
||||
|
||||
gint
|
||||
g_hook_compare_ids (GHook *new_hook,
|
||||
GHook *sibling)
|
||||
{
|
||||
return ((glong) new_hook->hook_id) - ((glong) sibling->hook_id);
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* giochannel.c: IO Channel abstraction
|
||||
* Copyright 1998 Owen Taylor
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "glib.h"
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
g_io_channel_init (GIOChannel *channel)
|
||||
{
|
||||
channel->channel_flags = 0;
|
||||
channel->ref_count = 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
g_io_channel_ref (GIOChannel *channel)
|
||||
{
|
||||
g_return_if_fail (channel != NULL);
|
||||
|
||||
channel->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
g_io_channel_unref (GIOChannel *channel)
|
||||
{
|
||||
g_return_if_fail (channel != NULL);
|
||||
|
||||
channel->ref_count--;
|
||||
if (channel->ref_count == 0)
|
||||
channel->funcs->io_free (channel);
|
||||
}
|
||||
|
||||
GIOError
|
||||
g_io_channel_read (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
guint count,
|
||||
guint *bytes_read)
|
||||
{
|
||||
g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
|
||||
|
||||
return channel->funcs->io_read (channel, buf, count, bytes_read);
|
||||
}
|
||||
|
||||
GIOError
|
||||
g_io_channel_write (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
guint count,
|
||||
guint *bytes_written)
|
||||
{
|
||||
g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
|
||||
|
||||
return channel->funcs->io_write (channel, buf, count, bytes_written);
|
||||
}
|
||||
|
||||
GIOError
|
||||
g_io_channel_seek (GIOChannel *channel,
|
||||
gint offset,
|
||||
GSeekType type)
|
||||
{
|
||||
g_return_val_if_fail (channel != NULL, G_IO_ERROR_UNKNOWN);
|
||||
|
||||
return channel->funcs->io_seek (channel, offset, type);
|
||||
}
|
||||
|
||||
void
|
||||
g_io_channel_close (GIOChannel *channel)
|
||||
{
|
||||
g_return_if_fail (channel != NULL);
|
||||
|
||||
channel->funcs->io_close (channel);
|
||||
}
|
||||
|
||||
guint
|
||||
g_io_add_watch_full (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
g_return_val_if_fail (channel != NULL, 0);
|
||||
|
||||
return channel->funcs->io_add_watch (channel, priority, condition,
|
||||
func, user_data, notify);
|
||||
}
|
||||
|
||||
guint
|
||||
g_io_add_watch (GIOChannel *channel,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return g_io_add_watch_full (channel, 0, condition, func, user_data, NULL);
|
||||
}
|
313
glib/giounix.c
313
glib/giounix.c
@ -1,313 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* giounix.c: IO Channels using unix file descriptors
|
||||
* Copyright 1998 Owen Taylor
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Unix IO Channels
|
||||
*/
|
||||
|
||||
typedef struct _GIOUnixChannel GIOUnixChannel;
|
||||
typedef struct _GIOUnixWatch GIOUnixWatch;
|
||||
|
||||
struct _GIOUnixChannel {
|
||||
GIOChannel channel;
|
||||
gint fd;
|
||||
};
|
||||
|
||||
struct _GIOUnixWatch {
|
||||
GPollFD pollfd;
|
||||
GIOChannel *channel;
|
||||
GIOCondition condition;
|
||||
GIOFunc callback;
|
||||
};
|
||||
|
||||
|
||||
static GIOError g_io_unix_read (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
guint count,
|
||||
guint *bytes_written);
|
||||
|
||||
static GIOError g_io_unix_write(GIOChannel *channel,
|
||||
gchar *buf,
|
||||
guint count,
|
||||
guint *bytes_written);
|
||||
static GIOError g_io_unix_seek (GIOChannel *channel,
|
||||
gint offset,
|
||||
GSeekType type);
|
||||
static void g_io_unix_close (GIOChannel *channel);
|
||||
static void g_io_unix_free (GIOChannel *channel);
|
||||
static guint g_io_unix_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
static gboolean g_io_unix_prepare (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gint *timeout,
|
||||
gpointer user_data);
|
||||
static gboolean g_io_unix_check (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gpointer user_data);
|
||||
static gboolean g_io_unix_dispatch (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gpointer user_data);
|
||||
static void g_io_unix_destroy (gpointer source_data);
|
||||
|
||||
GSourceFuncs unix_watch_funcs = {
|
||||
g_io_unix_prepare,
|
||||
g_io_unix_check,
|
||||
g_io_unix_dispatch,
|
||||
g_io_unix_destroy
|
||||
};
|
||||
|
||||
GIOFuncs unix_channel_funcs = {
|
||||
g_io_unix_read,
|
||||
g_io_unix_write,
|
||||
g_io_unix_seek,
|
||||
g_io_unix_close,
|
||||
g_io_unix_add_watch,
|
||||
g_io_unix_free,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
g_io_unix_prepare (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gint *timeout,
|
||||
gpointer user_data)
|
||||
{
|
||||
*timeout = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_io_unix_check (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gpointer user_data)
|
||||
{
|
||||
GIOUnixWatch *data = source_data;
|
||||
|
||||
return (data->pollfd.revents & data->condition);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_io_unix_dispatch (gpointer source_data,
|
||||
GTimeVal *current_time,
|
||||
gpointer user_data)
|
||||
|
||||
{
|
||||
GIOUnixWatch *data = source_data;
|
||||
|
||||
return (*data->callback)(data->channel,
|
||||
data->pollfd.revents & data->condition,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
g_io_unix_destroy (gpointer source_data)
|
||||
{
|
||||
GIOUnixWatch *data = source_data;
|
||||
|
||||
g_main_remove_poll (&data->pollfd);
|
||||
g_io_channel_unref (data->channel);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static GIOError
|
||||
g_io_unix_read (GIOChannel *channel,
|
||||
gchar *buf,
|
||||
guint count,
|
||||
guint *bytes_read)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
gint result;
|
||||
|
||||
result = read (unix_channel->fd, buf, count);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
*bytes_read = 0;
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
return G_IO_ERROR_INVAL;
|
||||
case EAGAIN:
|
||||
return G_IO_ERROR_AGAIN;
|
||||
default:
|
||||
return G_IO_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*bytes_read = result;
|
||||
return G_IO_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static GIOError
|
||||
g_io_unix_write(GIOChannel *channel,
|
||||
gchar *buf,
|
||||
guint count,
|
||||
guint *bytes_written)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
gint result;
|
||||
|
||||
result = write (unix_channel->fd, buf, count);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
*bytes_written = 0;
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
return G_IO_ERROR_INVAL;
|
||||
case EAGAIN:
|
||||
return G_IO_ERROR_AGAIN;
|
||||
default:
|
||||
return G_IO_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*bytes_written = result;
|
||||
return G_IO_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static GIOError
|
||||
g_io_unix_seek (GIOChannel *channel,
|
||||
gint offset,
|
||||
GSeekType type)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
int whence;
|
||||
off_t result;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case G_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case G_SEEK_CUR:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case G_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
g_warning ("g_io_unix_seek: unknown seek type");
|
||||
return G_IO_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
result = lseek (unix_channel->fd, offset, whence);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
return G_IO_ERROR_INVAL;
|
||||
default:
|
||||
return G_IO_ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else
|
||||
return G_IO_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
g_io_unix_close (GIOChannel *channel)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
|
||||
close (unix_channel->fd);
|
||||
}
|
||||
|
||||
static void
|
||||
g_io_unix_free (GIOChannel *channel)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
|
||||
g_free (unix_channel);
|
||||
}
|
||||
|
||||
static guint
|
||||
g_io_unix_add_watch (GIOChannel *channel,
|
||||
gint priority,
|
||||
GIOCondition condition,
|
||||
GIOFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
GIOUnixWatch *watch = g_new (GIOUnixWatch, 1);
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
|
||||
watch->channel = channel;
|
||||
g_io_channel_ref (channel);
|
||||
|
||||
watch->callback = func;
|
||||
watch->condition = condition;
|
||||
|
||||
watch->pollfd.fd = unix_channel->fd;
|
||||
watch->pollfd.events = condition;
|
||||
|
||||
g_main_add_poll (&watch->pollfd, priority);
|
||||
|
||||
return g_source_add (priority, TRUE, &unix_watch_funcs, watch, user_data, notify);
|
||||
}
|
||||
|
||||
GIOChannel *
|
||||
g_io_channel_unix_new (gint fd)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = g_new (GIOUnixChannel, 1);
|
||||
GIOChannel *channel = (GIOChannel *)unix_channel;
|
||||
|
||||
g_io_channel_init (channel);
|
||||
channel->funcs = &unix_channel_funcs;
|
||||
|
||||
unix_channel->fd = fd;
|
||||
return channel;
|
||||
}
|
||||
|
||||
gint
|
||||
g_io_channel_unix_get_fd (GIOChannel *channel)
|
||||
{
|
||||
GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
|
||||
return unix_channel->fd;
|
||||
}
|
1035
glib/giowin32.c
1035
glib/giowin32.c
File diff suppressed because it is too large
Load Diff
2827
glib/glib.h
2827
glib/glib.h
File diff suppressed because it is too large
Load Diff
670
glib/glist.c
670
glib/glist.c
@ -1,670 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
struct _GAllocator /* from gmem.c */
|
||||
{
|
||||
gchar *name;
|
||||
guint16 n_preallocs;
|
||||
guint is_unused : 1;
|
||||
guint type : 4;
|
||||
GAllocator *last;
|
||||
GMemChunk *mem_chunk;
|
||||
GList *free_lists; /* implementation specific */
|
||||
};
|
||||
|
||||
static GAllocator *current_allocator = NULL;
|
||||
G_LOCK_DEFINE_STATIC (current_allocator);
|
||||
|
||||
/* HOLDS: current_allocator_lock */
|
||||
static void
|
||||
g_list_validate_allocator (GAllocator *allocator)
|
||||
{
|
||||
g_return_if_fail (allocator != NULL);
|
||||
g_return_if_fail (allocator->is_unused == TRUE);
|
||||
|
||||
if (allocator->type != G_ALLOCATOR_LIST)
|
||||
{
|
||||
allocator->type = G_ALLOCATOR_LIST;
|
||||
if (allocator->mem_chunk)
|
||||
{
|
||||
g_mem_chunk_destroy (allocator->mem_chunk);
|
||||
allocator->mem_chunk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allocator->mem_chunk)
|
||||
{
|
||||
allocator->mem_chunk = g_mem_chunk_new (allocator->name,
|
||||
sizeof (GList),
|
||||
sizeof (GList) * allocator->n_preallocs,
|
||||
G_ALLOC_ONLY);
|
||||
allocator->free_lists = NULL;
|
||||
}
|
||||
|
||||
allocator->is_unused = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_list_push_allocator(GAllocator *allocator)
|
||||
{
|
||||
G_LOCK (current_allocator);
|
||||
g_list_validate_allocator ( allocator );
|
||||
allocator->last = current_allocator;
|
||||
current_allocator = allocator;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
void
|
||||
g_list_pop_allocator (void)
|
||||
{
|
||||
G_LOCK (current_allocator);
|
||||
if (current_allocator)
|
||||
{
|
||||
GAllocator *allocator;
|
||||
|
||||
allocator = current_allocator;
|
||||
current_allocator = allocator->last;
|
||||
allocator->last = NULL;
|
||||
allocator->is_unused = TRUE;
|
||||
}
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_alloc (void)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
G_LOCK (current_allocator);
|
||||
if (!current_allocator)
|
||||
{
|
||||
GAllocator *allocator = g_allocator_new ("GLib default GList allocator",
|
||||
128);
|
||||
g_list_validate_allocator (allocator);
|
||||
allocator->last = NULL;
|
||||
current_allocator = allocator;
|
||||
}
|
||||
if (!current_allocator->free_lists)
|
||||
{
|
||||
list = g_chunk_new (GList, current_allocator->mem_chunk);
|
||||
list->data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_allocator->free_lists->data)
|
||||
{
|
||||
list = current_allocator->free_lists->data;
|
||||
current_allocator->free_lists->data = list->next;
|
||||
list->data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list->next;
|
||||
}
|
||||
}
|
||||
G_UNLOCK (current_allocator);
|
||||
list->next = NULL;
|
||||
list->prev = NULL;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
g_list_free (GList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
list->data = list->next;
|
||||
G_LOCK (current_allocator);
|
||||
list->next = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_list_free_1 (GList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
list->data = NULL;
|
||||
G_LOCK (current_allocator);
|
||||
list->next = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_append (GList *list,
|
||||
gpointer data)
|
||||
{
|
||||
GList *new_list;
|
||||
GList *last;
|
||||
|
||||
new_list = g_list_alloc ();
|
||||
new_list->data = data;
|
||||
|
||||
if (list)
|
||||
{
|
||||
last = g_list_last (list);
|
||||
/* g_assert (last != NULL); */
|
||||
last->next = new_list;
|
||||
new_list->prev = last;
|
||||
|
||||
return list;
|
||||
}
|
||||
else
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_prepend (GList *list,
|
||||
gpointer data)
|
||||
{
|
||||
GList *new_list;
|
||||
|
||||
new_list = g_list_alloc ();
|
||||
new_list->data = data;
|
||||
|
||||
if (list)
|
||||
{
|
||||
if (list->prev)
|
||||
{
|
||||
list->prev->next = new_list;
|
||||
new_list->prev = list->prev;
|
||||
}
|
||||
list->prev = new_list;
|
||||
new_list->next = list;
|
||||
}
|
||||
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_insert (GList *list,
|
||||
gpointer data,
|
||||
gint position)
|
||||
{
|
||||
GList *new_list;
|
||||
GList *tmp_list;
|
||||
|
||||
if (position < 0)
|
||||
return g_list_append (list, data);
|
||||
else if (position == 0)
|
||||
return g_list_prepend (list, data);
|
||||
|
||||
tmp_list = g_list_nth (list, position);
|
||||
if (!tmp_list)
|
||||
return g_list_append (list, data);
|
||||
|
||||
new_list = g_list_alloc ();
|
||||
new_list->data = data;
|
||||
|
||||
if (tmp_list->prev)
|
||||
{
|
||||
tmp_list->prev->next = new_list;
|
||||
new_list->prev = tmp_list->prev;
|
||||
}
|
||||
new_list->next = tmp_list;
|
||||
tmp_list->prev = new_list;
|
||||
|
||||
if (tmp_list == list)
|
||||
return new_list;
|
||||
else
|
||||
return list;
|
||||
}
|
||||
|
||||
GList *
|
||||
g_list_concat (GList *list1, GList *list2)
|
||||
{
|
||||
GList *tmp_list;
|
||||
|
||||
if (list2)
|
||||
{
|
||||
tmp_list = g_list_last (list1);
|
||||
if (tmp_list)
|
||||
tmp_list->next = list2;
|
||||
else
|
||||
list1 = list2;
|
||||
list2->prev = tmp_list;
|
||||
}
|
||||
|
||||
return list1;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_remove (GList *list,
|
||||
gpointer data)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
tmp = list;
|
||||
while (tmp)
|
||||
{
|
||||
if (tmp->data != data)
|
||||
tmp = tmp->next;
|
||||
else
|
||||
{
|
||||
if (tmp->prev)
|
||||
tmp->prev->next = tmp->next;
|
||||
if (tmp->next)
|
||||
tmp->next->prev = tmp->prev;
|
||||
|
||||
if (list == tmp)
|
||||
list = list->next;
|
||||
|
||||
g_list_free_1 (tmp);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_remove_link (GList *list,
|
||||
GList *link)
|
||||
{
|
||||
if (link)
|
||||
{
|
||||
if (link->prev)
|
||||
link->prev->next = link->next;
|
||||
if (link->next)
|
||||
link->next->prev = link->prev;
|
||||
|
||||
if (link == list)
|
||||
list = list->next;
|
||||
|
||||
link->next = NULL;
|
||||
link->prev = NULL;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_copy (GList *list)
|
||||
{
|
||||
GList *new_list = NULL;
|
||||
|
||||
if (list)
|
||||
{
|
||||
GList *last;
|
||||
|
||||
new_list = g_list_alloc ();
|
||||
new_list->data = list->data;
|
||||
last = new_list;
|
||||
list = list->next;
|
||||
while (list)
|
||||
{
|
||||
last->next = g_list_alloc ();
|
||||
last->next->prev = last;
|
||||
last = last->next;
|
||||
last->data = list->data;
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_reverse (GList *list)
|
||||
{
|
||||
GList *last;
|
||||
|
||||
last = NULL;
|
||||
while (list)
|
||||
{
|
||||
last = list;
|
||||
list = last->next;
|
||||
last->next = last->prev;
|
||||
last->prev = list;
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_nth (GList *list,
|
||||
guint n)
|
||||
{
|
||||
while ((n-- > 0) && list)
|
||||
list = list->next;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_list_nth_data (GList *list,
|
||||
guint n)
|
||||
{
|
||||
while ((n-- > 0) && list)
|
||||
list = list->next;
|
||||
|
||||
return list ? list->data : NULL;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_find (GList *list,
|
||||
gpointer data)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
if (list->data == data)
|
||||
break;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_find_custom (GList *list,
|
||||
gpointer data,
|
||||
GCompareFunc func)
|
||||
{
|
||||
g_return_val_if_fail (func != NULL, list);
|
||||
|
||||
while (list)
|
||||
{
|
||||
if (! func (list->data, data))
|
||||
return list;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
gint
|
||||
g_list_position (GList *list,
|
||||
GList *link)
|
||||
{
|
||||
gint i;
|
||||
|
||||
i = 0;
|
||||
while (list)
|
||||
{
|
||||
if (list == link)
|
||||
return i;
|
||||
i++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
gint
|
||||
g_list_index (GList *list,
|
||||
gpointer data)
|
||||
{
|
||||
gint i;
|
||||
|
||||
i = 0;
|
||||
while (list)
|
||||
{
|
||||
if (list->data == data)
|
||||
return i;
|
||||
i++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_last (GList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
while (list->next)
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_first (GList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
while (list->prev)
|
||||
list = list->prev;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
guint
|
||||
g_list_length (GList *list)
|
||||
{
|
||||
guint length;
|
||||
|
||||
length = 0;
|
||||
while (list)
|
||||
{
|
||||
length++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void
|
||||
g_list_foreach (GList *list,
|
||||
GFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
(*func) (list->data, user_data);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GList*
|
||||
g_list_insert_sorted (GList *list,
|
||||
gpointer data,
|
||||
GCompareFunc func)
|
||||
{
|
||||
GList *tmp_list = list;
|
||||
GList *new_list;
|
||||
gint cmp;
|
||||
|
||||
g_return_val_if_fail (func != NULL, list);
|
||||
|
||||
if (!list)
|
||||
{
|
||||
new_list = g_list_alloc();
|
||||
new_list->data = data;
|
||||
return new_list;
|
||||
}
|
||||
|
||||
cmp = (*func) (data, tmp_list->data);
|
||||
|
||||
while ((tmp_list->next) && (cmp > 0))
|
||||
{
|
||||
tmp_list = tmp_list->next;
|
||||
cmp = (*func) (data, tmp_list->data);
|
||||
}
|
||||
|
||||
new_list = g_list_alloc();
|
||||
new_list->data = data;
|
||||
|
||||
if ((!tmp_list->next) && (cmp > 0))
|
||||
{
|
||||
tmp_list->next = new_list;
|
||||
new_list->prev = tmp_list;
|
||||
return list;
|
||||
}
|
||||
|
||||
if (tmp_list->prev)
|
||||
{
|
||||
tmp_list->prev->next = new_list;
|
||||
new_list->prev = tmp_list->prev;
|
||||
}
|
||||
new_list->next = tmp_list;
|
||||
tmp_list->prev = new_list;
|
||||
|
||||
if (tmp_list == list)
|
||||
return new_list;
|
||||
else
|
||||
return list;
|
||||
}
|
||||
|
||||
static GList *
|
||||
g_list_sort_merge (GList *l1,
|
||||
GList *l2,
|
||||
GCompareFunc compare_func)
|
||||
{
|
||||
GList list, *l, *lprev;
|
||||
|
||||
l = &list;
|
||||
lprev = NULL;
|
||||
|
||||
while (l1 && l2)
|
||||
{
|
||||
if (compare_func (l1->data, l2->data) < 0)
|
||||
{
|
||||
l->next = l1;
|
||||
l = l->next;
|
||||
l->prev = lprev;
|
||||
lprev = l;
|
||||
l1 = l1->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
l->next = l2;
|
||||
l = l->next;
|
||||
l->prev = lprev;
|
||||
lprev = l;
|
||||
l2 = l2->next;
|
||||
}
|
||||
}
|
||||
l->next = l1 ? l1 : l2;
|
||||
l->next->prev = l;
|
||||
|
||||
return list.next;
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_sort (GList *list,
|
||||
GCompareFunc compare_func)
|
||||
{
|
||||
GList *l1, *l2;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
if (!list->next)
|
||||
return list;
|
||||
|
||||
l1 = list;
|
||||
l2 = list->next;
|
||||
|
||||
while ((l2 = l2->next) != NULL)
|
||||
{
|
||||
if ((l2 = l2->next) == NULL)
|
||||
break;
|
||||
l1 = l1->next;
|
||||
}
|
||||
l2 = l1->next;
|
||||
l1->next = NULL;
|
||||
|
||||
return g_list_sort_merge (g_list_sort (list, compare_func),
|
||||
g_list_sort (l2, compare_func),
|
||||
compare_func);
|
||||
}
|
||||
|
||||
GList*
|
||||
g_list_sort2 (GList *list,
|
||||
GCompareFunc compare_func)
|
||||
{
|
||||
GSList *runs = NULL;
|
||||
GList *tmp;
|
||||
|
||||
/* Degenerate case. */
|
||||
if (!list) return NULL;
|
||||
|
||||
/* Assume: list = [12,2,4,11,2,4,6,1,1,12]. */
|
||||
for (tmp = list; tmp; )
|
||||
{
|
||||
GList *tmp2;
|
||||
for (tmp2 = tmp;
|
||||
tmp2->next && compare_func (tmp2->data, tmp2->next->data) <= 0;
|
||||
tmp2 = tmp2->next)
|
||||
/* Nothing */;
|
||||
runs = g_slist_append (runs, tmp);
|
||||
tmp = tmp2->next;
|
||||
tmp2->next = NULL;
|
||||
}
|
||||
/* Now: runs = [[12],[2,4,11],[2,4,6],[1,1,12]]. */
|
||||
|
||||
while (runs->next)
|
||||
{
|
||||
/* We have more than one run. Merge pairwise. */
|
||||
GSList *dst, *src, *dstprev = NULL;
|
||||
dst = src = runs;
|
||||
while (src && src->next)
|
||||
{
|
||||
dst->data = g_list_sort_merge (src->data,
|
||||
src->next->data,
|
||||
compare_func);
|
||||
dstprev = dst;
|
||||
dst = dst->next;
|
||||
src = src->next->next;
|
||||
}
|
||||
|
||||
/* If number of runs was odd, just keep the last. */
|
||||
if (src)
|
||||
{
|
||||
dst->data = src->data;
|
||||
dstprev = dst;
|
||||
dst = dst->next;
|
||||
}
|
||||
|
||||
dstprev->next = NULL;
|
||||
g_slist_free (dst);
|
||||
}
|
||||
|
||||
/* After 1st loop: runs = [[2,4,11,12],[1,1,2,4,6,12]]. */
|
||||
/* After 2nd loop: runs = [[1,1,2,2,4,4,6,11,12,12]]. */
|
||||
|
||||
list = runs->data;
|
||||
g_slist_free (runs);
|
||||
return list;
|
||||
}
|
1392
glib/gmain.c
1392
glib/gmain.c
File diff suppressed because it is too large
Load Diff
1008
glib/gmem.c
1008
glib/gmem.c
File diff suppressed because it is too large
Load Diff
756
glib/gmessages.c
756
glib/gmessages.c
@ -1,756 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "glib.h"
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
|
||||
/* Just use stdio. If we're out of memory, we're hosed anyway. */
|
||||
#undef write
|
||||
|
||||
static inline int
|
||||
write (FILE *fd,
|
||||
const char *buf,
|
||||
int len)
|
||||
{
|
||||
fwrite (buf, len, 1, fd);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_stdout_valid (void)
|
||||
{
|
||||
HANDLE handle;
|
||||
|
||||
handle = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
AllocConsole ();
|
||||
freopen ("CONOUT$", "w", stdout);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define ensure_stdout_valid() /* Define as empty */
|
||||
#endif
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
typedef struct _GLogDomain GLogDomain;
|
||||
typedef struct _GLogHandler GLogHandler;
|
||||
struct _GLogDomain
|
||||
{
|
||||
gchar *log_domain;
|
||||
GLogLevelFlags fatal_mask;
|
||||
GLogHandler *handlers;
|
||||
GLogDomain *next;
|
||||
};
|
||||
struct _GLogHandler
|
||||
{
|
||||
guint id;
|
||||
GLogLevelFlags log_level;
|
||||
GLogFunc log_func;
|
||||
gpointer data;
|
||||
GLogHandler *next;
|
||||
};
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
|
||||
static GMutex* g_messages_lock = NULL;
|
||||
|
||||
const gchar *g_log_domain_glib = "GLib";
|
||||
static GLogDomain *g_log_domains = NULL;
|
||||
static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
|
||||
static GPrintFunc glib_print_func = NULL;
|
||||
static GPrintFunc glib_printerr_func = NULL;
|
||||
static GErrorFunc glib_error_func = NULL;
|
||||
static GWarningFunc glib_warning_func = NULL;
|
||||
static GPrintFunc glib_message_func = NULL;
|
||||
|
||||
static GPrivate* g_log_depth = NULL;
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
static inline GLogDomain*
|
||||
g_log_find_domain (const gchar *log_domain)
|
||||
{
|
||||
register GLogDomain *domain;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
domain = g_log_domains;
|
||||
while (domain)
|
||||
{
|
||||
if (strcmp (domain->log_domain, log_domain) == 0)
|
||||
{
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
return domain;
|
||||
}
|
||||
domain = domain->next;
|
||||
}
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline GLogDomain*
|
||||
g_log_domain_new (const gchar *log_domain)
|
||||
{
|
||||
register GLogDomain *domain;
|
||||
|
||||
domain = g_new (GLogDomain, 1);
|
||||
domain->log_domain = g_strdup (log_domain);
|
||||
domain->fatal_mask = G_LOG_FATAL_MASK;
|
||||
domain->handlers = NULL;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
domain->next = g_log_domains;
|
||||
g_log_domains = domain;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
static inline void
|
||||
g_log_domain_check_free (GLogDomain *domain)
|
||||
{
|
||||
if (domain->fatal_mask == G_LOG_FATAL_MASK &&
|
||||
domain->handlers == NULL)
|
||||
{
|
||||
register GLogDomain *last, *work;
|
||||
|
||||
last = NULL;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
work = g_log_domains;
|
||||
while (work)
|
||||
{
|
||||
if (work == domain)
|
||||
{
|
||||
if (last)
|
||||
last->next = domain->next;
|
||||
else
|
||||
g_log_domains = domain->next;
|
||||
g_free (domain->log_domain);
|
||||
g_free (domain);
|
||||
break;
|
||||
}
|
||||
last = work;
|
||||
work = last->next;
|
||||
}
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static inline GLogFunc
|
||||
g_log_domain_get_handler (GLogDomain *domain,
|
||||
GLogLevelFlags log_level,
|
||||
gpointer *data)
|
||||
{
|
||||
if (domain && log_level)
|
||||
{
|
||||
register GLogHandler *handler;
|
||||
|
||||
handler = domain->handlers;
|
||||
while (handler)
|
||||
{
|
||||
if ((handler->log_level & log_level) == log_level)
|
||||
{
|
||||
*data = handler->data;
|
||||
return handler->log_func;
|
||||
}
|
||||
handler = handler->next;
|
||||
}
|
||||
}
|
||||
return g_log_default_handler;
|
||||
}
|
||||
|
||||
GLogLevelFlags
|
||||
g_log_set_always_fatal (GLogLevelFlags fatal_mask)
|
||||
{
|
||||
GLogLevelFlags old_mask;
|
||||
|
||||
/* restrict the global mask to levels that are known to glib */
|
||||
fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
|
||||
/* force errors to be fatal */
|
||||
fatal_mask |= G_LOG_LEVEL_ERROR;
|
||||
/* remove bogus flag */
|
||||
fatal_mask &= ~G_LOG_FLAG_FATAL;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
old_mask = g_log_always_fatal;
|
||||
g_log_always_fatal = fatal_mask;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return old_mask;
|
||||
}
|
||||
|
||||
GLogLevelFlags
|
||||
g_log_set_fatal_mask (const gchar *log_domain,
|
||||
GLogLevelFlags fatal_mask)
|
||||
{
|
||||
GLogLevelFlags old_flags;
|
||||
register GLogDomain *domain;
|
||||
|
||||
if (!log_domain)
|
||||
log_domain = "";
|
||||
|
||||
/* force errors to be fatal */
|
||||
fatal_mask |= G_LOG_LEVEL_ERROR;
|
||||
/* remove bogus flag */
|
||||
fatal_mask &= ~G_LOG_FLAG_FATAL;
|
||||
|
||||
domain = g_log_find_domain (log_domain);
|
||||
if (!domain)
|
||||
domain = g_log_domain_new (log_domain);
|
||||
old_flags = domain->fatal_mask;
|
||||
|
||||
domain->fatal_mask = fatal_mask;
|
||||
g_log_domain_check_free (domain);
|
||||
|
||||
return old_flags;
|
||||
}
|
||||
|
||||
guint
|
||||
g_log_set_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_levels,
|
||||
GLogFunc log_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
register GLogDomain *domain;
|
||||
register GLogHandler *handler;
|
||||
static guint handler_id = 0;
|
||||
|
||||
g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
|
||||
g_return_val_if_fail (log_func != NULL, 0);
|
||||
|
||||
if (!log_domain)
|
||||
log_domain = "";
|
||||
|
||||
domain = g_log_find_domain (log_domain);
|
||||
if (!domain)
|
||||
domain = g_log_domain_new (log_domain);
|
||||
|
||||
handler = g_new (GLogHandler, 1);
|
||||
g_mutex_lock (g_messages_lock);
|
||||
handler->id = ++handler_id;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
handler->log_level = log_levels;
|
||||
handler->log_func = log_func;
|
||||
handler->data = user_data;
|
||||
handler->next = domain->handlers;
|
||||
domain->handlers = handler;
|
||||
|
||||
return handler_id;
|
||||
}
|
||||
|
||||
void
|
||||
g_log_remove_handler (const gchar *log_domain,
|
||||
guint handler_id)
|
||||
{
|
||||
register GLogDomain *domain;
|
||||
|
||||
g_return_if_fail (handler_id > 0);
|
||||
|
||||
if (!log_domain)
|
||||
log_domain = "";
|
||||
|
||||
domain = g_log_find_domain (log_domain);
|
||||
if (domain)
|
||||
{
|
||||
register GLogHandler *work, *last;
|
||||
|
||||
last = NULL;
|
||||
work = domain->handlers;
|
||||
while (work)
|
||||
{
|
||||
if (work->id == handler_id)
|
||||
{
|
||||
if (last)
|
||||
last->next = work->next;
|
||||
else
|
||||
domain->handlers = work->next;
|
||||
g_free (work);
|
||||
g_log_domain_check_free (domain);
|
||||
return;
|
||||
}
|
||||
last = work;
|
||||
work = last->next;
|
||||
}
|
||||
}
|
||||
g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"",
|
||||
handler_id,
|
||||
log_domain);
|
||||
}
|
||||
|
||||
void
|
||||
g_logv (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *format,
|
||||
va_list args1)
|
||||
{
|
||||
va_list args2;
|
||||
gchar buffer[1025];
|
||||
register gint i;
|
||||
|
||||
log_level &= G_LOG_LEVEL_MASK;
|
||||
if (!log_level)
|
||||
return;
|
||||
|
||||
/* we use a stack buffer of fixed size, because we might get called
|
||||
* recursively.
|
||||
*/
|
||||
G_VA_COPY (args2, args1);
|
||||
if (g_printf_string_upper_bound (format, args1) < 1024)
|
||||
vsprintf (buffer, format, args2);
|
||||
else
|
||||
{
|
||||
/* since we might be out of memory, we can't use g_vsnprintf(). */
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
vsnprintf (buffer, 1024, format, args2);
|
||||
#else /* !HAVE_VSNPRINTF */
|
||||
/* we are out of luck here */
|
||||
strncpy (buffer, format, 1024);
|
||||
#endif /* !HAVE_VSNPRINTF */
|
||||
buffer[1024] = 0;
|
||||
}
|
||||
va_end (args2);
|
||||
|
||||
for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
|
||||
{
|
||||
register GLogLevelFlags test_level;
|
||||
|
||||
test_level = 1 << i;
|
||||
if (log_level & test_level)
|
||||
{
|
||||
guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
|
||||
GLogDomain *domain;
|
||||
GLogFunc log_func;
|
||||
gpointer data = NULL;
|
||||
|
||||
domain = g_log_find_domain (log_domain ? log_domain : "");
|
||||
|
||||
if (depth)
|
||||
test_level |= G_LOG_FLAG_RECURSION;
|
||||
|
||||
depth++;
|
||||
g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) |
|
||||
g_log_always_fatal) & test_level) != 0)
|
||||
test_level |= G_LOG_FLAG_FATAL;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
log_func = g_log_domain_get_handler (domain, test_level, &data);
|
||||
log_func (log_domain, test_level, buffer, data);
|
||||
|
||||
/* *domain can be cluttered now */
|
||||
|
||||
if (test_level & G_LOG_FLAG_FATAL)
|
||||
abort ();
|
||||
|
||||
depth--;
|
||||
g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_log (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
g_logv (log_domain, log_level, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
g_log_default_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer unused_data)
|
||||
{
|
||||
#ifdef NATIVE_WIN32
|
||||
FILE *fd;
|
||||
#else
|
||||
gint fd;
|
||||
#endif
|
||||
gboolean in_recursion;
|
||||
gboolean is_fatal;
|
||||
GErrorFunc local_glib_error_func;
|
||||
GWarningFunc local_glib_warning_func;
|
||||
GPrintFunc local_glib_message_func;
|
||||
|
||||
in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
|
||||
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
|
||||
log_level &= G_LOG_LEVEL_MASK;
|
||||
|
||||
if (!message)
|
||||
message = "g_log_default_handler(): (NULL) message";
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
/* Use just stdout as stderr is hard to get redirected from the
|
||||
* DOS prompt.
|
||||
*/
|
||||
fd = stdout;
|
||||
#else
|
||||
fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
|
||||
#endif
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
local_glib_error_func = glib_error_func;
|
||||
local_glib_warning_func = glib_warning_func;
|
||||
local_glib_message_func = glib_message_func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
switch (log_level)
|
||||
{
|
||||
case G_LOG_LEVEL_ERROR:
|
||||
if (!log_domain && local_glib_error_func)
|
||||
{
|
||||
/* compatibility code */
|
||||
local_glib_error_func (message);
|
||||
return;
|
||||
}
|
||||
/* use write(2) for output, in case we are out of memeory */
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, "\n", 1);
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
write (fd, "-", 1);
|
||||
}
|
||||
else
|
||||
write (fd, "\n** ", 4);
|
||||
if (in_recursion)
|
||||
write (fd, "ERROR (recursed) **: ", 21);
|
||||
else
|
||||
write (fd, "ERROR **: ", 10);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
case G_LOG_LEVEL_CRITICAL:
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, "\n", 1);
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
write (fd, "-", 1);
|
||||
}
|
||||
else
|
||||
write (fd, "\n** ", 4);
|
||||
if (in_recursion)
|
||||
write (fd, "CRITICAL (recursed) **: ", 24);
|
||||
else
|
||||
write (fd, "CRITICAL **: ", 13);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
case G_LOG_LEVEL_WARNING:
|
||||
if (!log_domain && local_glib_warning_func)
|
||||
{
|
||||
/* compatibility code */
|
||||
local_glib_warning_func (message);
|
||||
return;
|
||||
}
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, "\n", 1);
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
write (fd, "-", 1);
|
||||
}
|
||||
else
|
||||
write (fd, "\n** ", 4);
|
||||
if (in_recursion)
|
||||
write (fd, "WARNING (recursed) **: ", 23);
|
||||
else
|
||||
write (fd, "WARNING **: ", 12);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
case G_LOG_LEVEL_MESSAGE:
|
||||
if (!log_domain && local_glib_message_func)
|
||||
{
|
||||
/* compatibility code */
|
||||
local_glib_message_func (message);
|
||||
return;
|
||||
}
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
write (fd, "-", 1);
|
||||
}
|
||||
if (in_recursion)
|
||||
write (fd, "Message (recursed): ", 20);
|
||||
else
|
||||
write (fd, "Message: ", 9);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
case G_LOG_LEVEL_INFO:
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
write (fd, "-", 1);
|
||||
}
|
||||
if (in_recursion)
|
||||
write (fd, "INFO (recursed): ", 17);
|
||||
else
|
||||
write (fd, "INFO: ", 6);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
case G_LOG_LEVEL_DEBUG:
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
write (fd, "-", 1);
|
||||
}
|
||||
if (in_recursion)
|
||||
write (fd, "DEBUG (recursed): ", 18);
|
||||
else
|
||||
write (fd, "DEBUG: ", 7);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
default:
|
||||
/* we are used for a log level that is not defined by GLib itself,
|
||||
* try to make the best out of it.
|
||||
*/
|
||||
ensure_stdout_valid ();
|
||||
if (log_domain)
|
||||
{
|
||||
write (fd, log_domain, strlen (log_domain));
|
||||
if (in_recursion)
|
||||
write (fd, "-LOG (recursed:", 15);
|
||||
else
|
||||
write (fd, "-LOG (", 6);
|
||||
}
|
||||
else if (in_recursion)
|
||||
write (fd, "LOG (recursed:", 14);
|
||||
else
|
||||
write (fd, "LOG (", 5);
|
||||
if (log_level)
|
||||
{
|
||||
gchar string[] = "0x00): ";
|
||||
gchar *p = string + 2;
|
||||
guint i;
|
||||
|
||||
i = g_bit_nth_msf (log_level, -1);
|
||||
*p = i >> 4;
|
||||
p++;
|
||||
*p = '0' + (i & 0xf);
|
||||
if (*p > '9')
|
||||
*p += 'A' - '9' - 1;
|
||||
|
||||
write (fd, string, 7);
|
||||
}
|
||||
else
|
||||
write (fd, "): ", 3);
|
||||
write (fd, message, strlen(message));
|
||||
if (is_fatal)
|
||||
write (fd, "\naborting...\n", 13);
|
||||
else
|
||||
write (fd, "\n", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GPrintFunc
|
||||
g_set_print_handler (GPrintFunc func)
|
||||
{
|
||||
GPrintFunc old_print_func;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
old_print_func = glib_print_func;
|
||||
glib_print_func = func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return old_print_func;
|
||||
}
|
||||
|
||||
void
|
||||
g_print (const gchar *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gchar *string;
|
||||
GPrintFunc local_glib_print_func;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
va_start (args, format);
|
||||
string = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
local_glib_print_func = glib_print_func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
if (local_glib_print_func)
|
||||
local_glib_print_func (string);
|
||||
else
|
||||
{
|
||||
ensure_stdout_valid ();
|
||||
fputs (string, stdout);
|
||||
fflush (stdout);
|
||||
}
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
GPrintFunc
|
||||
g_set_printerr_handler (GPrintFunc func)
|
||||
{
|
||||
GPrintFunc old_printerr_func;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
old_printerr_func = glib_printerr_func;
|
||||
glib_printerr_func = func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return old_printerr_func;
|
||||
}
|
||||
|
||||
void
|
||||
g_printerr (const gchar *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gchar *string;
|
||||
GPrintFunc local_glib_printerr_func;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
va_start (args, format);
|
||||
string = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
local_glib_printerr_func = glib_printerr_func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
if (local_glib_printerr_func)
|
||||
local_glib_printerr_func (string);
|
||||
else
|
||||
{
|
||||
fputs (string, stderr);
|
||||
fflush (stderr);
|
||||
}
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
/* compatibility code */
|
||||
GErrorFunc
|
||||
g_set_error_handler (GErrorFunc func)
|
||||
{
|
||||
GErrorFunc old_error_func;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
old_error_func = glib_error_func;
|
||||
glib_error_func = func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return old_error_func;
|
||||
}
|
||||
|
||||
/* compatibility code */
|
||||
GWarningFunc
|
||||
g_set_warning_handler (GWarningFunc func)
|
||||
{
|
||||
GWarningFunc old_warning_func;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
old_warning_func = glib_warning_func;
|
||||
glib_warning_func = func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return old_warning_func;
|
||||
}
|
||||
|
||||
/* compatibility code */
|
||||
GPrintFunc
|
||||
g_set_message_handler (GPrintFunc func)
|
||||
{
|
||||
GPrintFunc old_message_func;
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
old_message_func = glib_message_func;
|
||||
glib_message_func = func;
|
||||
g_mutex_unlock (g_messages_lock);
|
||||
|
||||
return old_message_func;
|
||||
}
|
||||
|
||||
void
|
||||
g_messages_init (void)
|
||||
{
|
||||
g_messages_lock = g_mutex_new();
|
||||
g_log_depth = g_private_new(NULL);
|
||||
}
|
965
glib/gnode.c
965
glib/gnode.c
@ -1,965 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* GNode: N-way tree implementation.
|
||||
* Copyright (C) 1998 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
/* node allocation
|
||||
*/
|
||||
struct _GAllocator /* from gmem.c */
|
||||
{
|
||||
gchar *name;
|
||||
guint16 n_preallocs;
|
||||
guint is_unused : 1;
|
||||
guint type : 4;
|
||||
GAllocator *last;
|
||||
GMemChunk *mem_chunk;
|
||||
GNode *free_nodes; /* implementation specific */
|
||||
};
|
||||
|
||||
G_LOCK_DEFINE_STATIC (current_allocator);
|
||||
static GAllocator *current_allocator = NULL;
|
||||
|
||||
/* HOLDS: current_allocator_lock */
|
||||
static void
|
||||
g_node_validate_allocator (GAllocator *allocator)
|
||||
{
|
||||
g_return_if_fail (allocator != NULL);
|
||||
g_return_if_fail (allocator->is_unused == TRUE);
|
||||
|
||||
if (allocator->type != G_ALLOCATOR_NODE)
|
||||
{
|
||||
allocator->type = G_ALLOCATOR_NODE;
|
||||
if (allocator->mem_chunk)
|
||||
{
|
||||
g_mem_chunk_destroy (allocator->mem_chunk);
|
||||
allocator->mem_chunk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allocator->mem_chunk)
|
||||
{
|
||||
allocator->mem_chunk = g_mem_chunk_new (allocator->name,
|
||||
sizeof (GNode),
|
||||
sizeof (GNode) * allocator->n_preallocs,
|
||||
G_ALLOC_ONLY);
|
||||
allocator->free_nodes = NULL;
|
||||
}
|
||||
|
||||
allocator->is_unused = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_node_push_allocator (GAllocator *allocator)
|
||||
{
|
||||
G_LOCK (current_allocator);
|
||||
g_node_validate_allocator ( allocator );
|
||||
allocator->last = current_allocator;
|
||||
current_allocator = allocator;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
void
|
||||
g_node_pop_allocator (void)
|
||||
{
|
||||
G_LOCK (current_allocator);
|
||||
if (current_allocator)
|
||||
{
|
||||
GAllocator *allocator;
|
||||
|
||||
allocator = current_allocator;
|
||||
current_allocator = allocator->last;
|
||||
allocator->last = NULL;
|
||||
allocator->is_unused = TRUE;
|
||||
}
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
GNode*
|
||||
g_node_new (gpointer data)
|
||||
{
|
||||
GNode *node;
|
||||
|
||||
G_LOCK (current_allocator);
|
||||
if (!current_allocator)
|
||||
{
|
||||
GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
|
||||
128);
|
||||
g_node_validate_allocator (allocator);
|
||||
allocator->last = NULL;
|
||||
current_allocator = allocator;
|
||||
}
|
||||
if (!current_allocator->free_nodes)
|
||||
node = g_chunk_new (GNode, current_allocator->mem_chunk);
|
||||
else
|
||||
{
|
||||
node = current_allocator->free_nodes;
|
||||
current_allocator->free_nodes = node->next;
|
||||
}
|
||||
G_UNLOCK (current_allocator);
|
||||
|
||||
node->data = data;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
node->parent = NULL;
|
||||
node->children = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
g_nodes_free (GNode *node)
|
||||
{
|
||||
GNode *parent;
|
||||
|
||||
parent = node;
|
||||
while (1)
|
||||
{
|
||||
if (parent->children)
|
||||
g_nodes_free (parent->children);
|
||||
if (parent->next)
|
||||
parent = parent->next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
G_LOCK (current_allocator);
|
||||
parent->next = current_allocator->free_nodes;
|
||||
current_allocator->free_nodes = node;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
void
|
||||
g_node_destroy (GNode *root)
|
||||
{
|
||||
g_return_if_fail (root != NULL);
|
||||
|
||||
if (!G_NODE_IS_ROOT (root))
|
||||
g_node_unlink (root);
|
||||
|
||||
g_nodes_free (root);
|
||||
}
|
||||
|
||||
void
|
||||
g_node_unlink (GNode *node)
|
||||
{
|
||||
g_return_if_fail (node != NULL);
|
||||
|
||||
if (node->prev)
|
||||
node->prev->next = node->next;
|
||||
else if (node->parent)
|
||||
node->parent->children = node->next;
|
||||
node->parent = NULL;
|
||||
if (node->next)
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
node->next = NULL;
|
||||
}
|
||||
node->prev = NULL;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_insert (GNode *parent,
|
||||
gint position,
|
||||
GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (parent != NULL, node);
|
||||
g_return_val_if_fail (node != NULL, node);
|
||||
g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
|
||||
|
||||
if (position > 0)
|
||||
return g_node_insert_before (parent,
|
||||
g_node_nth_child (parent, position),
|
||||
node);
|
||||
else if (position == 0)
|
||||
return g_node_prepend (parent, node);
|
||||
else /* if (position < 0) */
|
||||
return g_node_append (parent, node);
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_insert_before (GNode *parent,
|
||||
GNode *sibling,
|
||||
GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (parent != NULL, node);
|
||||
g_return_val_if_fail (node != NULL, node);
|
||||
g_return_val_if_fail (G_NODE_IS_ROOT (node), node);
|
||||
if (sibling)
|
||||
g_return_val_if_fail (sibling->parent == parent, node);
|
||||
|
||||
node->parent = parent;
|
||||
|
||||
if (sibling)
|
||||
{
|
||||
if (sibling->prev)
|
||||
{
|
||||
node->prev = sibling->prev;
|
||||
node->prev->next = node;
|
||||
node->next = sibling;
|
||||
sibling->prev = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->parent->children = node;
|
||||
node->next = sibling;
|
||||
sibling->prev = node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent->children)
|
||||
{
|
||||
sibling = parent->children;
|
||||
while (sibling->next)
|
||||
sibling = sibling->next;
|
||||
node->prev = sibling;
|
||||
sibling->next = node;
|
||||
}
|
||||
else
|
||||
node->parent->children = node;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_prepend (GNode *parent,
|
||||
GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (parent != NULL, node);
|
||||
|
||||
return g_node_insert_before (parent, parent->children, node);
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_get_root (GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, NULL);
|
||||
|
||||
while (node->parent)
|
||||
node = node->parent;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_node_is_ancestor (GNode *node,
|
||||
GNode *descendant)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, FALSE);
|
||||
g_return_val_if_fail (descendant != NULL, FALSE);
|
||||
|
||||
while (descendant)
|
||||
{
|
||||
if (descendant->parent == node)
|
||||
return TRUE;
|
||||
|
||||
descendant = descendant->parent;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* returns 1 for root, 2 for first level children,
|
||||
* 3 for children's children...
|
||||
*/
|
||||
guint
|
||||
g_node_depth (GNode *node)
|
||||
{
|
||||
register guint depth = 0;
|
||||
|
||||
while (node)
|
||||
{
|
||||
depth++;
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
void
|
||||
g_node_reverse_children (GNode *node)
|
||||
{
|
||||
GNode *child;
|
||||
GNode *last;
|
||||
|
||||
g_return_if_fail (node != NULL);
|
||||
|
||||
child = node->children;
|
||||
last = NULL;
|
||||
while (child)
|
||||
{
|
||||
last = child;
|
||||
child = last->next;
|
||||
last->next = last->prev;
|
||||
last->prev = child;
|
||||
}
|
||||
node->children = last;
|
||||
}
|
||||
|
||||
guint
|
||||
g_node_max_height (GNode *root)
|
||||
{
|
||||
register GNode *child;
|
||||
register guint max_height = 0;
|
||||
|
||||
if (!root)
|
||||
return 0;
|
||||
|
||||
child = root->children;
|
||||
while (child)
|
||||
{
|
||||
register guint tmp_height;
|
||||
|
||||
tmp_height = g_node_max_height (child);
|
||||
if (tmp_height > max_height)
|
||||
max_height = tmp_height;
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
return max_height + 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_traverse_pre_order (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
if (g_node_traverse_pre_order (current, flags, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_depth_traverse_pre_order (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
guint depth,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
depth--;
|
||||
if (!depth)
|
||||
return FALSE;
|
||||
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
if (g_node_depth_traverse_pre_order (current, flags, depth, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_traverse_post_order (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
if (g_node_traverse_post_order (current, flags, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_depth_traverse_post_order (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
guint depth,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
depth--;
|
||||
if (depth)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
if (g_node_depth_traverse_post_order (current, flags, depth, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_traverse_in_order (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
GNode *child;
|
||||
register GNode *current;
|
||||
|
||||
child = node->children;
|
||||
current = child;
|
||||
child = current->next;
|
||||
|
||||
if (g_node_traverse_in_order (current, flags, func, data))
|
||||
return TRUE;
|
||||
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
while (child)
|
||||
{
|
||||
current = child;
|
||||
child = current->next;
|
||||
if (g_node_traverse_in_order (current, flags, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_depth_traverse_in_order (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
guint depth,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
depth--;
|
||||
if (depth)
|
||||
{
|
||||
GNode *child;
|
||||
register GNode *current;
|
||||
|
||||
child = node->children;
|
||||
current = child;
|
||||
child = current->next;
|
||||
|
||||
if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
|
||||
return TRUE;
|
||||
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
while (child)
|
||||
{
|
||||
current = child;
|
||||
child = current->next;
|
||||
if (g_node_depth_traverse_in_order (current, flags, depth, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (node, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_traverse_children (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
child = node->children;
|
||||
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
|
||||
if (current->children)
|
||||
{
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (current, data))
|
||||
return TRUE;
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (current, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
child = node->children;
|
||||
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
|
||||
if (current->children &&
|
||||
g_node_traverse_children (current, flags, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_depth_traverse_children (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
guint depth,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
child = node->children;
|
||||
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
|
||||
if (current->children)
|
||||
{
|
||||
if ((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (current, data))
|
||||
return TRUE;
|
||||
}
|
||||
else if ((flags & G_TRAVERSE_LEAFS) &&
|
||||
func (current, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
depth--;
|
||||
if (!depth)
|
||||
return FALSE;
|
||||
|
||||
child = node->children;
|
||||
|
||||
while (child)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = child;
|
||||
child = current->next;
|
||||
|
||||
if (current->children &&
|
||||
g_node_depth_traverse_children (current, flags, depth, func, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_node_traverse (GNode *root,
|
||||
GTraverseType order,
|
||||
GTraverseFlags flags,
|
||||
gint depth,
|
||||
GNodeTraverseFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_if_fail (root != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
g_return_if_fail (order <= G_LEVEL_ORDER);
|
||||
g_return_if_fail (flags <= G_TRAVERSE_MASK);
|
||||
g_return_if_fail (depth == -1 || depth > 0);
|
||||
|
||||
switch (order)
|
||||
{
|
||||
case G_PRE_ORDER:
|
||||
if (depth < 0)
|
||||
g_node_traverse_pre_order (root, flags, func, data);
|
||||
else
|
||||
g_node_depth_traverse_pre_order (root, flags, depth, func, data);
|
||||
break;
|
||||
case G_POST_ORDER:
|
||||
if (depth < 0)
|
||||
g_node_traverse_post_order (root, flags, func, data);
|
||||
else
|
||||
g_node_depth_traverse_post_order (root, flags, depth, func, data);
|
||||
break;
|
||||
case G_IN_ORDER:
|
||||
if (depth < 0)
|
||||
g_node_traverse_in_order (root, flags, func, data);
|
||||
else
|
||||
g_node_depth_traverse_in_order (root, flags, depth, func, data);
|
||||
break;
|
||||
case G_LEVEL_ORDER:
|
||||
if (root->children)
|
||||
{
|
||||
if (!((flags & G_TRAVERSE_NON_LEAFS) &&
|
||||
func (root, data)))
|
||||
{
|
||||
if (depth < 0)
|
||||
g_node_traverse_children (root, flags, func, data);
|
||||
else
|
||||
{
|
||||
depth--;
|
||||
if (depth)
|
||||
g_node_depth_traverse_children (root, flags, depth, func, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (flags & G_TRAVERSE_LEAFS)
|
||||
func (root, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_node_find_func (GNode *node,
|
||||
gpointer data)
|
||||
{
|
||||
register gpointer *d = data;
|
||||
|
||||
if (*d != node->data)
|
||||
return FALSE;
|
||||
|
||||
*(++d) = node;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_find (GNode *root,
|
||||
GTraverseType order,
|
||||
GTraverseFlags flags,
|
||||
gpointer data)
|
||||
{
|
||||
gpointer d[2];
|
||||
|
||||
g_return_val_if_fail (root != NULL, NULL);
|
||||
g_return_val_if_fail (order <= G_LEVEL_ORDER, NULL);
|
||||
g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
|
||||
|
||||
d[0] = data;
|
||||
d[1] = NULL;
|
||||
|
||||
g_node_traverse (root, order, flags, -1, g_node_find_func, d);
|
||||
|
||||
return d[1];
|
||||
}
|
||||
|
||||
static void
|
||||
g_node_count_func (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
guint *n)
|
||||
{
|
||||
if (node->children)
|
||||
{
|
||||
GNode *child;
|
||||
|
||||
if (flags & G_TRAVERSE_NON_LEAFS)
|
||||
(*n)++;
|
||||
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
g_node_count_func (child, flags, n);
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
else if (flags & G_TRAVERSE_LEAFS)
|
||||
(*n)++;
|
||||
}
|
||||
|
||||
guint
|
||||
g_node_n_nodes (GNode *root,
|
||||
GTraverseFlags flags)
|
||||
{
|
||||
guint n = 0;
|
||||
|
||||
g_return_val_if_fail (root != NULL, 0);
|
||||
g_return_val_if_fail (flags <= G_TRAVERSE_MASK, 0);
|
||||
|
||||
g_node_count_func (root, flags, &n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_last_child (GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, NULL);
|
||||
|
||||
node = node->children;
|
||||
if (node)
|
||||
while (node->next)
|
||||
node = node->next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_nth_child (GNode *node,
|
||||
guint n)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, NULL);
|
||||
|
||||
node = node->children;
|
||||
if (node)
|
||||
while ((n-- > 0) && node)
|
||||
node = node->next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
guint
|
||||
g_node_n_children (GNode *node)
|
||||
{
|
||||
guint n = 0;
|
||||
|
||||
g_return_val_if_fail (node != NULL, 0);
|
||||
|
||||
node = node->children;
|
||||
while (node)
|
||||
{
|
||||
n++;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_find_child (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, NULL);
|
||||
g_return_val_if_fail (flags <= G_TRAVERSE_MASK, NULL);
|
||||
|
||||
node = node->children;
|
||||
while (node)
|
||||
{
|
||||
if (node->data == data)
|
||||
{
|
||||
if (G_NODE_IS_LEAF (node))
|
||||
{
|
||||
if (flags & G_TRAVERSE_LEAFS)
|
||||
return node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & G_TRAVERSE_NON_LEAFS)
|
||||
return node;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
g_node_child_position (GNode *node,
|
||||
GNode *child)
|
||||
{
|
||||
register guint n = 0;
|
||||
|
||||
g_return_val_if_fail (node != NULL, -1);
|
||||
g_return_val_if_fail (child != NULL, -1);
|
||||
g_return_val_if_fail (child->parent == node, -1);
|
||||
|
||||
node = node->children;
|
||||
while (node)
|
||||
{
|
||||
if (node == child)
|
||||
return n;
|
||||
n++;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
gint
|
||||
g_node_child_index (GNode *node,
|
||||
gpointer data)
|
||||
{
|
||||
register guint n = 0;
|
||||
|
||||
g_return_val_if_fail (node != NULL, -1);
|
||||
|
||||
node = node->children;
|
||||
while (node)
|
||||
{
|
||||
if (node->data == data)
|
||||
return n;
|
||||
n++;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_first_sibling (GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, NULL);
|
||||
|
||||
while (node->prev)
|
||||
node = node->prev;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
GNode*
|
||||
g_node_last_sibling (GNode *node)
|
||||
{
|
||||
g_return_val_if_fail (node != NULL, NULL);
|
||||
|
||||
while (node->next)
|
||||
node = node->next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
g_node_children_foreach (GNode *node,
|
||||
GTraverseFlags flags,
|
||||
GNodeForeachFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_if_fail (node != NULL);
|
||||
g_return_if_fail (flags <= G_TRAVERSE_MASK);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
node = node->children;
|
||||
while (node)
|
||||
{
|
||||
register GNode *current;
|
||||
|
||||
current = node;
|
||||
node = current->next;
|
||||
if (G_NODE_IS_LEAF (current))
|
||||
{
|
||||
if (flags & G_TRAVERSE_LEAFS)
|
||||
func (current, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & G_TRAVERSE_NON_LEAFS)
|
||||
func (current, data);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
static const guint g_primes[] =
|
||||
{
|
||||
11,
|
||||
19,
|
||||
37,
|
||||
73,
|
||||
109,
|
||||
163,
|
||||
251,
|
||||
367,
|
||||
557,
|
||||
823,
|
||||
1237,
|
||||
1861,
|
||||
2777,
|
||||
4177,
|
||||
6247,
|
||||
9371,
|
||||
14057,
|
||||
21089,
|
||||
31627,
|
||||
47431,
|
||||
71143,
|
||||
106721,
|
||||
160073,
|
||||
240101,
|
||||
360163,
|
||||
540217,
|
||||
810343,
|
||||
1215497,
|
||||
1823231,
|
||||
2734867,
|
||||
4102283,
|
||||
6153409,
|
||||
9230113,
|
||||
13845163,
|
||||
};
|
||||
|
||||
static const guint g_nprimes = sizeof (g_primes) / sizeof (g_primes[0]);
|
||||
|
||||
guint
|
||||
g_spaced_primes_closest (guint num)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < g_nprimes; i++)
|
||||
if (g_primes[i] > num)
|
||||
return g_primes[i];
|
||||
|
||||
return g_primes[g_nprimes - 1];
|
||||
}
|
459
glib/grel.c
459
glib/grel.c
@ -1,459 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct _GRealRelation GRealRelation;
|
||||
typedef struct _GRealTuples GRealTuples;
|
||||
|
||||
struct _GRealRelation
|
||||
{
|
||||
gint fields;
|
||||
gint current_field;
|
||||
|
||||
GHashTable *all_tuples;
|
||||
GHashTable **hashed_tuple_tables;
|
||||
GMemChunk *tuple_chunk;
|
||||
|
||||
gint count;
|
||||
};
|
||||
|
||||
struct _GRealTuples
|
||||
{
|
||||
gint len;
|
||||
gint width;
|
||||
gpointer *data;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
tuple_equal_2 (gconstpointer v_a,
|
||||
gconstpointer v_b)
|
||||
{
|
||||
gpointer* a = (gpointer*) v_a;
|
||||
gpointer* b = (gpointer*) v_b;
|
||||
|
||||
return a[0] == b[0] && a[1] == b[1];
|
||||
}
|
||||
|
||||
static guint
|
||||
tuple_hash_2 (gconstpointer v_a)
|
||||
{
|
||||
gpointer* a = (gpointer*) v_a;
|
||||
|
||||
return (gulong)a[0] ^ (gulong)a[1];
|
||||
}
|
||||
|
||||
static GHashFunc
|
||||
tuple_hash (gint fields)
|
||||
{
|
||||
switch (fields)
|
||||
{
|
||||
case 2:
|
||||
return tuple_hash_2;
|
||||
default:
|
||||
g_error ("no tuple hash for %d", fields);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GCompareFunc
|
||||
tuple_equal (gint fields)
|
||||
{
|
||||
switch (fields)
|
||||
{
|
||||
case 2:
|
||||
return tuple_equal_2;
|
||||
default:
|
||||
g_error ("no tuple equal for %d", fields);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GRelation*
|
||||
g_relation_new (gint fields)
|
||||
{
|
||||
GRealRelation* rel = g_new0 (GRealRelation, 1);
|
||||
|
||||
rel->fields = fields;
|
||||
rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk",
|
||||
fields * sizeof (gpointer),
|
||||
fields * sizeof (gpointer) * 128,
|
||||
G_ALLOC_AND_FREE);
|
||||
rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
|
||||
rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
|
||||
|
||||
return (GRelation*) rel;
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
g_hash_table_destroy ((GHashTable*) value);
|
||||
}
|
||||
|
||||
void
|
||||
g_relation_destroy (GRelation *relation)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
gint i;
|
||||
|
||||
if (rel)
|
||||
{
|
||||
g_hash_table_destroy (rel->all_tuples);
|
||||
g_mem_chunk_destroy (rel->tuple_chunk);
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
{
|
||||
if (rel->hashed_tuple_tables[i])
|
||||
{
|
||||
g_hash_table_foreach (rel->hashed_tuple_tables[i], g_relation_free_array, NULL);
|
||||
g_hash_table_destroy (rel->hashed_tuple_tables[i]);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (rel->hashed_tuple_tables);
|
||||
g_free (rel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_relation_index (GRelation *relation,
|
||||
gint field,
|
||||
GHashFunc hash_func,
|
||||
GCompareFunc key_compare_func)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
|
||||
g_return_if_fail (relation != NULL);
|
||||
|
||||
g_return_if_fail (rel->count == 0 && rel->hashed_tuple_tables[field] == NULL);
|
||||
|
||||
rel->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_compare_func);
|
||||
}
|
||||
|
||||
void
|
||||
g_relation_insert (GRelation *relation,
|
||||
...)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk);
|
||||
va_list args;
|
||||
gint i;
|
||||
|
||||
va_start(args, relation);
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
tuple[i] = va_arg(args, gpointer);
|
||||
|
||||
va_end(args);
|
||||
|
||||
g_hash_table_insert (rel->all_tuples, tuple, tuple);
|
||||
|
||||
rel->count += 1;
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
{
|
||||
GHashTable *table;
|
||||
gpointer key;
|
||||
GHashTable *per_key_table;
|
||||
|
||||
table = rel->hashed_tuple_tables[i];
|
||||
|
||||
if (table == NULL)
|
||||
continue;
|
||||
|
||||
key = tuple[i];
|
||||
per_key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (per_key_table == NULL)
|
||||
{
|
||||
per_key_table = g_hash_table_new (tuple_hash (rel->fields), tuple_equal (rel->fields));
|
||||
g_hash_table_insert (table, key, per_key_table);
|
||||
}
|
||||
|
||||
g_hash_table_insert (per_key_table, tuple, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_delete_tuple (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gpointer *tuple = (gpointer*) tuple_value;
|
||||
GRealRelation *rel = (GRealRelation *) user_data;
|
||||
gint j;
|
||||
|
||||
g_assert (tuple_key == tuple_value);
|
||||
|
||||
for (j = 0; j < rel->fields; j += 1)
|
||||
{
|
||||
GHashTable *one_table = rel->hashed_tuple_tables[j];
|
||||
gpointer one_key;
|
||||
GHashTable *per_key_table;
|
||||
|
||||
if (one_table == NULL)
|
||||
continue;
|
||||
|
||||
if (j == rel->current_field)
|
||||
/* can't delete from the table we're foreaching in */
|
||||
continue;
|
||||
|
||||
one_key = tuple[j];
|
||||
|
||||
per_key_table = g_hash_table_lookup (one_table, one_key);
|
||||
|
||||
g_hash_table_remove (per_key_table, tuple);
|
||||
}
|
||||
|
||||
g_hash_table_remove (rel->all_tuples, tuple);
|
||||
|
||||
rel->count -= 1;
|
||||
}
|
||||
|
||||
gint
|
||||
g_relation_delete (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
GHashTable *table = rel->hashed_tuple_tables[field];
|
||||
GHashTable *key_table;
|
||||
gint count = rel->count;
|
||||
|
||||
g_return_val_if_fail (relation != NULL, 0);
|
||||
g_return_val_if_fail (table != NULL, 0);
|
||||
|
||||
key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (!key_table)
|
||||
return 0;
|
||||
|
||||
rel->current_field = field;
|
||||
|
||||
g_hash_table_foreach (key_table, g_relation_delete_tuple, rel);
|
||||
|
||||
g_hash_table_remove (table, key);
|
||||
|
||||
g_hash_table_destroy (key_table);
|
||||
|
||||
/* @@@ FIXME: Remove empty hash tables. */
|
||||
|
||||
return count - rel->count;
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_select_tuple (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gpointer *tuple = (gpointer*) tuple_value;
|
||||
GRealTuples *tuples = (GRealTuples*) user_data;
|
||||
gint stride = sizeof (gpointer) * tuples->width;
|
||||
|
||||
g_assert (tuple_key == tuple_value);
|
||||
|
||||
memcpy (tuples->data + (tuples->len * tuples->width),
|
||||
tuple,
|
||||
stride);
|
||||
|
||||
tuples->len += 1;
|
||||
}
|
||||
|
||||
GTuples*
|
||||
g_relation_select (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
GHashTable *table = rel->hashed_tuple_tables[field];
|
||||
GHashTable *key_table;
|
||||
GRealTuples *tuples = g_new0 (GRealTuples, 1);
|
||||
gint count;
|
||||
|
||||
g_return_val_if_fail (relation != NULL, NULL);
|
||||
g_return_val_if_fail (table != NULL, NULL);
|
||||
|
||||
key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (!key_table)
|
||||
return (GTuples*)tuples;
|
||||
|
||||
count = g_relation_count (relation, key, field);
|
||||
|
||||
tuples->data = g_malloc (sizeof (gpointer) * rel->fields * count);
|
||||
tuples->width = rel->fields;
|
||||
|
||||
g_hash_table_foreach (key_table, g_relation_select_tuple, tuples);
|
||||
|
||||
g_assert (count == tuples->len);
|
||||
|
||||
return (GTuples*)tuples;
|
||||
}
|
||||
|
||||
gint
|
||||
g_relation_count (GRelation *relation,
|
||||
gconstpointer key,
|
||||
gint field)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
GHashTable *table = rel->hashed_tuple_tables[field];
|
||||
GHashTable *key_table;
|
||||
|
||||
g_return_val_if_fail (relation != NULL, 0);
|
||||
g_return_val_if_fail (table != NULL, 0);
|
||||
|
||||
key_table = g_hash_table_lookup (table, key);
|
||||
|
||||
if (!key_table)
|
||||
return 0;
|
||||
|
||||
return g_hash_table_size (key_table);
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_relation_exists (GRelation *relation, ...)
|
||||
{
|
||||
GRealRelation *rel = (GRealRelation *) relation;
|
||||
gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk);
|
||||
va_list args;
|
||||
gint i;
|
||||
gboolean result;
|
||||
|
||||
va_start(args, relation);
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
tuple[i] = va_arg(args, gpointer);
|
||||
|
||||
va_end(args);
|
||||
|
||||
result = g_hash_table_lookup (rel->all_tuples, tuple) != NULL;
|
||||
|
||||
g_mem_chunk_free (rel->tuple_chunk, tuple);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
g_tuples_destroy (GTuples *tuples0)
|
||||
{
|
||||
GRealTuples *tuples = (GRealTuples*) tuples0;
|
||||
|
||||
if (tuples)
|
||||
{
|
||||
g_free (tuples->data);
|
||||
g_free (tuples);
|
||||
}
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_tuples_index (GTuples *tuples0,
|
||||
gint index,
|
||||
gint field)
|
||||
{
|
||||
GRealTuples *tuples = (GRealTuples*) tuples0;
|
||||
|
||||
g_return_val_if_fail (tuples0 != NULL, NULL);
|
||||
g_return_val_if_fail (field < tuples->width, NULL);
|
||||
|
||||
return tuples->data[index * tuples->width + field];
|
||||
}
|
||||
|
||||
/* Print
|
||||
*/
|
||||
|
||||
static void
|
||||
g_relation_print_one (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint i;
|
||||
GString *gstring;
|
||||
GRealRelation* rel = (GRealRelation*) user_data;
|
||||
gpointer* tuples = (gpointer*) tuple_value;
|
||||
|
||||
gstring = g_string_new ("[");
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
{
|
||||
g_string_sprintfa (gstring, "%p", tuples[i]);
|
||||
|
||||
if (i < (rel->fields - 1))
|
||||
g_string_append (gstring, ",");
|
||||
}
|
||||
|
||||
g_string_append (gstring, "]");
|
||||
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, gstring->str);
|
||||
g_string_free (gstring, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
g_relation_print_index (gpointer tuple_key,
|
||||
gpointer tuple_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GRealRelation* rel = (GRealRelation*) user_data;
|
||||
GHashTable* table = (GHashTable*) tuple_value;
|
||||
|
||||
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "*** key %p", tuple_key);
|
||||
|
||||
g_hash_table_foreach (table,
|
||||
g_relation_print_one,
|
||||
rel);
|
||||
}
|
||||
|
||||
void
|
||||
g_relation_print (GRelation *relation)
|
||||
{
|
||||
gint i;
|
||||
GRealRelation* rel = (GRealRelation*) relation;
|
||||
|
||||
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "*** all tuples (%d)", rel->count);
|
||||
|
||||
g_hash_table_foreach (rel->all_tuples,
|
||||
g_relation_print_one,
|
||||
rel);
|
||||
|
||||
for (i = 0; i < rel->fields; i += 1)
|
||||
{
|
||||
if (rel->hashed_tuple_tables[i] == NULL)
|
||||
continue;
|
||||
|
||||
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "*** index %d", i);
|
||||
|
||||
g_hash_table_foreach (rel->hashed_tuple_tables[i],
|
||||
g_relation_print_index,
|
||||
rel);
|
||||
}
|
||||
|
||||
}
|
1752
glib/gscanner.c
1752
glib/gscanner.c
File diff suppressed because it is too large
Load Diff
595
glib/gslist.c
595
glib/gslist.c
@ -1,595 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
struct _GAllocator /* from gmem.c */
|
||||
{
|
||||
gchar *name;
|
||||
guint16 n_preallocs;
|
||||
guint is_unused : 1;
|
||||
guint type : 4;
|
||||
GAllocator *last;
|
||||
GMemChunk *mem_chunk;
|
||||
GSList *free_lists; /* implementation specific */
|
||||
};
|
||||
|
||||
G_LOCK_DEFINE_STATIC (current_allocator);
|
||||
static GAllocator *current_allocator = NULL;
|
||||
|
||||
/* HOLDS: current_allocator_lock */
|
||||
static void
|
||||
g_slist_validate_allocator (GAllocator *allocator)
|
||||
{
|
||||
g_return_if_fail (allocator != NULL);
|
||||
g_return_if_fail (allocator->is_unused == TRUE);
|
||||
|
||||
if (allocator->type != G_ALLOCATOR_SLIST)
|
||||
{
|
||||
allocator->type = G_ALLOCATOR_SLIST;
|
||||
if (allocator->mem_chunk)
|
||||
{
|
||||
g_mem_chunk_destroy (allocator->mem_chunk);
|
||||
allocator->mem_chunk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allocator->mem_chunk)
|
||||
{
|
||||
allocator->mem_chunk = g_mem_chunk_new (allocator->name,
|
||||
sizeof (GSList),
|
||||
sizeof (GSList) * allocator->n_preallocs,
|
||||
G_ALLOC_ONLY);
|
||||
allocator->free_lists = NULL;
|
||||
}
|
||||
|
||||
allocator->is_unused = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_push_allocator (GAllocator *allocator)
|
||||
{
|
||||
G_LOCK (current_allocator);
|
||||
g_slist_validate_allocator (allocator);
|
||||
allocator->last = current_allocator;
|
||||
current_allocator = allocator;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_pop_allocator (void)
|
||||
{
|
||||
G_LOCK (current_allocator);
|
||||
if (current_allocator)
|
||||
{
|
||||
GAllocator *allocator;
|
||||
|
||||
allocator = current_allocator;
|
||||
current_allocator = allocator->last;
|
||||
allocator->last = NULL;
|
||||
allocator->is_unused = TRUE;
|
||||
}
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_alloc (void)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
G_LOCK (current_allocator);
|
||||
if (!current_allocator)
|
||||
{
|
||||
GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
|
||||
128);
|
||||
g_slist_validate_allocator (allocator);
|
||||
allocator->last = NULL;
|
||||
current_allocator = allocator;
|
||||
}
|
||||
if (!current_allocator->free_lists)
|
||||
{
|
||||
list = g_chunk_new (GSList, current_allocator->mem_chunk);
|
||||
list->data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_allocator->free_lists->data)
|
||||
{
|
||||
list = current_allocator->free_lists->data;
|
||||
current_allocator->free_lists->data = list->next;
|
||||
list->data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list->next;
|
||||
}
|
||||
}
|
||||
G_UNLOCK (current_allocator);
|
||||
|
||||
list->next = NULL;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_free (GSList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
list->data = list->next;
|
||||
G_LOCK (current_allocator);
|
||||
list->next = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_free_1 (GSList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
list->data = NULL;
|
||||
G_LOCK (current_allocator);
|
||||
list->next = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_append (GSList *list,
|
||||
gpointer data)
|
||||
{
|
||||
GSList *new_list;
|
||||
GSList *last;
|
||||
|
||||
new_list = g_slist_alloc ();
|
||||
new_list->data = data;
|
||||
|
||||
if (list)
|
||||
{
|
||||
last = g_slist_last (list);
|
||||
/* g_assert (last != NULL); */
|
||||
last->next = new_list;
|
||||
|
||||
return list;
|
||||
}
|
||||
else
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_prepend (GSList *list,
|
||||
gpointer data)
|
||||
{
|
||||
GSList *new_list;
|
||||
|
||||
new_list = g_slist_alloc ();
|
||||
new_list->data = data;
|
||||
new_list->next = list;
|
||||
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_insert (GSList *list,
|
||||
gpointer data,
|
||||
gint position)
|
||||
{
|
||||
GSList *prev_list;
|
||||
GSList *tmp_list;
|
||||
GSList *new_list;
|
||||
|
||||
if (position < 0)
|
||||
return g_slist_append (list, data);
|
||||
else if (position == 0)
|
||||
return g_slist_prepend (list, data);
|
||||
|
||||
new_list = g_slist_alloc ();
|
||||
new_list->data = data;
|
||||
|
||||
if (!list)
|
||||
return new_list;
|
||||
|
||||
prev_list = NULL;
|
||||
tmp_list = list;
|
||||
|
||||
while ((position-- > 0) && tmp_list)
|
||||
{
|
||||
prev_list = tmp_list;
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
|
||||
if (prev_list)
|
||||
{
|
||||
new_list->next = prev_list->next;
|
||||
prev_list->next = new_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_list->next = list;
|
||||
list = new_list;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GSList *
|
||||
g_slist_concat (GSList *list1, GSList *list2)
|
||||
{
|
||||
if (list2)
|
||||
{
|
||||
if (list1)
|
||||
g_slist_last (list1)->next = list2;
|
||||
else
|
||||
list1 = list2;
|
||||
}
|
||||
|
||||
return list1;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_remove (GSList *list,
|
||||
gpointer data)
|
||||
{
|
||||
GSList *tmp;
|
||||
GSList *prev;
|
||||
|
||||
prev = NULL;
|
||||
tmp = list;
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
if (tmp->data == data)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = tmp->next;
|
||||
if (list == tmp)
|
||||
list = list->next;
|
||||
|
||||
tmp->next = NULL;
|
||||
g_slist_free (tmp);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_remove_link (GSList *list,
|
||||
GSList *link)
|
||||
{
|
||||
GSList *tmp;
|
||||
GSList *prev;
|
||||
|
||||
prev = NULL;
|
||||
tmp = list;
|
||||
|
||||
while (tmp)
|
||||
{
|
||||
if (tmp == link)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = tmp->next;
|
||||
if (list == tmp)
|
||||
list = list->next;
|
||||
|
||||
tmp->next = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_copy (GSList *list)
|
||||
{
|
||||
GSList *new_list = NULL;
|
||||
|
||||
if (list)
|
||||
{
|
||||
GSList *last;
|
||||
|
||||
new_list = g_slist_alloc ();
|
||||
new_list->data = list->data;
|
||||
last = new_list;
|
||||
list = list->next;
|
||||
while (list)
|
||||
{
|
||||
last->next = g_slist_alloc ();
|
||||
last = last->next;
|
||||
last->data = list->data;
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_reverse (GSList *list)
|
||||
{
|
||||
GSList *prev = NULL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
GSList *next = list->next;
|
||||
|
||||
list->next = prev;
|
||||
|
||||
prev = list;
|
||||
list = next;
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_nth (GSList *list,
|
||||
guint n)
|
||||
{
|
||||
while ((n-- > 0) && list)
|
||||
list = list->next;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_slist_nth_data (GSList *list,
|
||||
guint n)
|
||||
{
|
||||
while ((n-- > 0) && list)
|
||||
list = list->next;
|
||||
|
||||
return list ? list->data : NULL;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_find (GSList *list,
|
||||
gpointer data)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
if (list->data == data)
|
||||
break;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_find_custom (GSList *list,
|
||||
gpointer data,
|
||||
GCompareFunc func)
|
||||
{
|
||||
g_return_val_if_fail (func != NULL, list);
|
||||
|
||||
while (list)
|
||||
{
|
||||
if (! func (list->data, data))
|
||||
return list;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
g_slist_position (GSList *list,
|
||||
GSList *link)
|
||||
{
|
||||
gint i;
|
||||
|
||||
i = 0;
|
||||
while (list)
|
||||
{
|
||||
if (list == link)
|
||||
return i;
|
||||
i++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
gint
|
||||
g_slist_index (GSList *list,
|
||||
gpointer data)
|
||||
{
|
||||
gint i;
|
||||
|
||||
i = 0;
|
||||
while (list)
|
||||
{
|
||||
if (list->data == data)
|
||||
return i;
|
||||
i++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_last (GSList *list)
|
||||
{
|
||||
if (list)
|
||||
{
|
||||
while (list->next)
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
guint
|
||||
g_slist_length (GSList *list)
|
||||
{
|
||||
guint length;
|
||||
|
||||
length = 0;
|
||||
while (list)
|
||||
{
|
||||
length++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_foreach (GSList *list,
|
||||
GFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
while (list)
|
||||
{
|
||||
(*func) (list->data, user_data);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_insert_sorted (GSList *list,
|
||||
gpointer data,
|
||||
GCompareFunc func)
|
||||
{
|
||||
GSList *tmp_list = list;
|
||||
GSList *prev_list = NULL;
|
||||
GSList *new_list;
|
||||
gint cmp;
|
||||
|
||||
g_return_val_if_fail (func != NULL, list);
|
||||
|
||||
if (!list)
|
||||
{
|
||||
new_list = g_slist_alloc();
|
||||
new_list->data = data;
|
||||
return new_list;
|
||||
}
|
||||
|
||||
cmp = (*func) (data, tmp_list->data);
|
||||
|
||||
while ((tmp_list->next) && (cmp > 0))
|
||||
{
|
||||
prev_list = tmp_list;
|
||||
tmp_list = tmp_list->next;
|
||||
cmp = (*func) (data, tmp_list->data);
|
||||
}
|
||||
|
||||
new_list = g_slist_alloc();
|
||||
new_list->data = data;
|
||||
|
||||
if ((!tmp_list->next) && (cmp > 0))
|
||||
{
|
||||
tmp_list->next = new_list;
|
||||
return list;
|
||||
}
|
||||
|
||||
if (prev_list)
|
||||
{
|
||||
prev_list->next = new_list;
|
||||
new_list->next = tmp_list;
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_list->next = list;
|
||||
return new_list;
|
||||
}
|
||||
}
|
||||
|
||||
static GSList*
|
||||
g_slist_sort_merge (GSList *l1,
|
||||
GSList *l2,
|
||||
GCompareFunc compare_func)
|
||||
{
|
||||
GSList list, *l;
|
||||
|
||||
l=&list;
|
||||
|
||||
while (l1 && l2)
|
||||
{
|
||||
if (compare_func(l1->data,l2->data) < 0)
|
||||
{
|
||||
l=l->next=l1;
|
||||
l1=l1->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
l=l->next=l2;
|
||||
l2=l2->next;
|
||||
}
|
||||
}
|
||||
l->next= l1 ? l1 : l2;
|
||||
|
||||
return list.next;
|
||||
}
|
||||
|
||||
GSList*
|
||||
g_slist_sort (GSList *list,
|
||||
GCompareFunc compare_func)
|
||||
{
|
||||
GSList *l1, *l2;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
if (!list->next)
|
||||
return list;
|
||||
|
||||
l1 = list;
|
||||
l2 = list->next;
|
||||
|
||||
while ((l2 = l2->next) != NULL)
|
||||
{
|
||||
if ((l2 = l2->next) == NULL)
|
||||
break;
|
||||
l1=l1->next;
|
||||
}
|
||||
l2 = l1->next;
|
||||
l1->next = NULL;
|
||||
|
||||
return g_slist_sort_merge (g_slist_sort (list, compare_func),
|
||||
g_slist_sort (l2, compare_func),
|
||||
compare_func);
|
||||
}
|
1496
glib/gstrfuncs.c
1496
glib/gstrfuncs.c
File diff suppressed because it is too large
Load Diff
512
glib/gstring.c
512
glib/gstring.c
@ -1,512 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
typedef struct _GRealStringChunk GRealStringChunk;
|
||||
typedef struct _GRealString GRealString;
|
||||
|
||||
struct _GRealStringChunk
|
||||
{
|
||||
GHashTable *const_table;
|
||||
GSList *storage_list;
|
||||
gint storage_next;
|
||||
gint this_size;
|
||||
gint default_size;
|
||||
};
|
||||
|
||||
struct _GRealString
|
||||
{
|
||||
gchar *str;
|
||||
gint len;
|
||||
gint alloc;
|
||||
};
|
||||
|
||||
G_LOCK_DEFINE_STATIC (string_mem_chunk);
|
||||
static GMemChunk *string_mem_chunk = NULL;
|
||||
|
||||
/* Hash Functions.
|
||||
*/
|
||||
|
||||
gint
|
||||
g_str_equal (gconstpointer v, gconstpointer v2)
|
||||
{
|
||||
return strcmp ((const gchar*) v, (const gchar*)v2) == 0;
|
||||
}
|
||||
|
||||
/* 31 bit hash function */
|
||||
guint
|
||||
g_str_hash (gconstpointer key)
|
||||
{
|
||||
const char *p = key;
|
||||
guint h = *p;
|
||||
|
||||
if (h)
|
||||
for (p += 1; *p != '\0'; p++)
|
||||
h = (h << 5) - h + *p;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* String Chunks.
|
||||
*/
|
||||
|
||||
GStringChunk*
|
||||
g_string_chunk_new (gint default_size)
|
||||
{
|
||||
GRealStringChunk *new_chunk = g_new (GRealStringChunk, 1);
|
||||
gint size = 1;
|
||||
|
||||
while (size < default_size)
|
||||
size <<= 1;
|
||||
|
||||
new_chunk->const_table = NULL;
|
||||
new_chunk->storage_list = NULL;
|
||||
new_chunk->storage_next = size;
|
||||
new_chunk->default_size = size;
|
||||
new_chunk->this_size = size;
|
||||
|
||||
return (GStringChunk*) new_chunk;
|
||||
}
|
||||
|
||||
void
|
||||
g_string_chunk_free (GStringChunk *fchunk)
|
||||
{
|
||||
GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
|
||||
GSList *tmp_list;
|
||||
|
||||
g_return_if_fail (chunk != NULL);
|
||||
|
||||
if (chunk->storage_list)
|
||||
{
|
||||
for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
|
||||
g_free (tmp_list->data);
|
||||
|
||||
g_slist_free (chunk->storage_list);
|
||||
}
|
||||
|
||||
if (chunk->const_table)
|
||||
g_hash_table_destroy (chunk->const_table);
|
||||
|
||||
g_free (chunk);
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_string_chunk_insert (GStringChunk *fchunk,
|
||||
const gchar *string)
|
||||
{
|
||||
GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
|
||||
gint len = strlen (string);
|
||||
char* pos;
|
||||
|
||||
g_return_val_if_fail (chunk != NULL, NULL);
|
||||
|
||||
if ((chunk->storage_next + len + 1) > chunk->this_size)
|
||||
{
|
||||
gint new_size = chunk->default_size;
|
||||
|
||||
while (new_size < len+1)
|
||||
new_size <<= 1;
|
||||
|
||||
chunk->storage_list = g_slist_prepend (chunk->storage_list,
|
||||
g_new (char, new_size));
|
||||
|
||||
chunk->this_size = new_size;
|
||||
chunk->storage_next = 0;
|
||||
}
|
||||
|
||||
pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
|
||||
|
||||
strcpy (pos, string);
|
||||
|
||||
chunk->storage_next += len + 1;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_string_chunk_insert_const (GStringChunk *fchunk,
|
||||
const gchar *string)
|
||||
{
|
||||
GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
|
||||
char* lookup;
|
||||
|
||||
g_return_val_if_fail (chunk != NULL, NULL);
|
||||
|
||||
if (!chunk->const_table)
|
||||
chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
|
||||
|
||||
if (!lookup)
|
||||
{
|
||||
lookup = g_string_chunk_insert (fchunk, string);
|
||||
g_hash_table_insert (chunk->const_table, lookup, lookup);
|
||||
}
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
/* Strings.
|
||||
*/
|
||||
static gint
|
||||
nearest_pow (gint num)
|
||||
{
|
||||
gint n = 1;
|
||||
|
||||
while (n < num)
|
||||
n <<= 1;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
g_string_maybe_expand (GRealString* string, gint len)
|
||||
{
|
||||
if (string->len + len >= string->alloc)
|
||||
{
|
||||
string->alloc = nearest_pow (string->len + len + 1);
|
||||
string->str = g_realloc (string->str, string->alloc);
|
||||
}
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_sized_new (guint dfl_size)
|
||||
{
|
||||
GRealString *string;
|
||||
|
||||
G_LOCK (string_mem_chunk);
|
||||
if (!string_mem_chunk)
|
||||
string_mem_chunk = g_mem_chunk_new ("string mem chunk",
|
||||
sizeof (GRealString),
|
||||
1024, G_ALLOC_AND_FREE);
|
||||
|
||||
string = g_chunk_new (GRealString, string_mem_chunk);
|
||||
G_UNLOCK (string_mem_chunk);
|
||||
|
||||
string->alloc = 0;
|
||||
string->len = 0;
|
||||
string->str = NULL;
|
||||
|
||||
g_string_maybe_expand (string, MAX (dfl_size, 2));
|
||||
string->str[0] = 0;
|
||||
|
||||
return (GString*) string;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_new (const gchar *init)
|
||||
{
|
||||
GString *string;
|
||||
|
||||
string = g_string_sized_new (2);
|
||||
|
||||
if (init)
|
||||
g_string_append (string, init);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
void
|
||||
g_string_free (GString *string,
|
||||
gint free_segment)
|
||||
{
|
||||
g_return_if_fail (string != NULL);
|
||||
|
||||
if (free_segment)
|
||||
g_free (string->str);
|
||||
|
||||
G_LOCK (string_mem_chunk);
|
||||
g_mem_chunk_free (string_mem_chunk, string);
|
||||
G_UNLOCK (string_mem_chunk);
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_assign (GString *lval,
|
||||
const gchar *rval)
|
||||
{
|
||||
g_return_val_if_fail (lval != NULL, NULL);
|
||||
g_return_val_if_fail (rval != NULL, NULL);
|
||||
|
||||
g_string_truncate (lval, 0);
|
||||
g_string_append (lval, rval);
|
||||
|
||||
return lval;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_truncate (GString* fstring,
|
||||
gint len)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (len >= 0, NULL);
|
||||
|
||||
string->len = len;
|
||||
|
||||
string->str[len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_append (GString *fstring,
|
||||
const gchar *val)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
int len;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (val != NULL, fstring);
|
||||
|
||||
len = strlen (val);
|
||||
g_string_maybe_expand (string, len);
|
||||
|
||||
strcpy (string->str + string->len, val);
|
||||
|
||||
string->len += len;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_append_c (GString *fstring,
|
||||
gchar c)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_string_maybe_expand (string, 1);
|
||||
|
||||
string->str[string->len++] = c;
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_prepend (GString *fstring,
|
||||
const gchar *val)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
gint len;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (val != NULL, fstring);
|
||||
|
||||
len = strlen (val);
|
||||
g_string_maybe_expand (string, len);
|
||||
|
||||
g_memmove (string->str + len, string->str, string->len);
|
||||
|
||||
strncpy (string->str, val, len);
|
||||
|
||||
string->len += len;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_prepend_c (GString *fstring,
|
||||
gchar c)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_string_maybe_expand (string, 1);
|
||||
|
||||
g_memmove (string->str + 1, string->str, string->len);
|
||||
|
||||
string->str[0] = c;
|
||||
|
||||
string->len += 1;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_insert (GString *fstring,
|
||||
gint pos,
|
||||
const gchar *val)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
gint len;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (val != NULL, fstring);
|
||||
g_return_val_if_fail (pos >= 0, fstring);
|
||||
g_return_val_if_fail (pos <= string->len, fstring);
|
||||
|
||||
len = strlen (val);
|
||||
g_string_maybe_expand (string, len);
|
||||
|
||||
g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
|
||||
|
||||
strncpy (string->str + pos, val, len);
|
||||
|
||||
string->len += len;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString *
|
||||
g_string_insert_c (GString *fstring,
|
||||
gint pos,
|
||||
gchar c)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (pos <= string->len, fstring);
|
||||
|
||||
g_string_maybe_expand (string, 1);
|
||||
|
||||
g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
|
||||
|
||||
string->str[pos] = c;
|
||||
|
||||
string->len += 1;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_erase (GString *fstring,
|
||||
gint pos,
|
||||
gint len)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
g_return_val_if_fail (len >= 0, fstring);
|
||||
g_return_val_if_fail (pos >= 0, fstring);
|
||||
g_return_val_if_fail (pos <= string->len, fstring);
|
||||
g_return_val_if_fail (pos + len <= string->len, fstring);
|
||||
|
||||
if (pos + len < string->len)
|
||||
g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
|
||||
|
||||
string->len -= len;
|
||||
|
||||
string->str[string->len] = 0;
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_down (GString *fstring)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
guchar *s;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
s = string->str;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = tolower (*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
GString*
|
||||
g_string_up (GString *fstring)
|
||||
{
|
||||
GRealString *string = (GRealString*)fstring;
|
||||
guchar *s;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
s = string->str;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper (*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return fstring;
|
||||
}
|
||||
|
||||
static void
|
||||
g_string_sprintfa_int (GString *string,
|
||||
const gchar *fmt,
|
||||
va_list args)
|
||||
{
|
||||
gchar *buffer;
|
||||
|
||||
buffer = g_strdup_vprintf (fmt, args);
|
||||
g_string_append (string, buffer);
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
g_string_sprintf (GString *string,
|
||||
const gchar *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
g_string_truncate (string, 0);
|
||||
|
||||
va_start (args, fmt);
|
||||
g_string_sprintfa_int (string, fmt, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
g_string_sprintfa (GString *string,
|
||||
const gchar *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
g_string_sprintfa_int (string, fmt, args);
|
||||
va_end (args);
|
||||
}
|
201
glib/gtimer.c
201
glib/gtimer.c
@ -1,201 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "glib.h"
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifndef NATIVE_WIN32
|
||||
#include <sys/time.h>
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
#include <windows.h>
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
typedef struct _GRealTimer GRealTimer;
|
||||
|
||||
struct _GRealTimer
|
||||
{
|
||||
#ifdef NATIVE_WIN32
|
||||
DWORD start;
|
||||
DWORD end;
|
||||
#else /* !NATIVE_WIN32 */
|
||||
struct timeval start;
|
||||
struct timeval end;
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
|
||||
guint active : 1;
|
||||
};
|
||||
|
||||
GTimer*
|
||||
g_timer_new (void)
|
||||
{
|
||||
GRealTimer *timer;
|
||||
|
||||
timer = g_new (GRealTimer, 1);
|
||||
timer->active = TRUE;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
timer->start = GetTickCount ();
|
||||
#else /* !NATIVE_WIN32 */
|
||||
gettimeofday (&timer->start, NULL);
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
|
||||
return ((GTimer*) timer);
|
||||
}
|
||||
|
||||
void
|
||||
g_timer_destroy (GTimer *timer)
|
||||
{
|
||||
g_return_if_fail (timer != NULL);
|
||||
|
||||
g_free (timer);
|
||||
}
|
||||
|
||||
void
|
||||
g_timer_start (GTimer *timer)
|
||||
{
|
||||
GRealTimer *rtimer;
|
||||
|
||||
g_return_if_fail (timer != NULL);
|
||||
|
||||
rtimer = (GRealTimer*) timer;
|
||||
rtimer->active = TRUE;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
rtimer->start = GetTickCount ();
|
||||
#else /* !NATIVE_WIN32 */
|
||||
gettimeofday (&rtimer->start, NULL);
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
}
|
||||
|
||||
void
|
||||
g_timer_stop (GTimer *timer)
|
||||
{
|
||||
GRealTimer *rtimer;
|
||||
|
||||
g_return_if_fail (timer != NULL);
|
||||
|
||||
rtimer = (GRealTimer*) timer;
|
||||
rtimer->active = FALSE;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
rtimer->end = GetTickCount ();
|
||||
#else /* !NATIVE_WIN32 */
|
||||
gettimeofday (&rtimer->end, NULL);
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
}
|
||||
|
||||
void
|
||||
g_timer_reset (GTimer *timer)
|
||||
{
|
||||
GRealTimer *rtimer;
|
||||
|
||||
g_return_if_fail (timer != NULL);
|
||||
|
||||
rtimer = (GRealTimer*) timer;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
rtimer->start = GetTickCount ();
|
||||
#else /* !NATIVE_WIN32 */
|
||||
gettimeofday (&rtimer->start, NULL);
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
}
|
||||
|
||||
gdouble
|
||||
g_timer_elapsed (GTimer *timer,
|
||||
gulong *microseconds)
|
||||
{
|
||||
GRealTimer *rtimer;
|
||||
gdouble total;
|
||||
#ifndef NATIVE_WIN32
|
||||
struct timeval elapsed;
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
g_return_val_if_fail (timer != NULL, 0);
|
||||
|
||||
rtimer = (GRealTimer*) timer;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
if (rtimer->active)
|
||||
rtimer->end = GetTickCount ();
|
||||
|
||||
/* Check for wraparound, which happens every 49.7 days.
|
||||
* No, Win95 machines probably are never running for that long,
|
||||
* but NT machines are.
|
||||
*/
|
||||
if (rtimer->end < rtimer->start)
|
||||
total = (UINT_MAX - (rtimer->start - rtimer->end)) / 1000.0;
|
||||
else
|
||||
total = (rtimer->end - rtimer->start) / 1000.0;
|
||||
|
||||
if (microseconds)
|
||||
{
|
||||
if (rtimer->end < rtimer->start)
|
||||
*microseconds =
|
||||
((UINT_MAX - (rtimer->start - rtimer->end)) % 1000) * 1000;
|
||||
else
|
||||
*microseconds =
|
||||
((rtimer->end - rtimer->start) % 1000) * 1000;
|
||||
}
|
||||
#else /* !NATIVE_WIN32 */
|
||||
if (rtimer->active)
|
||||
gettimeofday (&rtimer->end, NULL);
|
||||
|
||||
if (rtimer->start.tv_usec > rtimer->end.tv_usec)
|
||||
{
|
||||
rtimer->end.tv_usec += 1000000;
|
||||
rtimer->end.tv_sec--;
|
||||
}
|
||||
|
||||
elapsed.tv_usec = rtimer->end.tv_usec - rtimer->start.tv_usec;
|
||||
elapsed.tv_sec = rtimer->end.tv_sec - rtimer->start.tv_sec;
|
||||
|
||||
total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
|
||||
if (total < 0)
|
||||
{
|
||||
total = 0;
|
||||
|
||||
if (microseconds)
|
||||
*microseconds = 0;
|
||||
}
|
||||
else
|
||||
if (microseconds)
|
||||
*microseconds = elapsed.tv_usec;
|
||||
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
|
||||
return total;
|
||||
}
|
744
glib/gtree.c
744
glib/gtree.c
@ -1,744 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
|
||||
typedef struct _GRealTree GRealTree;
|
||||
typedef struct _GTreeNode GTreeNode;
|
||||
|
||||
struct _GRealTree
|
||||
{
|
||||
GTreeNode *root;
|
||||
GCompareFunc key_compare;
|
||||
};
|
||||
|
||||
struct _GTreeNode
|
||||
{
|
||||
gint balance; /* height (left) - height (right) */
|
||||
GTreeNode *left; /* left subtree */
|
||||
GTreeNode *right; /* right subtree */
|
||||
gpointer key; /* key for this node */
|
||||
gpointer value; /* value stored at this node */
|
||||
};
|
||||
|
||||
|
||||
static GTreeNode* g_tree_node_new (gpointer key,
|
||||
gpointer value);
|
||||
static void g_tree_node_destroy (GTreeNode *node);
|
||||
static GTreeNode* g_tree_node_insert (GTreeNode *node,
|
||||
GCompareFunc compare,
|
||||
gpointer key,
|
||||
gpointer value,
|
||||
gint *inserted);
|
||||
static GTreeNode* g_tree_node_remove (GTreeNode *node,
|
||||
GCompareFunc compare,
|
||||
gpointer key);
|
||||
static GTreeNode* g_tree_node_balance (GTreeNode *node);
|
||||
static GTreeNode* g_tree_node_remove_leftmost (GTreeNode *node,
|
||||
GTreeNode **leftmost);
|
||||
static GTreeNode* g_tree_node_restore_left_balance (GTreeNode *node,
|
||||
gint old_balance);
|
||||
static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
|
||||
gint old_balance);
|
||||
static gpointer g_tree_node_lookup (GTreeNode *node,
|
||||
GCompareFunc compare,
|
||||
gpointer key);
|
||||
static gint g_tree_node_count (GTreeNode *node);
|
||||
static gint g_tree_node_pre_order (GTreeNode *node,
|
||||
GTraverseFunc traverse_func,
|
||||
gpointer data);
|
||||
static gint g_tree_node_in_order (GTreeNode *node,
|
||||
GTraverseFunc traverse_func,
|
||||
gpointer data);
|
||||
static gint g_tree_node_post_order (GTreeNode *node,
|
||||
GTraverseFunc traverse_func,
|
||||
gpointer data);
|
||||
static gpointer g_tree_node_search (GTreeNode *node,
|
||||
GSearchFunc search_func,
|
||||
gpointer data);
|
||||
static gint g_tree_node_height (GTreeNode *node);
|
||||
static GTreeNode* g_tree_node_rotate_left (GTreeNode *node);
|
||||
static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
|
||||
static void g_tree_node_check (GTreeNode *node);
|
||||
|
||||
|
||||
G_LOCK_DEFINE_STATIC (g_tree_global);
|
||||
static GMemChunk *node_mem_chunk = NULL;
|
||||
static GTreeNode *node_free_list = NULL;
|
||||
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_new (gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
GTreeNode *node;
|
||||
|
||||
G_LOCK (g_tree_global);
|
||||
if (node_free_list)
|
||||
{
|
||||
node = node_free_list;
|
||||
node_free_list = node->right;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!node_mem_chunk)
|
||||
node_mem_chunk = g_mem_chunk_new ("GLib GTreeNode mem chunk",
|
||||
sizeof (GTreeNode),
|
||||
1024,
|
||||
G_ALLOC_ONLY);
|
||||
|
||||
node = g_chunk_new (GTreeNode, node_mem_chunk);
|
||||
}
|
||||
G_UNLOCK (g_tree_global);
|
||||
|
||||
node->balance = 0;
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
node->key = key;
|
||||
node->value = value;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
g_tree_node_destroy (GTreeNode *node)
|
||||
{
|
||||
if (node)
|
||||
{
|
||||
g_tree_node_destroy (node->right);
|
||||
g_tree_node_destroy (node->left);
|
||||
G_LOCK (g_tree_global);
|
||||
node->right = node_free_list;
|
||||
node_free_list = node;
|
||||
G_UNLOCK (g_tree_global);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GTree*
|
||||
g_tree_new (GCompareFunc key_compare_func)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_val_if_fail (key_compare_func != NULL, NULL);
|
||||
|
||||
rtree = g_new (GRealTree, 1);
|
||||
rtree->root = NULL;
|
||||
rtree->key_compare = key_compare_func;
|
||||
|
||||
return (GTree*) rtree;
|
||||
}
|
||||
|
||||
void
|
||||
g_tree_destroy (GTree *tree)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
g_tree_node_destroy (rtree->root);
|
||||
g_free (rtree);
|
||||
}
|
||||
|
||||
void
|
||||
g_tree_insert (GTree *tree,
|
||||
gpointer key,
|
||||
gpointer value)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
gint inserted;
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
inserted = FALSE;
|
||||
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
|
||||
key, value, &inserted);
|
||||
}
|
||||
|
||||
void
|
||||
g_tree_remove (GTree *tree,
|
||||
gpointer key)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare, key);
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_tree_lookup (GTree *tree,
|
||||
gpointer key)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_val_if_fail (tree != NULL, NULL);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
return g_tree_node_lookup (rtree->root, rtree->key_compare, key);
|
||||
}
|
||||
|
||||
void
|
||||
g_tree_traverse (GTree *tree,
|
||||
GTraverseFunc traverse_func,
|
||||
GTraverseType traverse_type,
|
||||
gpointer data)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
if (!rtree->root)
|
||||
return;
|
||||
|
||||
switch (traverse_type)
|
||||
{
|
||||
case G_PRE_ORDER:
|
||||
g_tree_node_pre_order (rtree->root, traverse_func, data);
|
||||
break;
|
||||
|
||||
case G_IN_ORDER:
|
||||
g_tree_node_in_order (rtree->root, traverse_func, data);
|
||||
break;
|
||||
|
||||
case G_POST_ORDER:
|
||||
g_tree_node_post_order (rtree->root, traverse_func, data);
|
||||
break;
|
||||
|
||||
case G_LEVEL_ORDER:
|
||||
g_warning ("g_tree_traverse(): traverse type G_LEVEL_ORDER isn't implemented.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_tree_search (GTree *tree,
|
||||
GSearchFunc search_func,
|
||||
gpointer data)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_val_if_fail (tree != NULL, NULL);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
if (rtree->root)
|
||||
return g_tree_node_search (rtree->root, search_func, data);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
g_tree_height (GTree *tree)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_val_if_fail (tree != NULL, 0);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
if (rtree->root)
|
||||
return g_tree_node_height (rtree->root);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
gint
|
||||
g_tree_nnodes (GTree *tree)
|
||||
{
|
||||
GRealTree *rtree;
|
||||
|
||||
g_return_val_if_fail (tree != NULL, 0);
|
||||
|
||||
rtree = (GRealTree*) tree;
|
||||
|
||||
if (rtree->root)
|
||||
return g_tree_node_count (rtree->root);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_insert (GTreeNode *node,
|
||||
GCompareFunc compare,
|
||||
gpointer key,
|
||||
gpointer value,
|
||||
gint *inserted)
|
||||
{
|
||||
gint old_balance;
|
||||
gint cmp;
|
||||
|
||||
if (!node)
|
||||
{
|
||||
*inserted = TRUE;
|
||||
return g_tree_node_new (key, value);
|
||||
}
|
||||
|
||||
cmp = (* compare) (key, node->key);
|
||||
if (cmp == 0)
|
||||
{
|
||||
*inserted = FALSE;
|
||||
node->value = value;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (cmp < 0)
|
||||
{
|
||||
if (node->left)
|
||||
{
|
||||
old_balance = node->left->balance;
|
||||
node->left = g_tree_node_insert (node->left, compare, key, value, inserted);
|
||||
|
||||
if ((old_balance != node->left->balance) && node->left->balance)
|
||||
node->balance -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*inserted = TRUE;
|
||||
node->left = g_tree_node_new (key, value);
|
||||
node->balance -= 1;
|
||||
}
|
||||
}
|
||||
else if (cmp > 0)
|
||||
{
|
||||
if (node->right)
|
||||
{
|
||||
old_balance = node->right->balance;
|
||||
node->right = g_tree_node_insert (node->right, compare, key, value, inserted);
|
||||
|
||||
if ((old_balance != node->right->balance) && node->right->balance)
|
||||
node->balance += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*inserted = TRUE;
|
||||
node->right = g_tree_node_new (key, value);
|
||||
node->balance += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*inserted)
|
||||
{
|
||||
if ((node->balance < -1) || (node->balance > 1))
|
||||
node = g_tree_node_balance (node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_remove (GTreeNode *node,
|
||||
GCompareFunc compare,
|
||||
gpointer key)
|
||||
{
|
||||
GTreeNode *new_root;
|
||||
gint old_balance;
|
||||
gint cmp;
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
cmp = (* compare) (key, node->key);
|
||||
if (cmp == 0)
|
||||
{
|
||||
GTreeNode *garbage;
|
||||
|
||||
garbage = node;
|
||||
|
||||
if (!node->right)
|
||||
{
|
||||
node = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_balance = node->right->balance;
|
||||
node->right = g_tree_node_remove_leftmost (node->right, &new_root);
|
||||
new_root->left = node->left;
|
||||
new_root->right = node->right;
|
||||
new_root->balance = node->balance;
|
||||
node = g_tree_node_restore_right_balance (new_root, old_balance);
|
||||
}
|
||||
|
||||
G_LOCK (g_tree_global);
|
||||
garbage->right = node_free_list;
|
||||
node_free_list = garbage;
|
||||
G_UNLOCK (g_tree_global);
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{
|
||||
if (node->left)
|
||||
{
|
||||
old_balance = node->left->balance;
|
||||
node->left = g_tree_node_remove (node->left, compare, key);
|
||||
node = g_tree_node_restore_left_balance (node, old_balance);
|
||||
}
|
||||
}
|
||||
else if (cmp > 0)
|
||||
{
|
||||
if (node->right)
|
||||
{
|
||||
old_balance = node->right->balance;
|
||||
node->right = g_tree_node_remove (node->right, compare, key);
|
||||
node = g_tree_node_restore_right_balance (node, old_balance);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_balance (GTreeNode *node)
|
||||
{
|
||||
if (node->balance < -1)
|
||||
{
|
||||
if (node->left->balance > 0)
|
||||
node->left = g_tree_node_rotate_left (node->left);
|
||||
node = g_tree_node_rotate_right (node);
|
||||
}
|
||||
else if (node->balance > 1)
|
||||
{
|
||||
if (node->right->balance < 0)
|
||||
node->right = g_tree_node_rotate_right (node->right);
|
||||
node = g_tree_node_rotate_left (node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_remove_leftmost (GTreeNode *node,
|
||||
GTreeNode **leftmost)
|
||||
{
|
||||
gint old_balance;
|
||||
|
||||
if (!node->left)
|
||||
{
|
||||
*leftmost = node;
|
||||
return node->right;
|
||||
}
|
||||
|
||||
old_balance = node->left->balance;
|
||||
node->left = g_tree_node_remove_leftmost (node->left, leftmost);
|
||||
return g_tree_node_restore_left_balance (node, old_balance);
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_restore_left_balance (GTreeNode *node,
|
||||
gint old_balance)
|
||||
{
|
||||
if (!node->left)
|
||||
node->balance += 1;
|
||||
else if ((node->left->balance != old_balance) &&
|
||||
(node->left->balance == 0))
|
||||
node->balance += 1;
|
||||
|
||||
if (node->balance > 1)
|
||||
return g_tree_node_balance (node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_restore_right_balance (GTreeNode *node,
|
||||
gint old_balance)
|
||||
{
|
||||
if (!node->right)
|
||||
node->balance -= 1;
|
||||
else if ((node->right->balance != old_balance) &&
|
||||
(node->right->balance == 0))
|
||||
node->balance -= 1;
|
||||
|
||||
if (node->balance < -1)
|
||||
return g_tree_node_balance (node);
|
||||
return node;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
g_tree_node_lookup (GTreeNode *node,
|
||||
GCompareFunc compare,
|
||||
gpointer key)
|
||||
{
|
||||
gint cmp;
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
cmp = (* compare) (key, node->key);
|
||||
if (cmp == 0)
|
||||
return node->value;
|
||||
|
||||
if (cmp < 0)
|
||||
{
|
||||
if (node->left)
|
||||
return g_tree_node_lookup (node->left, compare, key);
|
||||
}
|
||||
else if (cmp > 0)
|
||||
{
|
||||
if (node->right)
|
||||
return g_tree_node_lookup (node->right, compare, key);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gint
|
||||
g_tree_node_count (GTreeNode *node)
|
||||
{
|
||||
gint count;
|
||||
|
||||
count = 1;
|
||||
if (node->left)
|
||||
count += g_tree_node_count (node->left);
|
||||
if (node->right)
|
||||
count += g_tree_node_count (node->right);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static gint
|
||||
g_tree_node_pre_order (GTreeNode *node,
|
||||
GTraverseFunc traverse_func,
|
||||
gpointer data)
|
||||
{
|
||||
if ((*traverse_func) (node->key, node->value, data))
|
||||
return TRUE;
|
||||
if (node->left)
|
||||
{
|
||||
if (g_tree_node_pre_order (node->left, traverse_func, data))
|
||||
return TRUE;
|
||||
}
|
||||
if (node->right)
|
||||
{
|
||||
if (g_tree_node_pre_order (node->right, traverse_func, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
g_tree_node_in_order (GTreeNode *node,
|
||||
GTraverseFunc traverse_func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->left)
|
||||
{
|
||||
if (g_tree_node_in_order (node->left, traverse_func, data))
|
||||
return TRUE;
|
||||
}
|
||||
if ((*traverse_func) (node->key, node->value, data))
|
||||
return TRUE;
|
||||
if (node->right)
|
||||
{
|
||||
if (g_tree_node_in_order (node->right, traverse_func, data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
g_tree_node_post_order (GTreeNode *node,
|
||||
GTraverseFunc traverse_func,
|
||||
gpointer data)
|
||||
{
|
||||
if (node->left)
|
||||
{
|
||||
if (g_tree_node_post_order (node->left, traverse_func, data))
|
||||
return TRUE;
|
||||
}
|
||||
if (node->right)
|
||||
{
|
||||
if (g_tree_node_post_order (node->right, traverse_func, data))
|
||||
return TRUE;
|
||||
}
|
||||
if ((*traverse_func) (node->key, node->value, data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
g_tree_node_search (GTreeNode *node,
|
||||
GSearchFunc search_func,
|
||||
gpointer data)
|
||||
{
|
||||
gint dir;
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
dir = (* search_func) (node->key, data);
|
||||
if (dir == 0)
|
||||
return node->value;
|
||||
|
||||
if (dir < 0)
|
||||
node = node->left;
|
||||
else if (dir > 0)
|
||||
node = node->right;
|
||||
} while (node && (dir != 0));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gint
|
||||
g_tree_node_height (GTreeNode *node)
|
||||
{
|
||||
gint left_height;
|
||||
gint right_height;
|
||||
|
||||
if (node)
|
||||
{
|
||||
left_height = 0;
|
||||
right_height = 0;
|
||||
|
||||
if (node->left)
|
||||
left_height = g_tree_node_height (node->left);
|
||||
|
||||
if (node->right)
|
||||
right_height = g_tree_node_height (node->right);
|
||||
|
||||
return MAX (left_height, right_height) + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_rotate_left (GTreeNode *node)
|
||||
{
|
||||
GTreeNode *left;
|
||||
GTreeNode *right;
|
||||
gint a_bal;
|
||||
gint b_bal;
|
||||
|
||||
left = node->left;
|
||||
right = node->right;
|
||||
|
||||
node->right = right->left;
|
||||
right->left = node;
|
||||
|
||||
a_bal = node->balance;
|
||||
b_bal = right->balance;
|
||||
|
||||
if (b_bal <= 0)
|
||||
{
|
||||
if (a_bal >= 1)
|
||||
right->balance = b_bal - 1;
|
||||
else
|
||||
right->balance = a_bal + b_bal - 2;
|
||||
node->balance = a_bal - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a_bal <= b_bal)
|
||||
right->balance = a_bal - 2;
|
||||
else
|
||||
right->balance = b_bal - 1;
|
||||
node->balance = a_bal - b_bal - 1;
|
||||
}
|
||||
|
||||
return right;
|
||||
}
|
||||
|
||||
static GTreeNode*
|
||||
g_tree_node_rotate_right (GTreeNode *node)
|
||||
{
|
||||
GTreeNode *left;
|
||||
gint a_bal;
|
||||
gint b_bal;
|
||||
|
||||
left = node->left;
|
||||
|
||||
node->left = left->right;
|
||||
left->right = node;
|
||||
|
||||
a_bal = node->balance;
|
||||
b_bal = left->balance;
|
||||
|
||||
if (b_bal <= 0)
|
||||
{
|
||||
if (b_bal > a_bal)
|
||||
left->balance = b_bal + 1;
|
||||
else
|
||||
left->balance = a_bal + 2;
|
||||
node->balance = a_bal - b_bal + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a_bal <= -1)
|
||||
left->balance = b_bal + 1;
|
||||
else
|
||||
left->balance = a_bal + b_bal + 2;
|
||||
node->balance = a_bal + 1;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static void
|
||||
g_tree_node_check (GTreeNode *node)
|
||||
{
|
||||
gint left_height;
|
||||
gint right_height;
|
||||
gint balance;
|
||||
|
||||
if (node)
|
||||
{
|
||||
left_height = 0;
|
||||
right_height = 0;
|
||||
|
||||
if (node->left)
|
||||
left_height = g_tree_node_height (node->left);
|
||||
if (node->right)
|
||||
right_height = g_tree_node_height (node->right);
|
||||
|
||||
balance = right_height - left_height;
|
||||
if (balance != node->balance)
|
||||
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
|
||||
"g_tree_node_check: failed: %d ( %d )\n",
|
||||
balance, node->balance);
|
||||
|
||||
if (node->left)
|
||||
g_tree_node_check (node->left);
|
||||
if (node->right)
|
||||
g_tree_node_check (node->right);
|
||||
}
|
||||
}
|
927
glib/gutils.c
927
glib/gutils.c
@ -1,927 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe for the unix part, FIXME: make the win32 part MT safe as well.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "glibconfig.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
# define STRICT /* Strict typing, please */
|
||||
# include <windows.h>
|
||||
# include <direct.h>
|
||||
# include <errno.h>
|
||||
# include <ctype.h>
|
||||
# ifdef _MSC_VER
|
||||
# include <io.h>
|
||||
# endif /* _MSC_VER */
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
/* implement Glib's inline functions
|
||||
*/
|
||||
#define G_INLINE_FUNC extern
|
||||
#define G_CAN_INLINE 1
|
||||
#include "glib.h"
|
||||
|
||||
#ifdef MAXPATHLEN
|
||||
#define G_PATH_LENGTH (MAXPATHLEN + 1)
|
||||
#elif defined (PATH_MAX)
|
||||
#define G_PATH_LENGTH (PATH_MAX + 1)
|
||||
#else /* !MAXPATHLEN */
|
||||
#define G_PATH_LENGTH (2048 + 1)
|
||||
#endif /* !MAXPATHLEN && !PATH_MAX */
|
||||
|
||||
const guint glib_major_version = GLIB_MAJOR_VERSION;
|
||||
const guint glib_minor_version = GLIB_MINOR_VERSION;
|
||||
const guint glib_micro_version = GLIB_MICRO_VERSION;
|
||||
const guint glib_interface_age = GLIB_INTERFACE_AGE;
|
||||
const guint glib_binary_age = GLIB_BINARY_AGE;
|
||||
|
||||
#if defined (NATIVE_WIN32) && defined (__LCC__)
|
||||
int __stdcall
|
||||
LibMain (void *hinstDll,
|
||||
unsigned long dwReason,
|
||||
void *reserved)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif /* NATIVE_WIN32 && __LCC__ */
|
||||
|
||||
void
|
||||
g_atexit (GVoidFunc func)
|
||||
{
|
||||
gint result;
|
||||
gchar *error = NULL;
|
||||
|
||||
/* keep this in sync with glib.h */
|
||||
|
||||
#ifdef G_NATIVE_ATEXIT
|
||||
result = ATEXIT (func);
|
||||
if (result)
|
||||
error = g_strerror (errno);
|
||||
#elif defined (HAVE_ATEXIT)
|
||||
# ifdef NeXT /* @#%@! NeXTStep */
|
||||
result = !atexit ((void (*)(void)) func);
|
||||
if (result)
|
||||
error = g_strerror (errno);
|
||||
# else
|
||||
result = atexit ((void (*)(void)) func);
|
||||
if (result)
|
||||
error = g_strerror (errno);
|
||||
# endif /* NeXT */
|
||||
#elif defined (HAVE_ON_EXIT)
|
||||
result = on_exit ((void (*)(int, void *)) func, NULL);
|
||||
if (result)
|
||||
error = g_strerror (errno);
|
||||
#else
|
||||
result = 0;
|
||||
error = "no implementation";
|
||||
#endif /* G_NATIVE_ATEXIT */
|
||||
|
||||
if (error)
|
||||
g_error ("Could not register atexit() function: %s", error);
|
||||
}
|
||||
|
||||
gint
|
||||
g_snprintf (gchar *str,
|
||||
gulong n,
|
||||
gchar const *fmt,
|
||||
...)
|
||||
{
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
va_list args;
|
||||
gint retval;
|
||||
|
||||
g_return_val_if_fail (str != NULL, 0);
|
||||
g_return_val_if_fail (n > 0, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
va_start (args, fmt);
|
||||
retval = vsnprintf (str, n, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
str[n-1] = '\0';
|
||||
retval = strlen (str);
|
||||
}
|
||||
|
||||
return retval;
|
||||
#else /* !HAVE_VSNPRINTF */
|
||||
gchar *printed;
|
||||
va_list args;
|
||||
|
||||
g_return_val_if_fail (str != NULL, 0);
|
||||
g_return_val_if_fail (n > 0, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
va_start (args, fmt);
|
||||
printed = g_strdup_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
|
||||
strncpy (str, printed, n);
|
||||
str[n-1] = '\0';
|
||||
|
||||
g_free (printed);
|
||||
|
||||
return strlen (str);
|
||||
#endif /* !HAVE_VSNPRINTF */
|
||||
}
|
||||
|
||||
gint
|
||||
g_vsnprintf (gchar *str,
|
||||
gulong n,
|
||||
gchar const *fmt,
|
||||
va_list args)
|
||||
{
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
gint retval;
|
||||
|
||||
g_return_val_if_fail (str != NULL, 0);
|
||||
g_return_val_if_fail (n > 0, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
retval = vsnprintf (str, n, fmt, args);
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
str[n-1] = '\0';
|
||||
retval = strlen (str);
|
||||
}
|
||||
|
||||
return retval;
|
||||
#else /* !HAVE_VSNPRINTF */
|
||||
gchar *printed;
|
||||
|
||||
g_return_val_if_fail (str != NULL, 0);
|
||||
g_return_val_if_fail (n > 0, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
printed = g_strdup_vprintf (fmt, args);
|
||||
strncpy (str, printed, n);
|
||||
str[n-1] = '\0';
|
||||
|
||||
g_free (printed);
|
||||
|
||||
return strlen (str);
|
||||
#endif /* !HAVE_VSNPRINTF */
|
||||
}
|
||||
|
||||
guint
|
||||
g_parse_debug_string (const gchar *string,
|
||||
GDebugKey *keys,
|
||||
guint nkeys)
|
||||
{
|
||||
guint i;
|
||||
guint result = 0;
|
||||
|
||||
g_return_val_if_fail (string != NULL, 0);
|
||||
|
||||
if (!g_strcasecmp (string, "all"))
|
||||
{
|
||||
for (i=0; i<nkeys; i++)
|
||||
result |= keys[i].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *str = g_strdup (string);
|
||||
gchar *p = str;
|
||||
gchar *q;
|
||||
gboolean done = FALSE;
|
||||
|
||||
while (*p && !done)
|
||||
{
|
||||
q = strchr (p, ':');
|
||||
if (!q)
|
||||
{
|
||||
q = p + strlen(p);
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
*q = 0;
|
||||
|
||||
for (i=0; i<nkeys; i++)
|
||||
if (!g_strcasecmp(keys[i].key, p))
|
||||
result |= keys[i].value;
|
||||
|
||||
p = q+1;
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_basename (const gchar *file_name)
|
||||
{
|
||||
register gchar *base;
|
||||
|
||||
g_return_val_if_fail (file_name != NULL, NULL);
|
||||
|
||||
base = strrchr (file_name, G_DIR_SEPARATOR);
|
||||
if (base)
|
||||
return base + 1;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
if (isalpha (file_name[0]) && file_name[1] == ':')
|
||||
return (gchar*) file_name + 2;
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
return (gchar*) file_name;
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_path_is_absolute (const gchar *file_name)
|
||||
{
|
||||
g_return_val_if_fail (file_name != NULL, FALSE);
|
||||
|
||||
if (file_name[0] == G_DIR_SEPARATOR)
|
||||
return TRUE;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_path_skip_root (gchar *file_name)
|
||||
{
|
||||
g_return_val_if_fail (file_name != NULL, NULL);
|
||||
|
||||
if (file_name[0] == G_DIR_SEPARATOR)
|
||||
return file_name + 1;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
|
||||
return file_name + 3;
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_dirname (const gchar *file_name)
|
||||
{
|
||||
register gchar *base;
|
||||
register guint len;
|
||||
|
||||
g_return_val_if_fail (file_name != NULL, NULL);
|
||||
|
||||
base = strrchr (file_name, G_DIR_SEPARATOR);
|
||||
if (!base)
|
||||
return g_strdup (".");
|
||||
while (base > file_name && *base == G_DIR_SEPARATOR)
|
||||
base--;
|
||||
len = (guint) 1 + base - file_name;
|
||||
|
||||
base = g_new (gchar, len + 1);
|
||||
g_memmove (base, file_name, len);
|
||||
base[len] = 0;
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_get_current_dir (void)
|
||||
{
|
||||
gchar *buffer;
|
||||
gchar *dir;
|
||||
|
||||
buffer = g_new (gchar, G_PATH_LENGTH);
|
||||
*buffer = 0;
|
||||
|
||||
/* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
|
||||
* and, if that wasn't bad enough, hangs in doing so.
|
||||
*/
|
||||
#if defined (sun) && !defined (__SVR4)
|
||||
dir = getwd (buffer);
|
||||
#else /* !sun */
|
||||
dir = getcwd (buffer, G_PATH_LENGTH - 1);
|
||||
#endif /* !sun */
|
||||
|
||||
if (!dir || !*buffer)
|
||||
{
|
||||
/* hm, should we g_error() out here?
|
||||
* this can happen if e.g. "./" has mode \0000
|
||||
*/
|
||||
buffer[0] = G_DIR_SEPARATOR;
|
||||
buffer[1] = 0;
|
||||
}
|
||||
|
||||
dir = g_strdup (buffer);
|
||||
g_free (buffer);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_getenv (const gchar *variable)
|
||||
{
|
||||
#ifndef NATIVE_WIN32
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
|
||||
return getenv (variable);
|
||||
#else
|
||||
gchar *v;
|
||||
guint k;
|
||||
static gchar *p = NULL;
|
||||
static gint l;
|
||||
gchar dummy[2];
|
||||
|
||||
g_return_val_if_fail (variable != NULL, NULL);
|
||||
|
||||
v = getenv (variable);
|
||||
if (!v)
|
||||
return NULL;
|
||||
|
||||
/* On Windows NT, it is relatively typical that environment variables
|
||||
* contain references to other environment variables. Handle that by
|
||||
* calling ExpandEnvironmentStrings.
|
||||
*/
|
||||
|
||||
/* First check how much space we need */
|
||||
k = ExpandEnvironmentStrings (v, dummy, 2);
|
||||
/* Then allocate that much, and actualy do the expansion */
|
||||
if (p == NULL)
|
||||
{
|
||||
p = g_malloc (k);
|
||||
l = k;
|
||||
}
|
||||
else if (k > l)
|
||||
{
|
||||
p = g_realloc (p, k);
|
||||
l = k;
|
||||
}
|
||||
ExpandEnvironmentStrings (v, p, k);
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
G_LOCK_DEFINE_STATIC (g_utils_global);
|
||||
|
||||
static gchar *g_tmp_dir = NULL;
|
||||
static gchar *g_user_name = NULL;
|
||||
static gchar *g_real_name = NULL;
|
||||
static gchar *g_home_dir = NULL;
|
||||
|
||||
/* HOLDS: g_utils_global_lock */
|
||||
static void
|
||||
g_get_any_init (void)
|
||||
{
|
||||
if (!g_tmp_dir)
|
||||
{
|
||||
g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
|
||||
if (!g_tmp_dir)
|
||||
g_tmp_dir = g_strdup (g_getenv ("TMP"));
|
||||
if (!g_tmp_dir)
|
||||
g_tmp_dir = g_strdup (g_getenv ("TEMP"));
|
||||
|
||||
#ifdef P_tmpdir
|
||||
if (!g_tmp_dir)
|
||||
{
|
||||
int k;
|
||||
g_tmp_dir = g_strdup (P_tmpdir);
|
||||
k = strlen (g_tmp_dir);
|
||||
if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
|
||||
g_tmp_dir[k-1] = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!g_tmp_dir)
|
||||
{
|
||||
#ifndef NATIVE_WIN32
|
||||
g_tmp_dir = g_strdup ("/tmp");
|
||||
#else /* NATIVE_WIN32 */
|
||||
g_tmp_dir = g_strdup ("C:\\");
|
||||
#endif /* NATIVE_WIN32 */
|
||||
}
|
||||
|
||||
if (!g_home_dir)
|
||||
g_home_dir = g_strdup (g_getenv ("HOME"));
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
if (!g_home_dir)
|
||||
{
|
||||
/* The official way to specify a home directory on NT is
|
||||
* the HOMEDRIVE and HOMEPATH environment variables.
|
||||
*
|
||||
* This is inside #ifdef NATIVE_WIN32 because with the cygwin dll,
|
||||
* HOME should be a POSIX style pathname.
|
||||
*/
|
||||
|
||||
if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
|
||||
{
|
||||
gchar *homedrive, *homepath;
|
||||
|
||||
homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
|
||||
homepath = g_strdup (g_getenv ("HOMEPATH"));
|
||||
|
||||
g_home_dir = g_strconcat (homedrive, homepath, NULL);
|
||||
g_free (homedrive);
|
||||
g_free (homepath);
|
||||
}
|
||||
}
|
||||
#endif /* !NATIVE_WIN32 */
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
{
|
||||
struct passwd *pw = NULL;
|
||||
gpointer buffer = NULL;
|
||||
|
||||
# ifdef HAVE_GETPWUID_R
|
||||
struct passwd pwd;
|
||||
# ifdef _SC_GETPW_R_SIZE_MAX
|
||||
/* This reurns the maximum length */
|
||||
guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
|
||||
# else /* _SC_GETPW_R_SIZE_MAX */
|
||||
guint bufsize = 64;
|
||||
# endif /* _SC_GETPW_R_SIZE_MAX */
|
||||
gint error;
|
||||
|
||||
do
|
||||
{
|
||||
g_free (buffer);
|
||||
buffer = g_malloc (bufsize);
|
||||
errno = 0;
|
||||
|
||||
# ifdef HAVE_GETPWUID_R_POSIX
|
||||
error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
|
||||
error = error < 0 ? errno : error;
|
||||
# else /* !HAVE_GETPWUID_R_POSIX */
|
||||
# ifdef _AIX
|
||||
error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
|
||||
pw = error == 0 ? &pwd : NULL;
|
||||
# else /* !_AIX */
|
||||
pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
|
||||
error = pw ? 0 : errno;
|
||||
# endif /* !_AIX */
|
||||
# endif /* !HAVE_GETPWUID_R_POSIX */
|
||||
|
||||
if (!pw)
|
||||
{
|
||||
/* we bail out prematurely if the user id can't be found
|
||||
* (should be pretty rare case actually), or if the buffer
|
||||
* should be sufficiently big and lookups are still not
|
||||
* successfull.
|
||||
*/
|
||||
if (error == 0 || error == ENOENT)
|
||||
{
|
||||
g_warning ("getpwuid_r(): failed due to: No such user %d.",
|
||||
getuid ());
|
||||
break;
|
||||
}
|
||||
if (bufsize > 32 * 1024)
|
||||
{
|
||||
g_warning ("getpwuid_r(): failed due to: %s.",
|
||||
g_strerror (error));
|
||||
break;
|
||||
}
|
||||
|
||||
bufsize *= 2;
|
||||
}
|
||||
}
|
||||
while (!pw);
|
||||
# endif /* !HAVE_GETPWUID_R */
|
||||
|
||||
if (!pw)
|
||||
{
|
||||
setpwent ();
|
||||
pw = getpwuid (getuid ());
|
||||
endpwent ();
|
||||
}
|
||||
if (pw)
|
||||
{
|
||||
g_user_name = g_strdup (pw->pw_name);
|
||||
g_real_name = g_strdup (pw->pw_gecos);
|
||||
if (!g_home_dir)
|
||||
g_home_dir = g_strdup (pw->pw_dir);
|
||||
}
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
#else /* !HAVE_PWD_H */
|
||||
|
||||
# ifdef NATIVE_WIN32
|
||||
{
|
||||
guint len = 17;
|
||||
gchar buffer[17];
|
||||
|
||||
if (GetUserName (buffer, &len))
|
||||
{
|
||||
g_user_name = g_strdup (buffer);
|
||||
g_real_name = g_strdup (buffer);
|
||||
}
|
||||
}
|
||||
# endif /* NATIVE_WIN32 */
|
||||
|
||||
#endif /* !HAVE_PWD_H */
|
||||
|
||||
if (!g_user_name)
|
||||
g_user_name = g_strdup ("somebody");
|
||||
if (!g_real_name)
|
||||
g_real_name = g_strdup ("Unknown");
|
||||
else
|
||||
{
|
||||
gchar *p;
|
||||
|
||||
for (p = g_real_name; *p; p++)
|
||||
if (*p == ',')
|
||||
{
|
||||
*p = 0;
|
||||
p = g_strdup (g_real_name);
|
||||
g_free (g_real_name);
|
||||
g_real_name = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_get_user_name (void)
|
||||
{
|
||||
G_LOCK (g_utils_global);
|
||||
if (!g_tmp_dir)
|
||||
g_get_any_init ();
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return g_user_name;
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_get_real_name (void)
|
||||
{
|
||||
G_LOCK (g_utils_global);
|
||||
if (!g_tmp_dir)
|
||||
g_get_any_init ();
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return g_real_name;
|
||||
}
|
||||
|
||||
/* Return the home directory of the user. If there is a HOME
|
||||
* environment variable, its value is returned, otherwise use some
|
||||
* system-dependent way of finding it out. If no home directory can be
|
||||
* deduced, return NULL.
|
||||
*/
|
||||
|
||||
gchar*
|
||||
g_get_home_dir (void)
|
||||
{
|
||||
G_LOCK (g_utils_global);
|
||||
if (!g_tmp_dir)
|
||||
g_get_any_init ();
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return g_home_dir;
|
||||
}
|
||||
|
||||
/* Return a directory to be used to store temporary files. This is the
|
||||
* value of the TMPDIR, TMP or TEMP environment variables (they are
|
||||
* checked in that order). If none of those exist, use P_tmpdir from
|
||||
* stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
|
||||
* and C:\ on Windows.
|
||||
*/
|
||||
|
||||
gchar*
|
||||
g_get_tmp_dir (void)
|
||||
{
|
||||
G_LOCK (g_utils_global);
|
||||
if (!g_tmp_dir)
|
||||
g_get_any_init ();
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return g_tmp_dir;
|
||||
}
|
||||
|
||||
static gchar *g_prgname = NULL;
|
||||
|
||||
gchar*
|
||||
g_get_prgname (void)
|
||||
{
|
||||
gchar* retval;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
retval = g_prgname;
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
g_set_prgname (const gchar *prgname)
|
||||
{
|
||||
gchar *c;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
c = g_prgname;
|
||||
g_prgname = g_strdup (prgname);
|
||||
g_free (c);
|
||||
G_UNLOCK (g_utils_global);
|
||||
}
|
||||
|
||||
guint
|
||||
g_direct_hash (gconstpointer v)
|
||||
{
|
||||
return GPOINTER_TO_UINT (v);
|
||||
}
|
||||
|
||||
gint
|
||||
g_direct_equal (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
return v1 == v2;
|
||||
}
|
||||
|
||||
gint
|
||||
g_int_equal (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
return *((const gint*) v1) == *((const gint*) v2);
|
||||
}
|
||||
|
||||
guint
|
||||
g_int_hash (gconstpointer v)
|
||||
{
|
||||
return *(const gint*) v;
|
||||
}
|
||||
|
||||
#if 0 /* Old IO Channels */
|
||||
|
||||
GIOChannel*
|
||||
g_iochannel_new (gint fd)
|
||||
{
|
||||
GIOChannel *channel = g_new (GIOChannel, 1);
|
||||
|
||||
channel->fd = fd;
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
channel->peer = 0;
|
||||
channel->peer_fd = 0;
|
||||
channel->offset = 0;
|
||||
channel->need_wakeups = 0;
|
||||
#endif /* NATIVE_WIN32 */
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
void
|
||||
g_iochannel_free (GIOChannel *channel)
|
||||
{
|
||||
g_return_if_fail (channel != NULL);
|
||||
|
||||
g_free (channel);
|
||||
}
|
||||
|
||||
void
|
||||
g_iochannel_close_and_free (GIOChannel *channel)
|
||||
{
|
||||
g_return_if_fail (channel != NULL);
|
||||
|
||||
close (channel->fd);
|
||||
|
||||
g_iochannel_free (channel);
|
||||
}
|
||||
|
||||
#undef g_iochannel_wakeup_peer
|
||||
|
||||
void
|
||||
g_iochannel_wakeup_peer (GIOChannel *channel)
|
||||
{
|
||||
#ifdef NATIVE_WIN32
|
||||
static guint message = 0;
|
||||
#endif
|
||||
|
||||
g_return_if_fail (channel != NULL);
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
if (message == 0)
|
||||
message = RegisterWindowMessage ("gdk-pipe-readable");
|
||||
|
||||
# if 0
|
||||
g_print ("g_iochannel_wakeup_peer: calling PostThreadMessage (%#x, %d, %d, %d)\n",
|
||||
channel->peer, message, channel->peer_fd, channel->offset);
|
||||
# endif
|
||||
PostThreadMessage (channel->peer, message,
|
||||
channel->peer_fd, channel->offset);
|
||||
#endif /* NATIVE_WIN32 */
|
||||
}
|
||||
|
||||
#endif /* Old IO Channels */
|
||||
|
||||
#ifdef NATIVE_WIN32
|
||||
#ifdef _MSC_VER
|
||||
|
||||
int
|
||||
gwin_ftruncate (gint fd,
|
||||
guint size)
|
||||
{
|
||||
HANDLE hfile;
|
||||
guint curpos;
|
||||
|
||||
g_return_val_if_fail (fd >= 0, -1);
|
||||
|
||||
hfile = (HANDLE) _get_osfhandle (fd);
|
||||
curpos = SetFilePointer (hfile, 0, NULL, FILE_CURRENT);
|
||||
if (curpos == 0xFFFFFFFF
|
||||
|| SetFilePointer (hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
|
||||
|| !SetEndOfFile (hfile))
|
||||
{
|
||||
gint error = GetLastError ();
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_INVALID_HANDLE:
|
||||
errno = EBADF;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR*
|
||||
gwin_opendir (const char *dirname)
|
||||
{
|
||||
DIR *result;
|
||||
gchar *mask;
|
||||
guint k;
|
||||
|
||||
g_return_val_if_fail (dirname != NULL, NULL);
|
||||
|
||||
result = g_new0 (DIR, 1);
|
||||
result->find_file_data = g_new0 (WIN32_FIND_DATA, 1);
|
||||
result->dir_name = g_strdup (dirname);
|
||||
|
||||
k = strlen (result->dir_name);
|
||||
if (k && result->dir_name[k - 1] == '\\')
|
||||
{
|
||||
result->dir_name[k - 1] = '\0';
|
||||
k--;
|
||||
}
|
||||
mask = g_strdup_printf ("%s\\*", result->dir_name);
|
||||
|
||||
result->find_file_handle = (guint) FindFirstFile (mask,
|
||||
(LPWIN32_FIND_DATA) result->find_file_data);
|
||||
g_free (mask);
|
||||
|
||||
if (result->find_file_handle == (guint) INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int error = GetLastError ();
|
||||
|
||||
g_free (result->dir_name);
|
||||
g_free (result->find_file_data);
|
||||
g_free (result);
|
||||
switch (error)
|
||||
{
|
||||
default:
|
||||
errno = EIO;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
result->just_opened = TRUE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dirent*
|
||||
gwin_readdir (DIR *dir)
|
||||
{
|
||||
static struct dirent result;
|
||||
|
||||
g_return_val_if_fail (dir != NULL, NULL);
|
||||
|
||||
if (dir->just_opened)
|
||||
dir->just_opened = FALSE;
|
||||
else
|
||||
{
|
||||
if (!FindNextFile ((HANDLE) dir->find_file_handle,
|
||||
(LPWIN32_FIND_DATA) dir->find_file_data))
|
||||
{
|
||||
int error = GetLastError ();
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case ERROR_NO_MORE_FILES:
|
||||
return NULL;
|
||||
default:
|
||||
errno = EIO;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
strcpy (result.d_name, g_basename (((LPWIN32_FIND_DATA) dir->find_file_data)->cFileName));
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
void
|
||||
gwin_rewinddir (DIR *dir)
|
||||
{
|
||||
gchar *mask;
|
||||
|
||||
g_return_if_fail (dir != NULL);
|
||||
|
||||
if (!FindClose ((HANDLE) dir->find_file_handle))
|
||||
g_warning ("gwin_rewinddir(): FindClose() failed\n");
|
||||
|
||||
mask = g_strdup_printf ("%s\\*", dir->dir_name);
|
||||
dir->find_file_handle = (guint) FindFirstFile (mask,
|
||||
(LPWIN32_FIND_DATA) dir->find_file_data);
|
||||
g_free (mask);
|
||||
|
||||
if (dir->find_file_handle == (guint) INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int error = GetLastError ();
|
||||
|
||||
switch (error)
|
||||
{
|
||||
default:
|
||||
errno = EIO;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dir->just_opened = TRUE;
|
||||
}
|
||||
|
||||
gint
|
||||
gwin_closedir (DIR *dir)
|
||||
{
|
||||
g_return_val_if_fail (dir != NULL, -1);
|
||||
|
||||
if (!FindClose ((HANDLE) dir->find_file_handle))
|
||||
{
|
||||
int error = GetLastError ();
|
||||
|
||||
switch (error)
|
||||
{
|
||||
default:
|
||||
errno = EIO; return -1;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (dir->dir_name);
|
||||
g_free (dir->find_file_data);
|
||||
g_free (dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#endif /* NATIVE_WIN32 */
|
@ -1,486 +0,0 @@
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
|
||||
gboolean failed = FALSE;
|
||||
guint32 passed = 0;
|
||||
guint32 notpassed = 0;
|
||||
|
||||
#define TEST(m,cond) G_STMT_START { failed = !(cond); \
|
||||
if (failed) \
|
||||
{ ++notpassed; \
|
||||
if (!m) \
|
||||
g_print ("\n(%s:%d) failed for: %s\n", __FILE__, __LINE__, ( # cond )); \
|
||||
else \
|
||||
g_print ("\n(%s:%d) failed for: %s: (%s)\n", __FILE__, __LINE__, ( # cond ), (gchar*)m); \
|
||||
} \
|
||||
else \
|
||||
++passed; \
|
||||
if ((passed+notpassed) % 10000 == 0) g_print ("."); fflush (stdout); \
|
||||
} G_STMT_END
|
||||
|
||||
void g_date_debug_print(GDate* d)
|
||||
{
|
||||
if (!d) g_print("NULL!\n");
|
||||
else
|
||||
g_print("julian: %u (%s) DMY: %u %u %u (%s)\n",
|
||||
d->julian_days,
|
||||
d->julian ? "valid" : "invalid",
|
||||
d->day,
|
||||
d->month,
|
||||
d->year,
|
||||
d->dmy ? "valid" : "invalid");
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
GDate* d;
|
||||
guint32 j;
|
||||
GDateMonth m;
|
||||
GDateYear y, prev_y;
|
||||
GDateDay day;
|
||||
gchar buf[101];
|
||||
gchar* loc;
|
||||
/* Try to get all the leap year cases. */
|
||||
GDateYear check_years[] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 98, 99, 100, 101, 102, 103, 397,
|
||||
398, 399, 400, 401, 402, 403, 404, 405, 406,
|
||||
1598, 1599, 1600, 1601, 1602, 1650, 1651,
|
||||
1897, 1898, 1899, 1900, 1901, 1902, 1903,
|
||||
1961, 1962, 1963, 1964, 1965, 1967,
|
||||
1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976,
|
||||
1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985,
|
||||
1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
|
||||
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
||||
3000, 3001, 3002, 3998, 3999, 4000, 4001, 4002, 4003
|
||||
};
|
||||
guint n_check_years = sizeof(check_years)/sizeof(GDateYear);
|
||||
guint i;
|
||||
gboolean discontinuity;
|
||||
|
||||
g_print("checking GDate...");
|
||||
|
||||
TEST("sizeof(GDate) is not more than 8 bytes on this platform", sizeof(GDate) < 9);
|
||||
|
||||
d = g_date_new();
|
||||
|
||||
TEST("Empty constructor produces invalid date", !g_date_valid(d));
|
||||
|
||||
g_date_free(d);
|
||||
|
||||
d = g_date_new_dmy(1,1,1);
|
||||
|
||||
TEST("January 1, Year 1 created and valid", g_date_valid(d));
|
||||
|
||||
j = g_date_julian(d);
|
||||
|
||||
TEST("January 1, Year 1 is Julian date 1", j == 1);
|
||||
|
||||
TEST("Returned month is January", g_date_month(d) == G_DATE_JANUARY);
|
||||
TEST("Returned day is 1", g_date_day(d) == 1);
|
||||
TEST("Returned year is 1", g_date_year(d) == 1);
|
||||
|
||||
TEST("Bad month is invalid", !g_date_valid_month(G_DATE_BAD_MONTH));
|
||||
TEST("Month 13 is invalid", !g_date_valid_month(13));
|
||||
TEST("Bad day is invalid", !g_date_valid_day(G_DATE_BAD_DAY));
|
||||
TEST("Day 32 is invalid", !g_date_valid_day(32));
|
||||
TEST("Bad year is invalid", !g_date_valid_year(G_DATE_BAD_YEAR));
|
||||
TEST("Bad julian is invalid", !g_date_valid_julian(G_DATE_BAD_JULIAN));
|
||||
TEST("Bad weekday is invalid", !g_date_valid_weekday(G_DATE_BAD_WEEKDAY));
|
||||
TEST("Year 2000 is a leap year", g_date_is_leap_year(2000));
|
||||
TEST("Year 1999 is not a leap year", !g_date_is_leap_year(1999));
|
||||
TEST("Year 1996 is a leap year", g_date_is_leap_year(1996));
|
||||
TEST("Year 1600 is a leap year", g_date_is_leap_year(1600));
|
||||
TEST("Year 2100 is not a leap year", !g_date_is_leap_year(2100));
|
||||
TEST("Year 1800 is not a leap year", !g_date_is_leap_year(1800));
|
||||
|
||||
g_date_free(d);
|
||||
|
||||
loc = setlocale(LC_ALL,"");
|
||||
if (loc)
|
||||
g_print("\nLocale set to %s\n", loc);
|
||||
else
|
||||
g_print("\nLocale unchanged\n");
|
||||
|
||||
d = g_date_new();
|
||||
g_date_set_time(d, time(NULL));
|
||||
TEST("Today is valid", g_date_valid(d));
|
||||
|
||||
g_date_strftime(buf,100,"Today is a %A, %x\n", d);
|
||||
g_print("%s", buf);
|
||||
|
||||
g_date_set_time(d, 1);
|
||||
TEST("Beginning of Unix epoch is valid", g_date_valid(d));
|
||||
|
||||
g_date_strftime(buf,100,"1 second into the Unix epoch it was a %A, in the month of %B, %x\n", d);
|
||||
g_print("%s", buf);
|
||||
|
||||
g_date_set_julian(d, 1);
|
||||
TEST("GDate's \"Julian\" epoch's first day is valid", g_date_valid(d));
|
||||
|
||||
g_date_strftime(buf,100,"Our \"Julian\" epoch begins on a %A, in the month of %B, %x\n",
|
||||
d);
|
||||
g_print("%s", buf);
|
||||
|
||||
g_date_set_dmy(d, 10, 1, 2000);
|
||||
|
||||
g_date_strftime(buf,100,"%x", d);
|
||||
|
||||
g_date_set_parse(d, buf);
|
||||
/* Note: this test will hopefully work, but no promises. */
|
||||
TEST("Successfully parsed a %x-formatted string",
|
||||
g_date_valid(d) &&
|
||||
g_date_month(d) == 1 &&
|
||||
g_date_day(d) == 10 &&
|
||||
g_date_year(d) == 2000);
|
||||
if (failed)
|
||||
g_date_debug_print(d);
|
||||
|
||||
g_date_free(d);
|
||||
|
||||
j = G_DATE_BAD_JULIAN;
|
||||
|
||||
i = 0;
|
||||
discontinuity = TRUE;
|
||||
y = check_years[0];
|
||||
prev_y = G_DATE_BAD_YEAR;
|
||||
while (i < n_check_years)
|
||||
{
|
||||
guint32 first_day_of_year = G_DATE_BAD_JULIAN;
|
||||
guint16 days_in_year = g_date_is_leap_year(y) ? 366 : 365;
|
||||
guint sunday_week_of_year = 0;
|
||||
guint sunday_weeks_in_year = g_date_sunday_weeks_in_year(y);
|
||||
guint monday_week_of_year = 0;
|
||||
guint monday_weeks_in_year = g_date_monday_weeks_in_year(y);
|
||||
|
||||
if (discontinuity)
|
||||
g_print(" (Break in sequence of requested years to check)\n");
|
||||
|
||||
g_print("Checking year %u", y);
|
||||
|
||||
TEST("Year is valid", g_date_valid_year(y));
|
||||
|
||||
TEST("Number of Sunday weeks in year is 52 or 53",
|
||||
sunday_weeks_in_year == 52 || sunday_weeks_in_year == 53);
|
||||
|
||||
TEST("Number of Monday weeks in year is 52 or 53",
|
||||
monday_weeks_in_year == 52 || monday_weeks_in_year == 53);
|
||||
|
||||
m = 1;
|
||||
while (m < 13)
|
||||
{
|
||||
guint8 dim = g_date_days_in_month(m,y);
|
||||
GDate days[31]; /* This is the fast way, no allocation */
|
||||
|
||||
TEST("Sensible number of days in month", (dim > 0 && dim < 32));
|
||||
|
||||
TEST("Month between 1 and 12 is valid", g_date_valid_month(m));
|
||||
|
||||
day = 1;
|
||||
|
||||
g_date_clear(days, 31);
|
||||
|
||||
while (day <= dim)
|
||||
{
|
||||
guint i;
|
||||
GDate tmp;
|
||||
|
||||
TEST("DMY triplet is valid", g_date_valid_dmy(day,m,y));
|
||||
|
||||
/* Create GDate with triplet */
|
||||
|
||||
d = &days[day-1];
|
||||
|
||||
TEST("Cleared day is invalid", !g_date_valid(d));
|
||||
|
||||
g_date_set_dmy(d,day,m,y);
|
||||
|
||||
TEST("Set day is valid", g_date_valid(d));
|
||||
|
||||
if (m == G_DATE_JANUARY && day == 1)
|
||||
{
|
||||
first_day_of_year = g_date_julian(d);
|
||||
}
|
||||
|
||||
g_assert(first_day_of_year != G_DATE_BAD_JULIAN);
|
||||
|
||||
TEST("Date with DMY triplet is valid", g_date_valid(d));
|
||||
TEST("Month accessor works", g_date_month(d) == m);
|
||||
TEST("Year accessor works", g_date_year(d) == y);
|
||||
TEST("Day of month accessor works", g_date_day(d) == day);
|
||||
|
||||
TEST("Day of year is consistent with Julian dates",
|
||||
((g_date_julian(d) + 1 - first_day_of_year) ==
|
||||
(g_date_day_of_year(d))));
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print("first day: %u this day: %u day of year: %u\n",
|
||||
first_day_of_year,
|
||||
g_date_julian(d),
|
||||
g_date_day_of_year(d));
|
||||
}
|
||||
|
||||
if (m == G_DATE_DECEMBER && day == 31)
|
||||
{
|
||||
TEST("Last day of year equals number of days in year",
|
||||
g_date_day_of_year(d) == days_in_year);
|
||||
if (failed)
|
||||
{
|
||||
g_print("last day: %u days in year: %u\n",
|
||||
g_date_day_of_year(d), days_in_year);
|
||||
}
|
||||
}
|
||||
|
||||
TEST("Day of year is not more than number of days in the year",
|
||||
g_date_day_of_year(d) <= days_in_year);
|
||||
|
||||
TEST("Monday week of year is not more than number of weeks in the year",
|
||||
g_date_monday_week_of_year(d) <= monday_weeks_in_year);
|
||||
if (failed)
|
||||
{
|
||||
g_print("Weeks in year: %u\n", monday_weeks_in_year);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
TEST("Monday week of year is >= than last week of year",
|
||||
g_date_monday_week_of_year(d) >= monday_week_of_year);
|
||||
|
||||
if (g_date_weekday(d) == G_DATE_MONDAY)
|
||||
{
|
||||
|
||||
TEST("Monday week of year on Monday 1 more than previous day's week of year",
|
||||
(g_date_monday_week_of_year(d) - monday_week_of_year) == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST("Monday week of year on non-Monday 0 more than previous day's week of year",
|
||||
(g_date_monday_week_of_year(d) - monday_week_of_year) == 0);
|
||||
}
|
||||
|
||||
|
||||
monday_week_of_year = g_date_monday_week_of_year(d);
|
||||
|
||||
|
||||
TEST("Sunday week of year is not more than number of weeks in the year",
|
||||
g_date_sunday_week_of_year(d) <= sunday_weeks_in_year);
|
||||
if (failed)
|
||||
{
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
TEST("Sunday week of year is >= than last week of year",
|
||||
g_date_sunday_week_of_year(d) >= sunday_week_of_year);
|
||||
|
||||
if (g_date_weekday(d) == G_DATE_SUNDAY)
|
||||
{
|
||||
TEST("Sunday week of year on Sunday 1 more than previous day's week of year",
|
||||
(g_date_sunday_week_of_year(d) - sunday_week_of_year) == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST("Sunday week of year on non-Sunday 0 more than previous day's week of year",
|
||||
(g_date_sunday_week_of_year(d) - sunday_week_of_year) == 0);
|
||||
}
|
||||
|
||||
sunday_week_of_year = g_date_sunday_week_of_year(d);
|
||||
|
||||
TEST("Date is equal to itself",
|
||||
g_date_compare(d,d) == 0);
|
||||
|
||||
|
||||
/*************** Increments ***********/
|
||||
|
||||
i = 1;
|
||||
while (i < 402) /* Need to get 400 year increments in */
|
||||
{
|
||||
|
||||
/***** Days ******/
|
||||
tmp = *d;
|
||||
g_date_add_days(d, i);
|
||||
|
||||
TEST("Adding days gives a value greater than previous",
|
||||
g_date_compare(d, &tmp) > 0);
|
||||
|
||||
g_date_subtract_days(d, i);
|
||||
TEST("Forward days then backward days returns us to current day",
|
||||
g_date_day(d) == day);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
TEST("Forward days then backward days returns us to current month",
|
||||
g_date_month(d) == m);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
TEST("Forward days then backward days returns us to current year",
|
||||
g_date_year(d) == y);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
/******* Months ********/
|
||||
|
||||
tmp = *d;
|
||||
g_date_add_months(d, i);
|
||||
TEST("Adding months gives a larger value",
|
||||
g_date_compare(d, &tmp) > 0);
|
||||
g_date_subtract_months(d, i);
|
||||
|
||||
TEST("Forward months then backward months returns us to current month",
|
||||
g_date_month(d) == m);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
TEST("Forward months then backward months returns us to current year",
|
||||
g_date_year(d) == y);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
|
||||
if (day < 29)
|
||||
{
|
||||
/* Day should be unchanged */
|
||||
|
||||
TEST("Forward months then backward months returns us to current day",
|
||||
g_date_day(d) == day);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reset the day for later tests */
|
||||
g_date_set_day(d, day);
|
||||
}
|
||||
|
||||
/******* Years ********/
|
||||
|
||||
tmp = *d;
|
||||
g_date_add_years(d, i);
|
||||
|
||||
TEST("Adding years gives a larger value",
|
||||
g_date_compare(d,&tmp) > 0);
|
||||
|
||||
g_date_subtract_years(d, i);
|
||||
|
||||
TEST("Forward years then backward years returns us to current month",
|
||||
g_date_month(d) == m);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
TEST("Forward years then backward years returns us to current year",
|
||||
g_date_year(d) == y);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
|
||||
if (m != 2 && day != 29)
|
||||
{
|
||||
TEST("Forward years then backward years returns us to current day",
|
||||
g_date_day(d) == day);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y);
|
||||
g_date_debug_print(d);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_date_set_day(d, day); /* reset */
|
||||
}
|
||||
|
||||
i += 10;
|
||||
}
|
||||
|
||||
/***** increment test relative to our local Julian count */
|
||||
|
||||
if (!discontinuity) {
|
||||
|
||||
/* We can only run sequence tests between sequential years */
|
||||
|
||||
TEST("Julians are sequential with increment 1",
|
||||
j+1 == g_date_julian(d));
|
||||
if (failed)
|
||||
{
|
||||
g_print("Out of sequence, prev: %u expected: %u got: %u\n",
|
||||
j, j+1, g_date_julian(d));
|
||||
}
|
||||
|
||||
g_date_add_days(d,1);
|
||||
TEST("Next day has julian 1 higher",
|
||||
g_date_julian(d) == j + 2);
|
||||
g_date_subtract_days(d, 1);
|
||||
|
||||
if (j != G_DATE_BAD_JULIAN)
|
||||
{
|
||||
g_date_subtract_days(d, 1);
|
||||
|
||||
TEST("Previous day has julian 1 lower",
|
||||
g_date_julian(d) == j);
|
||||
|
||||
g_date_add_days(d, 1); /* back to original */
|
||||
}
|
||||
}
|
||||
discontinuity = FALSE; /* goes away now */
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
j = g_date_julian(d); /* inc current julian */
|
||||
|
||||
++day;
|
||||
}
|
||||
++m;
|
||||
}
|
||||
g_print(" done\n");
|
||||
++i;
|
||||
prev_y = y;
|
||||
y = check_years[i];
|
||||
if (prev_y == G_DATE_BAD_YEAR ||
|
||||
(prev_y + 1) != y) discontinuity = TRUE;
|
||||
}
|
||||
|
||||
|
||||
g_print("\n%u tests passed, %u failed\n",passed, notpassed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,109 +0,0 @@
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
void g_date_debug_print(GDate* d)
|
||||
{
|
||||
if (!d) g_print("NULL!\n");
|
||||
else
|
||||
g_print("julian: %u (%s) DMY: %u %u %u (%s)\n",
|
||||
d->julian_days,
|
||||
d->julian ? "valid" : "invalid",
|
||||
d->day,
|
||||
d->month,
|
||||
d->year,
|
||||
d->dmy ? "valid" : "invalid");
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* These only work in the POSIX locale, maybe C too -
|
||||
* type POSIX into the program to check them
|
||||
*/
|
||||
char* posix_tests [] = {
|
||||
"19981024",
|
||||
"981024",
|
||||
"October 1998",
|
||||
"October 98",
|
||||
"oCT 98",
|
||||
"10/24/98",
|
||||
"10 -- 24 -- 98",
|
||||
"10/24/1998",
|
||||
"October 24, 1998",
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
GDate* d;
|
||||
gchar* loc;
|
||||
gchar input[1024];
|
||||
|
||||
loc = setlocale(LC_ALL,"");
|
||||
if (loc)
|
||||
g_print("\nLocale set to %s\n", loc);
|
||||
else
|
||||
g_print("\nLocale unchanged\n");
|
||||
|
||||
d = g_date_new();
|
||||
|
||||
while (fgets(input, 1023, stdin))
|
||||
{
|
||||
if (input[0] == '\n')
|
||||
{
|
||||
g_print("Enter a date to parse and press enter, or type `POSIX':\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(input,"POSIX\n") == 0)
|
||||
{
|
||||
char** s = posix_tests;
|
||||
while (*s) {
|
||||
g_date_set_parse(d, *s);
|
||||
|
||||
g_print("POSIXy parse test `%s' ...", *s);
|
||||
|
||||
if (!g_date_valid(d))
|
||||
{
|
||||
g_print(" failed.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar buf[256];
|
||||
|
||||
g_date_strftime(buf,100," parsed `%x' (%B %d %Y)\n",
|
||||
d);
|
||||
g_print("%s", buf);
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_date_set_parse(d, input);
|
||||
|
||||
if (!g_date_valid(d))
|
||||
{
|
||||
g_print("Parse failed.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar buf[256];
|
||||
|
||||
g_date_strftime(buf,100,"Parsed: `%x' (%B %d %Y)\n",
|
||||
d);
|
||||
g_print("%s", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_date_free(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
921
tests/testglib.c
921
tests/testglib.c
@ -1,921 +0,0 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "glib.h"
|
||||
|
||||
int array[10000];
|
||||
gboolean failed = FALSE;
|
||||
|
||||
#define TEST(m,cond) G_STMT_START { failed = !(cond); \
|
||||
if (failed) \
|
||||
{ if (!m) \
|
||||
g_print ("\n(%s:%d) failed for: %s\n", __FILE__, __LINE__, ( # cond )); \
|
||||
else \
|
||||
g_print ("\n(%s:%d) failed for: %s: (%s)\n", __FILE__, __LINE__, ( # cond ), (gchar*)m); \
|
||||
} \
|
||||
else \
|
||||
g_print ("."); fflush (stdout); \
|
||||
} G_STMT_END
|
||||
|
||||
#define C2P(c) ((gpointer) ((long) (c)))
|
||||
#define P2C(p) ((gchar) ((long) (p)))
|
||||
|
||||
#define GLIB_TEST_STRING "el dorado "
|
||||
#define GLIB_TEST_STRING_5 "el do"
|
||||
|
||||
static gboolean
|
||||
node_build_string (GNode *node,
|
||||
gpointer data)
|
||||
{
|
||||
gchar **p = data;
|
||||
gchar *string;
|
||||
gchar c[2] = "_";
|
||||
|
||||
c[0] = P2C (node->data);
|
||||
|
||||
string = g_strconcat (*p ? *p : "", c, NULL);
|
||||
g_free (*p);
|
||||
*p = string;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
g_node_test (void)
|
||||
{
|
||||
GNode *root;
|
||||
GNode *node;
|
||||
GNode *node_B;
|
||||
GNode *node_F;
|
||||
GNode *node_G;
|
||||
GNode *node_J;
|
||||
guint i;
|
||||
gchar *tstring;
|
||||
|
||||
g_print ("checking n-way trees: ");
|
||||
failed = FALSE;
|
||||
|
||||
root = g_node_new (C2P ('A'));
|
||||
TEST (NULL, g_node_depth (root) == 1 && g_node_max_height (root) == 1);
|
||||
|
||||
node_B = g_node_new (C2P ('B'));
|
||||
g_node_append (root, node_B);
|
||||
TEST (NULL, root->children == node_B);
|
||||
|
||||
g_node_append_data (node_B, C2P ('E'));
|
||||
g_node_prepend_data (node_B, C2P ('C'));
|
||||
g_node_insert (node_B, 1, g_node_new (C2P ('D')));
|
||||
|
||||
node_F = g_node_new (C2P ('F'));
|
||||
g_node_append (root, node_F);
|
||||
TEST (NULL, root->children->next == node_F);
|
||||
|
||||
node_G = g_node_new (C2P ('G'));
|
||||
g_node_append (node_F, node_G);
|
||||
node_J = g_node_new (C2P ('J'));
|
||||
g_node_prepend (node_G, node_J);
|
||||
g_node_insert (node_G, 42, g_node_new (C2P ('K')));
|
||||
g_node_insert_data (node_G, 0, C2P ('H'));
|
||||
g_node_insert (node_G, 1, g_node_new (C2P ('I')));
|
||||
|
||||
TEST (NULL, g_node_depth (root) == 1);
|
||||
TEST (NULL, g_node_max_height (root) == 4);
|
||||
TEST (NULL, g_node_depth (node_G->children->next) == 4);
|
||||
TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_LEAFS) == 7);
|
||||
TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_NON_LEAFS) == 4);
|
||||
TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == 11);
|
||||
TEST (NULL, g_node_max_height (node_F) == 3);
|
||||
TEST (NULL, g_node_n_children (node_G) == 4);
|
||||
TEST (NULL, g_node_find_child (root, G_TRAVERSE_ALL, C2P ('F')) == node_F);
|
||||
TEST (NULL, g_node_find (root, G_LEVEL_ORDER, G_TRAVERSE_NON_LEAFS, C2P ('I')) == NULL);
|
||||
TEST (NULL, g_node_find (root, G_IN_ORDER, G_TRAVERSE_LEAFS, C2P ('J')) == node_J);
|
||||
|
||||
for (i = 0; i < g_node_n_children (node_B); i++)
|
||||
{
|
||||
node = g_node_nth_child (node_B, i);
|
||||
TEST (NULL, P2C (node->data) == ('C' + i));
|
||||
}
|
||||
|
||||
for (i = 0; i < g_node_n_children (node_G); i++)
|
||||
TEST (NULL, g_node_child_position (node_G, g_node_nth_child (node_G, i)) == i);
|
||||
|
||||
/* we have built: A
|
||||
* / \
|
||||
* B F
|
||||
* / | \ \
|
||||
* C D E G
|
||||
* / /\ \
|
||||
* H I J K
|
||||
*
|
||||
* for in-order traversal, 'G' is considered to be the "left"
|
||||
* child of 'F', which will cause 'F' to be the last node visited.
|
||||
*/
|
||||
|
||||
tstring = NULL;
|
||||
g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "ABCDEFGHIJK") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
g_node_traverse (root, G_POST_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "CDEBHIJKGFA") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
g_node_traverse (root, G_IN_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "CBDEAHGIJKF") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "ABFCDEGHIJK") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
|
||||
g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_LEAFS, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "CDEHIJK") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
g_node_traverse (root, G_PRE_ORDER, G_TRAVERSE_NON_LEAFS, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "ABFG") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
|
||||
g_node_reverse_children (node_B);
|
||||
g_node_reverse_children (node_G);
|
||||
|
||||
g_node_traverse (root, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, node_build_string, &tstring);
|
||||
TEST (tstring, strcmp (tstring, "ABFEDCGKJIH") == 0);
|
||||
g_free (tstring); tstring = NULL;
|
||||
|
||||
g_node_destroy (root);
|
||||
|
||||
/* allocation tests */
|
||||
|
||||
root = g_node_new (NULL);
|
||||
node = root;
|
||||
|
||||
for (i = 0; i < 2048; i++)
|
||||
{
|
||||
g_node_append (node, g_node_new (NULL));
|
||||
if ((i%5) == 4)
|
||||
node = node->children->next;
|
||||
}
|
||||
TEST (NULL, g_node_max_height (root) > 100);
|
||||
TEST (NULL, g_node_n_nodes (root, G_TRAVERSE_ALL) == 1 + 2048);
|
||||
|
||||
g_node_destroy (root);
|
||||
|
||||
if (!failed)
|
||||
g_print ("ok\n");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
my_hash_callback_remove (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
int *d = value;
|
||||
|
||||
if ((*d) % 2)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
my_hash_callback_remove_test (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
int *d = value;
|
||||
|
||||
if ((*d) % 2)
|
||||
g_print ("bad!\n");
|
||||
}
|
||||
|
||||
static void
|
||||
my_hash_callback (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
int *d = value;
|
||||
*d = 1;
|
||||
}
|
||||
|
||||
static guint
|
||||
my_hash (gconstpointer key)
|
||||
{
|
||||
return (guint) *((const gint*) key);
|
||||
}
|
||||
|
||||
static gint
|
||||
my_hash_compare (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
return *((const gint*) a) == *((const gint*) b);
|
||||
}
|
||||
|
||||
static gint
|
||||
my_list_compare_one (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
gint one = *((const gint*)a);
|
||||
gint two = *((const gint*)b);
|
||||
return one-two;
|
||||
}
|
||||
|
||||
static gint
|
||||
my_list_compare_two (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
gint one = *((const gint*)a);
|
||||
gint two = *((const gint*)b);
|
||||
return two-one;
|
||||
}
|
||||
|
||||
/* static void
|
||||
my_list_print (gpointer a, gpointer b)
|
||||
{
|
||||
gint three = *((gint*)a);
|
||||
g_print("%d", three);
|
||||
}; */
|
||||
|
||||
static gint
|
||||
my_compare (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const char *cha = a;
|
||||
const char *chb = b;
|
||||
|
||||
return *cha - *chb;
|
||||
}
|
||||
|
||||
static gint
|
||||
my_traverse (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
char *ch = key;
|
||||
g_print ("%c ", *ch);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
GList *list, *t;
|
||||
GSList *slist, *st;
|
||||
GHashTable *hash_table;
|
||||
GMemChunk *mem_chunk;
|
||||
GStringChunk *string_chunk;
|
||||
GTimer *timer;
|
||||
gint nums[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
gint morenums[10] = { 8, 9, 7, 0, 3, 2, 5, 1, 4, 6};
|
||||
gchar *string;
|
||||
|
||||
gchar *mem[10000], *tmp_string = NULL, *tmp_string_2;
|
||||
gint i, j;
|
||||
GArray *garray;
|
||||
GPtrArray *gparray;
|
||||
GByteArray *gbarray;
|
||||
GString *string1, *string2;
|
||||
GTree *tree;
|
||||
char chars[62];
|
||||
GRelation *relation;
|
||||
GTuples *tuples;
|
||||
gint data [1024];
|
||||
struct {
|
||||
gchar *filename;
|
||||
gchar *dirname;
|
||||
} dirname_checks[] = {
|
||||
#ifndef NATIVE_WIN32
|
||||
{ "/", "/" },
|
||||
{ "////", "/" },
|
||||
{ ".////", "." },
|
||||
{ ".", "." },
|
||||
{ "..", "." },
|
||||
{ "../", ".." },
|
||||
{ "..////", ".." },
|
||||
{ "", "." },
|
||||
{ "a/b", "a" },
|
||||
{ "a/b/", "a/b" },
|
||||
{ "c///", "c" },
|
||||
#else
|
||||
{ "\\", "\\" },
|
||||
{ ".\\\\\\\\", "." },
|
||||
{ ".", "." },
|
||||
{ "..", "." },
|
||||
{ "..\\", ".." },
|
||||
{ "..\\\\\\\\", ".." },
|
||||
{ "", "." },
|
||||
{ "a\\b", "a" },
|
||||
{ "a\\b\\", "a\\b" },
|
||||
{ "c\\\\\\", "c" },
|
||||
#endif
|
||||
};
|
||||
guint n_dirname_checks = sizeof (dirname_checks) / sizeof (dirname_checks[0]);
|
||||
guint16 gu16t1 = 0x44afU, gu16t2 = 0xaf44U;
|
||||
guint32 gu32t1 = 0x02a7f109U, gu32t2 = 0x09f1a702U;
|
||||
#ifdef G_HAVE_GINT64
|
||||
guint64 gu64t1 = G_GINT64_CONSTANT(0x1d636b02300a7aa7U),
|
||||
gu64t2 = G_GINT64_CONSTANT(0xa77a0a30026b631dU);
|
||||
#endif
|
||||
|
||||
g_print ("TestGLib v%u.%u.%u (i:%u b:%u)\n",
|
||||
glib_major_version,
|
||||
glib_minor_version,
|
||||
glib_micro_version,
|
||||
glib_interface_age,
|
||||
glib_binary_age);
|
||||
|
||||
string = g_get_current_dir ();
|
||||
g_print ("cwd: %s\n", string);
|
||||
g_free (string);
|
||||
g_print ("user: %s\n", g_get_user_name ());
|
||||
g_print ("real: %s\n", g_get_real_name ());
|
||||
g_print ("home: %s\n", g_get_home_dir ());
|
||||
g_print ("tmp-dir: %s\n", g_get_tmp_dir ());
|
||||
|
||||
/* type sizes */
|
||||
g_print ("checking size of gint8: %d", (int)sizeof (gint8));
|
||||
TEST (NULL, sizeof (gint8) == 1);
|
||||
g_print ("\nchecking size of gint16: %d", (int)sizeof (gint16));
|
||||
TEST (NULL, sizeof (gint16) == 2);
|
||||
g_print ("\nchecking size of gint32: %d", (int)sizeof (gint32));
|
||||
TEST (NULL, sizeof (gint32) == 4);
|
||||
#ifdef G_HAVE_GINT64
|
||||
g_print ("\nchecking size of gint64: %d", (int)sizeof (gint64));
|
||||
TEST (NULL, sizeof (gint64) == 8);
|
||||
#endif /* G_HAVE_GINT64 */
|
||||
g_print ("\n");
|
||||
|
||||
g_print ("checking g_dirname()...");
|
||||
for (i = 0; i < n_dirname_checks; i++)
|
||||
{
|
||||
gchar *dirname;
|
||||
|
||||
dirname = g_dirname (dirname_checks[i].filename);
|
||||
if (strcmp (dirname, dirname_checks[i].dirname) != 0)
|
||||
{
|
||||
g_print ("\nfailed for \"%s\"==\"%s\" (returned: \"%s\")\n",
|
||||
dirname_checks[i].filename,
|
||||
dirname_checks[i].dirname,
|
||||
dirname);
|
||||
n_dirname_checks = 0;
|
||||
}
|
||||
g_free (dirname);
|
||||
}
|
||||
if (n_dirname_checks)
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking doubly linked lists...");
|
||||
|
||||
list = NULL;
|
||||
for (i = 0; i < 10; i++)
|
||||
list = g_list_append (list, &nums[i]);
|
||||
list = g_list_reverse (list);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
t = g_list_nth (list, i);
|
||||
if (*((gint*) t->data) != (9 - i))
|
||||
g_error ("Regular insert failed");
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
if(g_list_position(list, g_list_nth (list, i)) != i)
|
||||
g_error("g_list_position does not seem to be the inverse of g_list_nth\n");
|
||||
|
||||
g_list_free (list);
|
||||
list = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
list = g_list_insert_sorted (list, &morenums[i], my_list_compare_one);
|
||||
|
||||
/*
|
||||
g_print("\n");
|
||||
g_list_foreach (list, my_list_print, NULL);
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
t = g_list_nth (list, i);
|
||||
if (*((gint*) t->data) != i)
|
||||
g_error ("Sorted insert failed");
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
list = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
list = g_list_insert_sorted (list, &morenums[i], my_list_compare_two);
|
||||
|
||||
/*
|
||||
g_print("\n");
|
||||
g_list_foreach (list, my_list_print, NULL);
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
t = g_list_nth (list, i);
|
||||
if (*((gint*) t->data) != (9 - i))
|
||||
g_error ("Sorted insert failed");
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
list = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
list = g_list_prepend (list, &morenums[i]);
|
||||
|
||||
list = g_list_sort (list, my_list_compare_two);
|
||||
|
||||
/*
|
||||
g_print("\n");
|
||||
g_list_foreach (list, my_list_print, NULL);
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
t = g_list_nth (list, i);
|
||||
if (*((gint*) t->data) != (9 - i))
|
||||
g_error ("Merge sort failed");
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking singly linked lists...");
|
||||
|
||||
slist = NULL;
|
||||
for (i = 0; i < 10; i++)
|
||||
slist = g_slist_append (slist, &nums[i]);
|
||||
slist = g_slist_reverse (slist);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
st = g_slist_nth (slist, i);
|
||||
if (*((gint*) st->data) != (9 - i))
|
||||
g_error ("failed");
|
||||
}
|
||||
|
||||
g_slist_free (slist);
|
||||
slist = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
slist = g_slist_insert_sorted (slist, &morenums[i], my_list_compare_one);
|
||||
|
||||
/*
|
||||
g_print("\n");
|
||||
g_slist_foreach (slist, my_list_print, NULL);
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
st = g_slist_nth (slist, i);
|
||||
if (*((gint*) st->data) != i)
|
||||
g_error ("Sorted insert failed");
|
||||
}
|
||||
|
||||
g_slist_free(slist);
|
||||
slist = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
slist = g_slist_insert_sorted (slist, &morenums[i], my_list_compare_two);
|
||||
|
||||
/*
|
||||
g_print("\n");
|
||||
g_slist_foreach (slist, my_list_print, NULL);
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
st = g_slist_nth (slist, i);
|
||||
if (*((gint*) st->data) != (9 - i))
|
||||
g_error("Sorted insert failed");
|
||||
}
|
||||
|
||||
g_slist_free(slist);
|
||||
slist = NULL;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
slist = g_slist_prepend (slist, &morenums[i]);
|
||||
|
||||
slist = g_slist_sort (slist, my_list_compare_two);
|
||||
|
||||
/*
|
||||
g_print("\n");
|
||||
g_slist_foreach (slist, my_list_print, NULL);
|
||||
*/
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
st = g_slist_nth (slist, i);
|
||||
if (*((gint*) st->data) != (9 - i))
|
||||
g_error("Sorted insert failed");
|
||||
}
|
||||
|
||||
g_slist_free(slist);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking binary trees...\n");
|
||||
|
||||
tree = g_tree_new (my_compare);
|
||||
i = 0;
|
||||
for (j = 0; j < 10; j++, i++)
|
||||
{
|
||||
chars[i] = '0' + j;
|
||||
g_tree_insert (tree, &chars[i], &chars[i]);
|
||||
}
|
||||
for (j = 0; j < 26; j++, i++)
|
||||
{
|
||||
chars[i] = 'A' + j;
|
||||
g_tree_insert (tree, &chars[i], &chars[i]);
|
||||
}
|
||||
for (j = 0; j < 26; j++, i++)
|
||||
{
|
||||
chars[i] = 'a' + j;
|
||||
g_tree_insert (tree, &chars[i], &chars[i]);
|
||||
}
|
||||
|
||||
g_print ("tree height: %d\n", g_tree_height (tree));
|
||||
g_print ("tree nnodes: %d\n", g_tree_nnodes (tree));
|
||||
|
||||
g_print ("tree: ");
|
||||
g_tree_traverse (tree, my_traverse, G_IN_ORDER, NULL);
|
||||
g_print ("\n");
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
g_tree_remove (tree, &chars[i]);
|
||||
|
||||
g_print ("tree height: %d\n", g_tree_height (tree));
|
||||
g_print ("tree nnodes: %d\n", g_tree_nnodes (tree));
|
||||
|
||||
g_print ("tree: ");
|
||||
g_tree_traverse (tree, my_traverse, G_IN_ORDER, NULL);
|
||||
g_print ("\n");
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
/* check n-way trees */
|
||||
g_node_test ();
|
||||
|
||||
g_print ("checking mem chunks...");
|
||||
|
||||
mem_chunk = g_mem_chunk_new ("test mem chunk", 50, 100, G_ALLOC_AND_FREE);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
mem[i] = g_chunk_new (gchar, mem_chunk);
|
||||
|
||||
for (j = 0; j < 50; j++)
|
||||
mem[i][j] = i * j;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
g_mem_chunk_free (mem_chunk, mem[i]);
|
||||
}
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking hash tables...");
|
||||
|
||||
hash_table = g_hash_table_new (my_hash, my_hash_compare);
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
array[i] = i;
|
||||
g_hash_table_insert (hash_table, &array[i], &array[i]);
|
||||
}
|
||||
g_hash_table_foreach (hash_table, my_hash_callback, NULL);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
if (array[i] == 0)
|
||||
g_print ("%d\n", i);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_hash_table_remove (hash_table, &array[i]);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
array[i] = i;
|
||||
g_hash_table_insert (hash_table, &array[i], &array[i]);
|
||||
}
|
||||
|
||||
if (g_hash_table_foreach_remove (hash_table, my_hash_callback_remove, NULL) != 5000 ||
|
||||
g_hash_table_size (hash_table) != 5000)
|
||||
g_print ("bad!\n");
|
||||
|
||||
g_hash_table_foreach (hash_table, my_hash_callback_remove_test, NULL);
|
||||
|
||||
|
||||
g_hash_table_destroy (hash_table);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking string chunks...");
|
||||
|
||||
string_chunk = g_string_chunk_new (1024);
|
||||
|
||||
for (i = 0; i < 100000; i ++)
|
||||
{
|
||||
tmp_string = g_string_chunk_insert (string_chunk, "hi pete");
|
||||
|
||||
if (strcmp ("hi pete", tmp_string) != 0)
|
||||
g_error ("string chunks are broken.\n");
|
||||
}
|
||||
|
||||
tmp_string_2 = g_string_chunk_insert_const (string_chunk, tmp_string);
|
||||
|
||||
g_assert (tmp_string_2 != tmp_string &&
|
||||
strcmp(tmp_string_2, tmp_string) == 0);
|
||||
|
||||
tmp_string = g_string_chunk_insert_const (string_chunk, tmp_string);
|
||||
|
||||
g_assert (tmp_string_2 == tmp_string);
|
||||
|
||||
g_string_chunk_free (string_chunk);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking arrays...");
|
||||
|
||||
garray = g_array_new (FALSE, FALSE, sizeof (gint));
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_array_append_val (garray, i);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
if (g_array_index (garray, gint, i) != i)
|
||||
g_print ("uh oh: %d ( %d )\n", g_array_index (garray, gint, i), i);
|
||||
|
||||
g_array_free (garray, TRUE);
|
||||
|
||||
garray = g_array_new (FALSE, FALSE, sizeof (gint));
|
||||
for (i = 0; i < 100; i++)
|
||||
g_array_prepend_val (garray, i);
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
if (g_array_index (garray, gint, i) != (100 - i - 1))
|
||||
g_print ("uh oh: %d ( %d )\n", g_array_index (garray, gint, i), 100 - i - 1);
|
||||
|
||||
g_array_free (garray, TRUE);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking strings...");
|
||||
|
||||
string1 = g_string_new ("hi pete!");
|
||||
string2 = g_string_new ("");
|
||||
|
||||
g_assert (strcmp ("hi pete!", string1->str) == 0);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_string_append_c (string1, 'a'+(i%26));
|
||||
|
||||
#if !(defined (_MSC_VER) || defined (__LCC__))
|
||||
/* MSVC and LCC use the same run-time C library, which doesn't like
|
||||
the %10000.10000f format... */
|
||||
g_string_sprintf (string2, "%s|%0100d|%s|%s|%0*d|%*.*f|%10000.10000f",
|
||||
"this pete guy sure is a wuss, like he's the number ",
|
||||
1,
|
||||
" wuss. everyone agrees.\n",
|
||||
string1->str,
|
||||
10, 666, 15, 15, 666.666666666, 666.666666666);
|
||||
#else
|
||||
g_string_sprintf (string2, "%s|%0100d|%s|%s|%0*d|%*.*f|%100.100f",
|
||||
"this pete guy sure is a wuss, like he's the number ",
|
||||
1,
|
||||
" wuss. everyone agrees.\n",
|
||||
string1->str,
|
||||
10, 666, 15, 15, 666.666666666, 666.666666666);
|
||||
#endif
|
||||
|
||||
g_print ("string2 length = %d...\n", string2->len);
|
||||
string2->str[70] = '\0';
|
||||
g_print ("first 70 chars:\n%s\n", string2->str);
|
||||
string2->str[141] = '\0';
|
||||
g_print ("next 70 chars:\n%s\n", string2->str+71);
|
||||
string2->str[212] = '\0';
|
||||
g_print ("and next 70:\n%s\n", string2->str+142);
|
||||
g_print ("last 70 chars:\n%s\n", string2->str+string2->len - 70);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking timers...\n");
|
||||
|
||||
timer = g_timer_new ();
|
||||
g_print (" spinning for 3 seconds...\n");
|
||||
|
||||
g_timer_start (timer);
|
||||
while (g_timer_elapsed (timer, NULL) < 3)
|
||||
;
|
||||
|
||||
g_timer_stop (timer);
|
||||
g_timer_destroy (timer);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking g_strcasecmp...");
|
||||
g_assert (g_strcasecmp ("FroboZZ", "frobozz") == 0);
|
||||
g_assert (g_strcasecmp ("frobozz", "frobozz") == 0);
|
||||
g_assert (g_strcasecmp ("frobozz", "FROBOZZ") == 0);
|
||||
g_assert (g_strcasecmp ("FROBOZZ", "froboz") != 0);
|
||||
g_assert (g_strcasecmp ("", "") == 0);
|
||||
g_assert (g_strcasecmp ("!#%&/()", "!#%&/()") == 0);
|
||||
g_assert (g_strcasecmp ("a", "b") < 0);
|
||||
g_assert (g_strcasecmp ("a", "B") < 0);
|
||||
g_assert (g_strcasecmp ("A", "b") < 0);
|
||||
g_assert (g_strcasecmp ("A", "B") < 0);
|
||||
g_assert (g_strcasecmp ("b", "a") > 0);
|
||||
g_assert (g_strcasecmp ("b", "A") > 0);
|
||||
g_assert (g_strcasecmp ("B", "a") > 0);
|
||||
g_assert (g_strcasecmp ("B", "A") > 0);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking g_strdup...");
|
||||
g_assert(g_strdup(NULL) == NULL);
|
||||
string = g_strdup(GLIB_TEST_STRING);
|
||||
g_assert(string != NULL);
|
||||
g_assert(strcmp(string, GLIB_TEST_STRING) == 0);
|
||||
g_free(string);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking g_strconcat...");
|
||||
string = g_strconcat(GLIB_TEST_STRING, NULL);
|
||||
g_assert(string != NULL);
|
||||
g_assert(strcmp(string, GLIB_TEST_STRING) == 0);
|
||||
g_free(string);
|
||||
string = g_strconcat(GLIB_TEST_STRING, GLIB_TEST_STRING,
|
||||
GLIB_TEST_STRING, NULL);
|
||||
g_assert(string != NULL);
|
||||
g_assert(strcmp(string, GLIB_TEST_STRING GLIB_TEST_STRING
|
||||
GLIB_TEST_STRING) == 0);
|
||||
g_free(string);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking g_strdup_printf...");
|
||||
string = g_strdup_printf ("%05d %-5s", 21, "test");
|
||||
g_assert (string != NULL);
|
||||
g_assert (strcmp(string, "00021 test ") == 0);
|
||||
g_free (string);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
/* g_debug (argv[0]); */
|
||||
|
||||
/* Relation tests */
|
||||
|
||||
g_print ("checking relations...");
|
||||
|
||||
relation = g_relation_new (2);
|
||||
|
||||
g_relation_index (relation, 0, g_int_hash, g_int_equal);
|
||||
g_relation_index (relation, 1, g_int_hash, g_int_equal);
|
||||
|
||||
for (i = 0; i < 1024; i += 1)
|
||||
data[i] = i;
|
||||
|
||||
for (i = 1; i < 1023; i += 1)
|
||||
{
|
||||
g_relation_insert (relation, data + i, data + i + 1);
|
||||
g_relation_insert (relation, data + i, data + i - 1);
|
||||
}
|
||||
|
||||
for (i = 2; i < 1022; i += 1)
|
||||
{
|
||||
g_assert (! g_relation_exists (relation, data + i, data + i));
|
||||
g_assert (! g_relation_exists (relation, data + i, data + i + 2));
|
||||
g_assert (! g_relation_exists (relation, data + i, data + i - 2));
|
||||
}
|
||||
|
||||
for (i = 1; i < 1023; i += 1)
|
||||
{
|
||||
g_assert (g_relation_exists (relation, data + i, data + i + 1));
|
||||
g_assert (g_relation_exists (relation, data + i, data + i - 1));
|
||||
}
|
||||
|
||||
for (i = 2; i < 1022; i += 1)
|
||||
{
|
||||
g_assert (g_relation_count (relation, data + i, 0) == 2);
|
||||
g_assert (g_relation_count (relation, data + i, 1) == 2);
|
||||
}
|
||||
|
||||
g_assert (g_relation_count (relation, data, 0) == 0);
|
||||
|
||||
g_assert (g_relation_count (relation, data + 42, 0) == 2);
|
||||
g_assert (g_relation_count (relation, data + 43, 1) == 2);
|
||||
g_assert (g_relation_count (relation, data + 41, 1) == 2);
|
||||
g_relation_delete (relation, data + 42, 0);
|
||||
g_assert (g_relation_count (relation, data + 42, 0) == 0);
|
||||
g_assert (g_relation_count (relation, data + 43, 1) == 1);
|
||||
g_assert (g_relation_count (relation, data + 41, 1) == 1);
|
||||
|
||||
tuples = g_relation_select (relation, data + 200, 0);
|
||||
|
||||
g_assert (tuples->len == 2);
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < tuples->len; i += 1)
|
||||
{
|
||||
printf ("%d %d\n",
|
||||
*(gint*) g_tuples_index (tuples, i, 0),
|
||||
*(gint*) g_tuples_index (tuples, i, 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert (g_relation_exists (relation, data + 300, data + 301));
|
||||
g_relation_delete (relation, data + 300, 0);
|
||||
g_assert (!g_relation_exists (relation, data + 300, data + 301));
|
||||
|
||||
g_tuples_destroy (tuples);
|
||||
|
||||
g_relation_destroy (relation);
|
||||
|
||||
relation = NULL;
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
g_print ("checking pointer arrays...");
|
||||
|
||||
gparray = g_ptr_array_new ();
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_ptr_array_add (gparray, GINT_TO_POINTER (i));
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
if (g_ptr_array_index (gparray, i) != GINT_TO_POINTER (i))
|
||||
g_print ("array fails: %p ( %p )\n", g_ptr_array_index (gparray, i), GINT_TO_POINTER (i));
|
||||
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
|
||||
g_print ("ok\n");
|
||||
|
||||
|
||||
g_print ("checking byte arrays...");
|
||||
|
||||
gbarray = g_byte_array_new ();
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_byte_array_append (gbarray, (guint8*) "abcd", 4);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
g_assert (gbarray->data[4*i] == 'a');
|
||||
g_assert (gbarray->data[4*i+1] == 'b');
|
||||
g_assert (gbarray->data[4*i+2] == 'c');
|
||||
g_assert (gbarray->data[4*i+3] == 'd');
|
||||
}
|
||||
|
||||
g_byte_array_free (gbarray, TRUE);
|
||||
g_print ("ok\n");
|
||||
|
||||
g_printerr ("g_log tests:");
|
||||
g_warning ("harmless warning with parameters: %d %s %#x", 42, "Boo", 12345);
|
||||
g_message ("the next warning is a test:");
|
||||
string = NULL;
|
||||
g_print (string);
|
||||
|
||||
g_print ("checking endian macros (host is ");
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
g_print ("big endian)...");
|
||||
#else
|
||||
g_print ("little endian)...");
|
||||
#endif
|
||||
g_assert (GUINT16_SWAP_LE_BE (gu16t1) == gu16t2);
|
||||
g_assert (GUINT32_SWAP_LE_BE (gu32t1) == gu32t2);
|
||||
#ifdef G_HAVE_GINT64
|
||||
g_assert (GUINT64_SWAP_LE_BE (gu64t1) == gu64t2);
|
||||
#endif
|
||||
g_print ("ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user