commit 030129423f63ad5df669f26640fbdf0292828a86 Author: Alexander Vdolainen Date: Mon Nov 24 00:22:08 2014 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c9f1de --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +*~ +*.o +*.a +*.lo +*.la +*.dvi +*.synctex.gz +.deps +.libs +autom4te.cache/ +Makefile +Makefile.in +aclocal.m4 +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +depcomp +install-sh +intltool-extract.in +intltool-merge.in +intltool-update.in +lib/libtdata-0.2.pc +libtool +ltmain.sh +missing +mkinstalldirs +po/Makefile.in.in +po/POTFILES +po/stamp-it +stamp-h1 +include/version.h +.emacs.desktop +nbproject diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..8ac1c7e --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +This software was developed by Askele companies group. + * EU part: http://askele.com + * NW European part of Russia: http://askele-ingria.com +Team: + * General SW Architect and PM: Alexander Vdolainen diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..befd914 --- /dev/null +++ b/COPYING @@ -0,0 +1,3 @@ +Askele business software license. + +Libs and others might be under LGPLv3. \ No newline at end of file diff --git a/COPYING.LGPL3 b/COPYING.LGPL3 new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/COPYING.LGPL3 @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..93ca727 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,10 @@ +2013-09-22 Alexander Vdolainen + * (a set of files): added autotools + +2014-11-23 Alexander Vdolainen + * Initial import of 0.2 version + + +Copyright 2013-2014 Askele, Inc. +Copying and distribution of this file, with or without modification, are +permitted provided the copyright notice and this notice are preserved. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..a1e89e1 --- /dev/null +++ b/INSTALL @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..bf26403 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,32 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = po include lib + +libtdatadocdir = ${prefix}/doc/libtdata +libtdatadoc_DATA = \ + README\ + COPYING\ + AUTHORS\ + ChangeLog\ + INSTALL\ + NEWS + + +INTLTOOL_FILES = intltool-extract.in \ + intltool-merge.in \ + intltool-update.in + +EXTRA_DIST = $(libtdatadoc_DATA) \ + $(INTLTOOL_FILES) + +DISTCLEANFILES = intltool-extract \ + intltool-merge \ + intltool-update \ + po/.intltool-merge-cache + +clean-local: + + +# Remove doc directory on uninstall +uninstall-local: + -rm -r $(libtdatadocdir) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..195c730 --- /dev/null +++ b/NEWS @@ -0,0 +1 @@ +22.09.2013: Autotools choosen to be a build be. diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..a0ec5ee --- /dev/null +++ b/autogen.sh @@ -0,0 +1,157 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +if [ -n "$GNOME2_DIR" ]; then + ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS" + LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH" + PATH="$GNOME2_DIR/bin:$PATH" + export PATH + export LD_LIBRARY_PATH +fi + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level package directory" + exit 1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`autoconf' installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^IT_PROG_INTLTOOL" $srcdir/configure.ac >/dev/null) && { + (intltoolize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`intltool' installed." + echo "You can get it from:" + echo " ftp://ftp.gnome.org/pub/GNOME/" + DIE=1 + } +} + +(grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.ac >/dev/null) && { + (xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`xml-i18n-toolize' installed." + echo "You can get it from:" + echo " ftp://ftp.gnome.org/pub/GNOME/" + DIE=1 + } +} + +(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { + (libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`libtool' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } +} + +(grep "^AM_GLIB_GNU_GETTEXT" $srcdir/configure.ac >/dev/null) && { + (grep "sed.*POTFILES" $srcdir/configure.ac) > /dev/null || \ + (glib-gettextize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`glib' installed." + echo "You can get it from: ftp://ftp.gtk.org/pub/gtk" + DIE=1 + } +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`automake' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing \`aclocal'. The version of \`automake'" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo \`$0\'" command line." + echo +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + +for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.ac -print` +do + dr=`dirname $coin` + if test -f $dr/NO-AUTO-GEN; then + echo skipping $dr -- flagged as no auto-gen + else + echo processing $dr + ( cd $dr + + aclocalinclude="$ACLOCAL_FLAGS" + + if grep "^AM_GLIB_GNU_GETTEXT" configure.ac >/dev/null; then + echo "Creating $dr/aclocal.m4 ..." + test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 + echo "Running glib-gettextize... Ignore non-fatal messages." + echo "no" | glib-gettextize --force --copy + echo "Making $dr/aclocal.m4 writable ..." + test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 + fi + if grep "^IT_PROG_INTLTOOL" configure.ac >/dev/null; then + echo "Running intltoolize..." + intltoolize --copy --force --automake + fi + if grep "^AM_PROG_XML_I18N_TOOLS" configure.ac >/dev/null; then + echo "Running xml-i18n-toolize..." + xml-i18n-toolize --copy --force --automake + fi + if grep "^LT_INIT" configure.ac >/dev/null; then + if test -z "$NO_LIBTOOLIZE" ; then + echo "Running libtoolize..." + libtoolize --force --copy + fi + fi + echo "Running aclocal $aclocalinclude ..." + aclocal $aclocalinclude + if grep "^A[CM]_CONFIG_HEADER" configure.ac >/dev/null; then + echo "Running autoheader..." + autoheader + fi + echo "Running automake --gnu $am_opt ..." + automake --add-missing --copy --gnu $am_opt + echo "Running autoconf ..." + autoconf + ) + fi +done + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure "$@" ... + $srcdir/configure "$@" \ + && echo Now type \`make\' to compile. || exit 1 +else + echo Skipping configure process. +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..2ddd070 --- /dev/null +++ b/configure.ac @@ -0,0 +1,42 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(libtdata, 0.2) + +AC_CONFIG_HEADERS([config.h]) + +AM_INIT_AUTOMAKE([1.11]) + +AM_SILENT_RULES([yes]) + +AC_PROG_CC + +dnl *************************************************************************** +dnl Internationalization +dnl *************************************************************************** +IT_PROG_INTLTOOL([0.35.0]) + +GETTEXT_PACKAGE=libtdata +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [GETTEXT package name]) +AM_GLIB_GNU_GETTEXT + + +LT_INIT + +dnl ***************** +dnl ***** options ***** +dnl ***************** + +AC_ARG_ENABLE([build_examples], + AS_HELP_STRING([--enable-build-examples], [Enable examples build])) + +AS_IF([test "x$enable_build_examples" = "xyes"], [ + AC_DEFINE([BUILD_EXAMPLES], 1, [build of examples enabled]) +]) + +AC_OUTPUT([ +Makefile +lib/libtdata-0.2.pc +lib/Makefile +include/Makefile +po/Makefile.in]) diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 0000000..e69de29 diff --git a/examples/TODO b/examples/TODO new file mode 100644 index 0000000..e69de29 diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..ebbaf3d --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1 @@ +nobase_include_HEADERS = tdata/bitwise.h tdata/idx_allocator.h tdata/macro.h tdata/tree.h tdata/usrtc.h diff --git a/include/tdata/bitwise.h b/include/tdata/bitwise.h new file mode 100644 index 0000000..ada6a04 --- /dev/null +++ b/include/tdata/bitwise.h @@ -0,0 +1,429 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * (c) Copyright 2006,2007,2008 Jari OS Core Team + * (c) Copyright 2008 Dmitry Gromada + * (c) Copyright 2010 Alexander Vdolainen + * + * (c) Copyright 2012 - 2013 Askele Oy + * + * Implements bitwise operations with multiword bitmaps + */ + +#ifndef __BITWISE_H__ +#define __BITWISE_H__ + +/* TODO: add arch deps */ +//#include + +/* TODO: add linux headers tests */ +#include + +#ifdef __BITS_PER_LONG +#define BITS_PER_LONG __BITS_PER_LONG +#endif + +#if BITS_PER_LONG == 64 +#define TYPE_LONG_SHIFT 6 +#endif + +#if BITS_PER_LONG == 32 +#define TYPE_LONG_SHIFT 5 +#endif + +typedef struct __bitmap { + int nwords; + unsigned long *map; +} bitmap_t; + +/** + * @fn static inline void bit_set(void *bitmap, int bit) + * Set bit number @a bit in the bitmap @a bitmap + * @note The limit of @a bitmap = sizeof(unsigned long) + * + * @param[out] bitmap - A pointer to the bitmap + * @param bit - Number of bit to set + */ +#ifndef ARCH_BIT_SET +static inline void bit_set(void *bitmap, int bit) +{ + *(unsigned long *)bitmap |= (1 << bit); +} +#else +#define bit_set(bitmap, bit) arch_bit_set(bitmap, bit) +#endif /* ARCH_BIT_SET */ + +/** + * @fn static inline void bit_clear(void *bitmap, int bit) + * Clear bit number @a bit in the bitmap @a bitmap + * @note The limit of @a bitmap = sizeof(unsigned long) + * + * @param[out] bitmap - A pointer to the bitmap + * @param bit - Number of bit to clear + */ +#ifndef ARCH_BIT_CLEAR +static inline void bit_clear(void *bitmap, int bit) +{ + *(unsigned long *)bitmap &= ~(1 << bit); +} +#else +#define bit_clear(bitmap, bit) arch_bit_clear(bitmap, bit) +#endif /* ARCH_BIT_CLEAR */ + +/** + * @fn static inline void bit_toggle(void *bitmap, int bit) + * Toggle bit @a bit in the bitmap @a bitmap. + * @note The limit of @a bitmap = sizeof(unsigned long) + * + * @param[out] bitmap - A pointer to the bitmap. + * @param bit - Number of bit to toggle + */ +#ifndef ARCH_BIT_TOGGLE +static inline void bit_toggle(void *bitmap, int bit) +{ + *(unsigned long *)bitmap ^= (1 << bit); +} +#else +#define bit_toggle(bitmap, bit) arch_bit_toggle(bitmap, bit) +#endif /* ARCH_BIT_TOGGLE */ + +/** + * @fn static inline int bit_test(void *bitmap, int bitno) + * Test if bit with number @a bitno is set in the bitmap @a bitmap. + * @note The limit of @a bitmap = sizeof(unsigned long) + * + * @param bitmap - A pointer to the bitmap. + * @param bitno - Number of bit to test + * @return 1 if bit is set and 0 otherwise + */ +#ifndef ARCH_BIT_TEST +static inline int bit_test(void *bitmap, int bitno) +{ + return ((*(unsigned long *)bitmap & (1 << bitno)) >> bitno); +} +#else +#define bit_test(bitmap, bitno) arch_bit_test(bitmap, bitno) +#endif /* ARCH_BIT_TEST */ + +/** + * @fn static inline int bit_test_and_set(void *bitmap, int bitno) + * @brief Get old value of bit with number @a bitno and set @a bitno bit in the bitmap + * + * This function is similar to bit_set() except it copies old bit value before + * setting it to 1 and return that value after needed bit was setted. + * @note The limit of @a bitmap = sizeof(unsigned long) + * + * @param bitmap - A pointer to the bitmap + * @param bitno - The number of bit to test and set + * @return Old value of bit with number @a bitno + */ +#ifndef ARCH_BIT_TEST_AND_SET +static inline int bit_test_and_set(void *bitmap, int bitno) +{ + int val = (*(unsigned long *)bitmap & (1 << bitno)); + *(unsigned long *)bitmap |= (1 << bitno); + + return val; +} +#else +#define bit_test_and_set(bitmap, bitno) arch_bit_test_and_set(bitmap, bitno) +#endif /* ARCH_BIT_TEST_AND_SET */ + +/** + * @fn static inline int bit_test_and_reset(void *bitmap, int bitno) + * @brief Get old value of bit with number @a bitno and clear @a bitno bit in the bitmap + * + * This function is similar to bit_clear() except it copies old bit value before + * setting it to 1 and return that value after needed bit was setted. + * @note The limit of @a bitmap = sizeof(unsigned long) + * + * @param bitmap - A pointer to the bitmap + * @param bitno - The number of bit to test and set + * @return Old value of bit with number @a bitno + */ +#ifndef ARCH_BIT_TEST_AND_RESET +static inline int bit_test_and_reset(void *bitmap, int bitno) +{ + int val = (*(unsigned long *)bitmap & (1 << bitno)); + *(unsigned long *)bitmap &= ~(1 << bitno); + + return val; +} +#else +#define bit_test_and_reset(bitmap, bitno) arch_bit_test_and_reset(bitmap, bitno) +#endif /* ARCH_BIT_TEST_AND_RESET */ + +/** + * @fn static inline long bit_find_lsf(unsigned long word) + * Find first set least significant bit. + * + * @param word - Where to search + * @return Found bit number on success, negative value on failure. + */ +#ifndef ARCH_BIT_FIND_LSF +static inline long bit_find_lsf(unsigned long word) +{ + long c = -1; + + for (; word; c++, word >>= 1) { + if ((word & 0x01)) { + c++; + break; + } + } + + return c; +} +#else +#define bit_find_lsf(word) arch_bit_find_lsf(word) +#endif /* ARCH_BIT_FIND_LSF */ + +#ifndef ARCH_ZERO_BIT_FIND_LSF +#define zero_bit_find_lsf(word) bit_find_lsf(~(word)) +#else +#define zero_bit_find_lsf(word) arch_zero_bit_find_lsf(word) +#endif + +/** + * @fn static inline long bit_find_msf(unsigned long word) + * Find most significant set bit in the @a word. + * + * @param word - Where to search. + * @return Found bit number on success, negative value on failure. + */ +#ifndef ARCH_BIT_FIND_MSF +static inline long bit_find_msf(unsigned long word) +{ + long c = -1; + + while (word) { + c++; + word >>= 1; + } + + return c; +} +#else +#define bit_find_msf(word) arch_bit_find_msf(word) +#endif /* ARCH_BIT_FIND_MSF */ + +/** + * @fn static inline long bit_find_lsfz(unsigned long word) + * Find first zero least significant bit. + * + * @param word - Where to search + * @return Found bit number on success, negative value on failure. + */ +#ifndef ARCH_BIT_FIND_LSFZ +static inline long bit_find_lsfz(unsigned long word) +{ + long c = -1; + + word = ~word; + + for (; word; c++, word >>= 1) { + if ((word & 0x01)) { + c++; + break; + } + } + + return c; +} +#else +#define bit_find_lsfz(word) arch_bit_find_lsfz(word) +#endif /* ARCH_BIT_FIND_LSFZ */ + +/** + * @fn static inline long bit_find_msfz(unsigned long word) + * Find most significant zero bit in the @a word. + * + * @param word - Where to search. + * @return Found bit number on success, negative value on failure. + */ +#ifndef ARCH_BIT_FIND_MSFZ +static inline long bit_find_msfz(unsigned long word) +{ + long c = -1; + + word = ~word; + + while (word) { + c++; + word >>= 1; + } + + return c; +} +#else +#define bit_find_msfz(word) arch_bit_find_msfz(word) +#endif /* ARCH_BIT_FIND_MSFZ */ + +/** + * @fn static inline void bits_or(void *word, unsigned long flags) + * Executes logical OR with @a word and @a flags and writes result to @a word + * @note The limit of @a word = sizeof(unsigned long) + * + * @param[out] word - A pointer to memory results will be written to + * @param flsgs - Flags that will be OR'ed with @a word + */ +#ifndef ARCH_BITS_OR +static inline void bits_or(void *word, unsigned long flags) +{ + *(unsigned long *)word |= flags; +} +#define bits_or(word, flags) panic("bits_or uniplemented") +#else +#define bits_or(word, flags) arch_bits_or(word, flags) +#endif /* ARCH_BITS_OR */ + +/** + * @fn static inline void bits_and(void *word, unsigned long mask) + * Executes logical AND with @a word and @a mask and writes result to @a word. + * @note The limit of @a word = sizeof(unsigned long) + * + * @param[out] word - A pointer to memory results will be written to + * @param mask - A mask that will be AND'ed with @a word + */ +#ifndef ARCH_BITS_AND +static inline void bits_and(void *word, unsigned long mask) +{ + *(unsigned long *)word &= mask; +} +#else +#define bits_and(word, mask) arch_bits_and(word, mask) +#endif /* ARCH_BITS_AND */ + + +/* + * Initialize multiword bitmap + * + * @param map - pointer to the multiword bitmap + * @param bitno - memory size in bits to allocate + * + * @return 0 on success, -1 if can't allocate memory + */ +int init_bitmap(bitmap_t *bitmap, int nbits); + +/* + * Free memory taken by multiword bitmap + * + * @param bitmap - bitmap to free + */ +void free_bitmap(bitmap_t *map); + +/** + * Set bit number @a bit in the bitmap @a bitmap + * + * @param bitmap - A pointer to the bitmap + * @param bit - Number of bit to set + */ +void bit_set_multi(bitmap_t *bitmap, int bitno); + +/** + * test bit of a multiword bitmap + * + * @param bitmap - A pointer to the bitmap + * @param bitno - The number of bit to test + * + * @return value of the specified bit + */ +int bit_test_multi(bitmap_t *bitmap, int bitno); + +/** + * @brief Get old value of bit with number @a bitno and set @a bitno bit in the bitmap + * + * This function is similar to bit_set() except it copies old bit value before + * setting it to 1 and return that value after needed bit was setted. + * + * @param bitmap - A pointer to the bitmap + * @param bitno - The number of bit to test and set + * + * @return Old value of bit with number @a bitno or -1 if bitno is illegal + */ +int bit_test_and_set_multi(bitmap_t *bitmap, int bitno); + +/** + * @brief Get old value of bit with number @a bitno and clear @a bitno bit in the bitmap + * + * This function is similar to bit_set() except it copies old bit value before + * setting it to 1 and return that value after needed bit was setted. + * + * @param bitmap - A pointer to the bitmap + * @param bitno - The number of bit to test and set + * + * @return Old value of bit with number @a bitno or -1 if bitno is illegal + */ +int bit_test_and_reset_multi(bitmap_t *bitmap, int bitno); + + +/** + * Clear bit number @a bit in the bitmap @a bitmap + * + * @param bitmap - A pointer to the bitmap + * @param bit - Number of bit to clear + */ +void bit_clear_multi(bitmap_t *bitmap, int bitno); + +/* + * Set multiple bits in the multiword bitmap + * + * @param bitmap - pointer to the multimap bitmap + * @param start_bit - bit to set from + * int end_bit - bit to set upto + */ +void bitrange_set_multi(bitmap_t *bitmap, int start_bit, int end_bit); + +/* + * Clear multiple bits in the multiword bitmap + * + * @param bitmap - pointer to the multimap bitmap + * @param start_bit - bit to clear from + * int end_bit - bit to clear upto + */ +void bitrange_clear_multi(bitmap_t *bitmap, int start_bit, int end_bit); + +/** + * Find most significant set bit in multimap word which from the 0 bit + * upto @end_bit + * + * @param word - Where to search. + * @param end_bit - most bit to search upto + * @return Found bit number on success, negative value on failure. + */ +int bit_find_msf_multi(bitmap_t *bitmap, int mbit); + +/** + * Find first set least significant bit. + * + * @param word - Where to search + * @param sbit - least bit to search from + * @return Found bit number on success, negative value on failure. + */ +int bit_find_lsf_multi(bitmap_t *bitmap, int lbit); + +#ifndef ARCH_BIT_TEST_AND_CLEAR +static inline int bit_test_and_clear(void *bitmap, int bitno) +{ + int val = bit_test(bitmap, bitno); + bit_clear(bitmap, bitno); + return val; +} +#else +#define bit_test_and_clear(bitmap, bitno) arch_bit_test_and_clear(bitmap, bitno) +#endif + +#endif /* __BITWISE_H__ */ diff --git a/include/tdata/idx_allocator.h b/include/tdata/idx_allocator.h new file mode 100644 index 0000000..da64b8b --- /dev/null +++ b/include/tdata/idx_allocator.h @@ -0,0 +1,130 @@ +/* + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * (c) Copyright 2006,2007,2008 MString Core Team + * (c) Copyright 2009 Dan Kruchinin + * (c) Copyright 2009 Alfeiks Kaanoken (libc adaptation) + * (c) Copyright 2009 Dmitry Gromada (locking added) + * (c) Copyright 2013 Alexander Vdolainen (verios changes to make it run on linux) + * + * (c) Copyright 2012 - 2013 Askele Oy + * + * Index allocator + * + */ + +/** + * @file include/libdata/idx_allocator.h + * @brief Index allocator API and definitions + * + * Index allocator is a quite simple bitmaps based data + * structure allowing to allocate non-negative integers + * from an ordered continuous numbers set. + * It may be useful for dynamic allocation of pids, uids and + * other identifiers that must be unique. + * Any identifier from a given set may be allocated, deallocated and reserved + * (which prevents its allocation). + * Note, there is no any sence to use index allocator for relatively + * small(for example for sets containing less than 1024 items) identifier sets. + * Allocator uses *at least* BYTES_PER_ITEM + sizeof(ulong_t) bytes for its internal bitmaps. + */ + +#ifndef __IDX_ALLOCATOR_H__ +#define __IDX_ALLOCATOR_H__ + +#include +#include + +typedef unsigned long ulong_t; + +#define BYTES_PER_ITEM 64 /**< Number of bytes per one entry of a second-level bitmap */ +#define WORDS_PER_ITEM (BYTES_PER_ITEM / sizeof(ulong_t)) /**< Number of machine words(ulong_t) per second-level bitmap item */ +#define IDX_INVAL ~0UL /**< Invalid index value */ + +#define ida_lock_init(lock) pthread_mutex_init(lock, NULL) +#define ida_lock_destroy(lock) pthread_mutex_destroy(lock); +#define ida_lock(a) pthread_mutex_lock(&a->lock) +#define ida_unlock(a) pthread_mutex_unlock(&a->lock) +#define ida_lockable(a) (a->lck) + +typedef pthread_mutex_t ida_lock_t; + +/** + * @struct idx_allocator_t + * @brief Index allocator structure + */ +typedef struct __idx_allocator { + int size; /**< Total number of words used for second-level bitmap */ + ulong_t max_id; /**< Maximum index value(exclusive) */ + ulong_t *main_bmap; /**< First-level(main) bitmap that splits second-level bitmap on several parts */ + ulong_t *ids_bmap; /**< Second-level bitmap whose each bit corresponds to particular unique identifier */ + ida_lock_t lock; + int lck; +} idx_allocator_t; + +#define idx_allocator_initialized(ida) (((idx_allocator_t*)(ida))->max_id) + +/** + * @brief Initialize an index allocator. + * @param ida - A pointer to particular index allocator + * @param idx_max - Maximum index value. + * @lockable - flag to indicate the allocator must support locking itself + */ +int idx_allocator_init(idx_allocator_t *ida, ulong_t idx_max, int lockable); + +/** + * @brief Destroy index allocator. + * + * This function frees space used by allocator's internal + * bitmaps. After it is called, allocator can not be used. + * + * @param ida - A pointer to praticular index allocator. + */ +void idx_allocator_destroy(idx_allocator_t *ida); + +/** + * @brief Allocate new index from an allocator's set. + * @param ida - A pointer to target index allocator. + * @return Valid index value on success, IDX_INVAL on error. + * @see IDX_INVAL + * @see idx_reserve + * @see idx_free + */ +ulong_t idx_allocate(idx_allocator_t *ida); + +/** + * @brief Reserves particular index number. + * + * This action prevents named index number from + * allocation. Index allocator skips reserved indices until + * they are fried with idx_free + * + * @param ida - A pointer to particular index allocator. + * @param idx - Number of index to reserve. + * @see idx_free + * @see idx_allocate + */ +void idx_reserve(idx_allocator_t *ida, ulong_t idx); + +/** + * @brief Free back index @a idx to named allocator @a ida. + * @param ida - Allocator index will be freed back to. + * @param idx - An index to free. + * @see idx_allocate + * @see idx_reserve + */ +void idx_free(idx_allocator_t *ida, ulong_t idx); + +#endif /* __IDX_ALLOCATOR_H__ */ diff --git a/include/tdata/macro.h b/include/tdata/macro.h new file mode 100644 index 0000000..b8cc2ab --- /dev/null +++ b/include/tdata/macro.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * macro.h + * Copyright (C) 2006-2013 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#ifndef __MACRO_H__ +#define __MACRO_H__ + +/*this macros just for better source code look and feel*/ + +#define left usrtc_left +#define right usrtc_right +#define parent usrtc_parent +#define next usrtc_right +#define prev usrtc_left +#define data usrtc_data +#define key usrtc_node_key +#define rb_color usrtc_rb_color +#define impl_specific usrtc_impldata + +#define futable usrtc_futable +#define nodecount usrtc_nodecount +#define maxcount usrtc_maxcount +#define dupes_allowed usrtc_dupes_allowed +#define sentinel usrtc_sentinel +#define compare usrtc_compare +#define node_alloc usrtc_node_alloc +#define node_free usrtc_node_free +#define context usrtc_context + +#endif /*__MACRO_H__*/ diff --git a/include/tdata/tree.h b/include/tdata/tree.h new file mode 100644 index 0000000..1e8d897 --- /dev/null +++ b/include/tdata/tree.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * tree.h + * Copyright (C) 2006-2013 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#ifndef __TREE_H__ +#define __TREE_H__ + +#include + +#define tree_root_priv(T) ((T)->sentinel.left) +#define tree_null_priv(L) (&(L)->sentinel) +#define TREE_DEPTH_MAX 64 + +/*tree functions*/ +void usrtc_tree_init(usrtc_t *us); +void usrtc_tree_insert(usrtc_t *us, usrtc_node_t *node, const void *key); +void usrtc_tree_delete(usrtc_t *us, usrtc_node_t *node, usrtc_node_t **pswap, + usrtc_node_t **pchild); +usrtc_node_t *usrtc_tree_lookup(usrtc_t *us, const void *key); +usrtc_node_t *usrtc_tree_lower_bound(usrtc_t *us, const void *key); +usrtc_node_t *usrtc_tree_upper_bound(usrtc_t *us, const void *key); +usrtc_node_t *usrtc_tree_first(usrtc_t *us); +usrtc_node_t *usrtc_tree_last(usrtc_t *us); +usrtc_node_t *usrtc_tree_next(usrtc_t *us, usrtc_node_t *curr); +usrtc_node_t *usrtc_tree_prev(usrtc_t *us, usrtc_node_t *curr); +void usrtc_tree_convert_to_list(usrtc_t *us); +void usrtc_tree_convert_from_list(usrtc_t *us); +void usrtc_tree_rotate_left(usrtc_node_t *child, usrtc_node_t *parent); +void usrtc_tree_rotate_right(usrtc_node_t *child, usrtc_node_t *parent); + + +#endif /*__TREE_H__*/ diff --git a/include/tdata/usrtc.h b/include/tdata/usrtc.h new file mode 100644 index 0000000..9d2a35c --- /dev/null +++ b/include/tdata/usrtc.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * usrtc.h + * Copyright (C) 2006-2013 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#ifndef __USRTC_H__ +#define __USRTC_H__ + +#define USRTC_COUNT_T_MAX ((1 << (sizeof(unsigned long)*(sizeof(char) << 1)))-1) + +/*count and some misc typedefs*/ +typedef unsigned long usrtc_count_t; +typedef unsigned int usrtc_impl_id_t; + +/* implementations ids, + * if you want to add some + * add the id here, don't forget to do it. + */ +#define USRTC_LIST 0 +#define USRTC_BST 1 +#define USRTC_REDBLACK 2 +#define USRTC_SPLAY 3 +#define USRTC_AVL 4 + +typedef enum { + usrtc_lst, + usrtc_bst, + usrtc_other +} usrtc_impltype_t; + +typedef enum { + usrtc_red, + usrtc_black +} usrtc_rb_color_t; +typedef enum { + usrtc_balanced, + usrtc_leftheavy, + usrtc_rightheavy +} usrtc_avl_balance_t; + +/*used for the specific implementation features*/ +typedef union { + int usrtc_dummy; + usrtc_rb_color_t usrtc_rb_color; + usrtc_avl_balance_t usrtc_avl_balance; +} usrtc_impldata_t; + +/*universal node*/ +typedef struct __usrtc_node_t { + struct __usrtc_node_t *usrtc_left; + struct __usrtc_node_t *usrtc_right; + struct __usrtc_node_t *usrtc_parent; + void *usrtc_data; + const void *usrtc_node_key; + usrtc_impldata_t usrtc_impldata; +} usrtc_node_t; + +typedef long (*usrtc_compare_t)(const void*, const void*); +typedef usrtc_node_t *(*usrtc_node_alloc_t)(void *); +typedef void (*usrtc_node_free_t)(void *, usrtc_node_t *); + +typedef struct __usrtc_t { + struct __usrtc_functions_t *usrtc_futable; + usrtc_count_t usrtc_nodecount; + usrtc_count_t usrtc_maxcount; + int usrtc_dupes_allowed; + usrtc_node_t usrtc_sentinel; + usrtc_compare_t usrtc_compare; + usrtc_node_alloc_t usrtc_node_alloc; + usrtc_node_free_t usrtc_node_free; + void *usrtc_context; +} usrtc_t; + +typedef struct __usrtc_functions_t { + void (*usrtc_init)(usrtc_t *); + void (*usrtc_insert)(usrtc_t *, usrtc_node_t *, const void *); + void (*usrtc_delete)(usrtc_t *, usrtc_node_t *); + usrtc_node_t *(*usrtc_lookup)(usrtc_t *, const void *); + usrtc_node_t *(*usrtc_lower_bound)(usrtc_t *, const void *); + usrtc_node_t *(*usrtc_upper_bound)(usrtc_t *, const void *); + usrtc_node_t *(*usrtc_first)(usrtc_t *); + usrtc_node_t *(*usrtc_last)(usrtc_t *); + usrtc_node_t *(*usrtc_next)(usrtc_t *, usrtc_node_t *); + usrtc_node_t *(*usrtc_prev)(usrtc_t *, usrtc_node_t *); + void (*usrtc_convert_to_list)(usrtc_t *); + void (*usrtc_convert_from_list)(usrtc_t *); + usrtc_impltype_t usrtc_type; +} usrtc_functions_t; + +/*basic rtc functions*/ +void usrtc_init(usrtc_t *us,int impl,usrtc_count_t maxcount,usrtc_compare_t compare); +usrtc_t *usrtc_create(int impl,usrtc_count_t maxcount,usrtc_compare_t compare); +void usrtc_destroy(usrtc_t *us); +void usrtc_convert_to(usrtc_t *us,int impl); +usrtc_count_t usrtc_count(usrtc_t *us); +int usrtc_isempty(usrtc_t *us); +int usrtc_isfull(usrtc_t *us); +int usrtc_alloc_insert(usrtc_t *us,const void *key,void *data); +void usrtc_delete_free(usrtc_t *us,usrtc_node_t *node); +void usrtc_set_allocator(usrtc_t *us,usrtc_node_alloc_t alloc,usrtc_node_free_t n_free,void *context); +void usrtc_allow_dupes(usrtc_t *ud); + +/*basic node functions*/ +void usrtc_node_init(usrtc_node_t *node,void *data); +usrtc_node_t *usrtc_node_create(void *data); +void usrtc_node_destroy(usrtc_node_t *node); +void *usrtc_node_getdata(usrtc_node_t *node); +void usrtc_node_setdata(usrtc_node_t *node,void *data); +const void *usrtc_node_getkey(usrtc_node_t *node); + +/*rtc wrappers for the specific data structure functions*/ +void usrtc_insert(usrtc_t *us,usrtc_node_t *node,const void *key); +void usrtc_delete(usrtc_t *us,usrtc_node_t *node); +usrtc_node_t *usrtc_lookup(usrtc_t *us,const void *key); +usrtc_node_t *usrtc_lower_bound(usrtc_t *us,const void *key); +usrtc_node_t *usrtc_upper_bound(usrtc_t *us,const void *key); +usrtc_node_t *usrtc_first(usrtc_t *us); +usrtc_node_t *usrtc_last(usrtc_t *us); +usrtc_node_t *usrtc_next(usrtc_t *us,usrtc_node_t *node); +usrtc_node_t *usrtc_prev(usrtc_t *us,usrtc_node_t *node); + +#endif /*__USRTC_H__*/ diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..2e4eca1 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,33 @@ +## Process this file with automake to produce Makefile.in + +AM_CPPFLAGS = \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \ + $(LIBTDATA_CFLAGS) -I../include + +AM_CFLAGS =\ + -Wall\ + -g + +lib_LTLIBRARIES = libtdata.la + + +libtdata_la_SOURCES = \ + avl.c lslist.c redblack.c splay.c \ + tree.c usrtc.c bitwise.c idx_allocator.c + +libtdata_la_LDFLAGS = + +libtdata_la_LIBADD = + +##include_HEADERS = \ +## ../include/tdata/macro.h ../include/tdata/tree.h ../include/tdata/usrtc.h \ +## ../include/tdata/bitwise.h ../include/tdata/idx_allocator.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libtdata-0.2.pc + +EXTRA_DIST = \ + libtdata-0.2.pc.in + diff --git a/lib/avl.c b/lib/avl.c new file mode 100644 index 0000000..5771ca6 --- /dev/null +++ b/lib/avl.c @@ -0,0 +1,327 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * avl.c + * Copyright (C) 2006-2013, 2014 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#include +#include +#include + +#define balance usrtc_impldata.usrtc_avl_balance +#define BALANCED usrtc_balanced +#define LEFTHEAVY usrtc_leftheavy +#define RIGHTHEAVY usrtc_rightheavy + +/*local functions prototypes*/ +static void avl_init(usrtc_t *); +static void avl_insert(usrtc_t *,usrtc_node_t *,const void *); +static void avl_delete(usrtc_t *,usrtc_node_t *); +static void avl_convert_from_list(usrtc_t *); + +usrtc_functions_t usrtc_avl_fu = { + avl_init, + avl_insert, + avl_delete, + usrtc_tree_lookup, + usrtc_tree_lower_bound, + usrtc_tree_upper_bound, + usrtc_tree_first, + usrtc_tree_last, + usrtc_tree_next, + usrtc_tree_prev, + usrtc_tree_convert_to_list, + avl_convert_from_list, + usrtc_bst +}; + +/*internal use*/ +static void rotate_left(usrtc_node_t **); +static void rotate_right(usrtc_node_t **); +static void fix_balance(usrtc_node_t **,usrtc_avl_balance_t ); +static int insert(usrtc_t *,usrtc_node_t *,usrtc_node_t **,usrtc_node_t *); +static usrtc_node_t *make_tree(usrtc_node_t **,usrtc_count_t ,int *,usrtc_node_t *); + +/*implementation*/ +static void avl_init(usrtc_t *us) +{ + usrtc_tree_init(us); + us->sentinel.balance=BALANCED; +} + +static void avl_insert(usrtc_t *us,usrtc_node_t *node,const void *key) +{ + usrtc_node_t *nil=tree_null_priv(us); + + node->key=key; + node->left=nil; + node->right=nil; + node->balance=BALANCED; + + if(insert(us,node,&nil->left,nil)) { + nil->balance=LEFTHEAVY; + } + + us->nodecount++; +} + +static void avl_delete(usrtc_t *us,usrtc_node_t *node) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *swap; + usrtc_node_t *child; + usrtc_node_t *parent; + + /*basic deletion*/ + usrtc_tree_delete(us,node,&swap,&child); + + /*implementation specific*/ + swap->balance=node->balance; + parent=child->parent; + + if(parent==nil) { + if(child==nil) { + parent->balance=BALANCED; + } + } + + while(parent!=nil) { + if((parent->left==nil) && (parent->right==nil)) { + if(child!=nil) + return; + if(parent==BALANCED) + return; + parent->balance=BALANCED; + } + else { + usrtc_node_t **pparent; + if(parent==parent->parent->left) + pparent=&parent->parent->left; + else + pparent=&parent->parent->right; + + if(child==parent->left) + fix_balance(pparent,RIGHTHEAVY); + else { + if(child!=parent->right) + return; + + fix_balance(pparent,LEFTHEAVY); + } + + parent=*pparent; + } + + if(parent->balance==BALANCED) { + child=parent; + parent=child->parent; + } + else + break; + } +} + +static void avl_convert_from_list(usrtc_t *us) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *root; + int height; + + if(us->nodecount==0) { + nil->balance=BALANCED; + return; + } + + root=make_tree(&nil->next,us->nodecount,&height,nil); + + if(nil->next!=nil) + return; + + nil->left=root; + root->parent=nil; + nil->balance=LEFTHEAVY; +} + +/*---*/ +static void rotate_left(usrtc_node_t **top) +{ + usrtc_node_t *parent=*top; + usrtc_node_t *child=parent->right; + + child->parent=parent->parent; + parent->right=child->left; + parent->right->parent=parent; + child->left=parent; + parent->parent=child; + *top=child; +} + +static void rotate_right(usrtc_node_t **top) +{ + usrtc_node_t *parent=*top; + usrtc_node_t *child=parent->left; + + child->parent=parent->parent; + parent->left=child->right; + parent->left->parent=parent; + child->right=parent; + parent->parent=child; + *top=child; +} + +static void fix_balance(usrtc_node_t **pnode,usrtc_avl_balance_t bal) +{ + usrtc_node_t *node=*pnode; + usrtc_node_t *child; + usrtc_node_t *grandchild; + + if(node->balance==BALANCED) + node->balance=bal; + else if(node->balance!=bal) + node->balance=BALANCED; + else { + if(node->balance!=bal) + return; + + if(bal==LEFTHEAVY) { + child=node->left; + if(child->balance==LEFTHEAVY) { + node->balance=BALANCED; + child->balance=BALANCED; + rotate_right(pnode); + } + else if(child->balance==BALANCED) { + node->balance=LEFTHEAVY; + child->balance=RIGHTHEAVY; + rotate_right(pnode); + } + else { + grandchild=child->right; + if(grandchild->balance==LEFTHEAVY) { + node->balance=RIGHTHEAVY; + child->balance=BALANCED; + } + else if(grandchild->balance==RIGHTHEAVY) { + node->balance=BALANCED; + child->balance=LEFTHEAVY; + } + else { + node->balance=BALANCED; + child->balance=BALANCED; + } + grandchild->balance=BALANCED; + rotate_left(&node->left); + rotate_right(pnode); + } + } + else { + child=node->right; + if(child->balance==RIGHTHEAVY) { + node->balance=BALANCED; + child->balance=BALANCED; + rotate_left(pnode); + } + else if(child->balance==BALANCED) { + node->balance=RIGHTHEAVY; + child->balance=LEFTHEAVY; + rotate_left(pnode); + } + else { + grandchild=child->left; + if(grandchild->balance==RIGHTHEAVY) { + node->balance=LEFTHEAVY; + child->balance=BALANCED; + } + else if(grandchild->balance==LEFTHEAVY) { + node->balance=BALANCED; + child->balance=RIGHTHEAVY; + } + else { + node->balance=BALANCED; + child->balance=BALANCED; + } + grandchild->balance=BALANCED; + rotate_right(&node->right); + rotate_left(pnode); + } + } + } +} + +static int insert(usrtc_t *us,usrtc_node_t *what,usrtc_node_t **where,usrtc_node_t *parent) +{ + usrtc_node_t *here=*where; + int result; + + if(here==tree_null_priv(us)) { + *where=what; + what->parent=parent; + return 1; + } + else { + result=us->compare(what->key,here->key); + + if(result < 0) { + if(insert(us,what,&here->left,here)) { + fix_balance(where,LEFTHEAVY); + return ((*where)->balance!=BALANCED); + } + } + else { + if(insert(us,what,&here->right,here)) { + fix_balance(where,RIGHTHEAVY); + return ((*where)->balance!=BALANCED); + } + } + } + return 0; +} + +static usrtc_node_t *make_tree(usrtc_node_t **pnode,usrtc_count_t count, + int *pheight,usrtc_node_t *nil) +{ + usrtc_count_t leftcount; + int leftheight, rightheight; + usrtc_node_t *root; + usrtc_node_t *leftroot; + + if(count==0) { + *pheight=0; + return nil; + } + + leftcount=(count-1)/2; + leftroot=make_tree(pnode,leftcount,&leftheight,nil); + count-=leftcount; + + root=*pnode; + *pnode=root->next; + --count; + + root->left=leftroot; + leftroot->parent=root; + root->right=make_tree(pnode,count,&rightheight,nil); + root->right->parent=root; + + if(leftheight>rightheight) + return (void *)0; + + *pheight=rightheight+1; + root->balance=(leftheight==rightheight) ? BALANCED : RIGHTHEAVY; + + return root; +} + diff --git a/lib/bitwise.c b/lib/bitwise.c new file mode 100644 index 0000000..2966b50 --- /dev/null +++ b/lib/bitwise.c @@ -0,0 +1,201 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * (c) Copyright 2006,2007,2008 Jari OS Core Team + * (c) Copyright 2008 Dmitry Gromada + * (c) Copyright 2010 Alexander Vdolainen + * + * (c) Copyright 2012 - 2013, 2014 Askele Oy + * + * Implements bitwise operations with multiword bitmaps + */ + +#include +#include +#include +#include +#include + +/* operation equivalent to division modulo number of power 2 */ +#define MOD_POW2(var, pow) ((var) & ((pow) - 1)) + +int init_bitmap(bitmap_t *bitmap, int nbits) +{ + int ret = 0; + int size = nbits >> TYPE_LONG_SHIFT; + + if (nbits < 0) + return -1; + + if (size << TYPE_LONG_SHIFT != nbits) + size++; + + bitmap->map = (unsigned long*)malloc(size * sizeof(unsigned long)); + if (bitmap->map == NULL) + ret = -1; + else + bitmap->nwords = size; + + memset(bitmap->map, 0, size * sizeof(unsigned long)); + + return ret; +} + + +void free_bitmap(bitmap_t *bitmap) +{ + if (bitmap->map) { + free(bitmap->map); + bitmap->map = NULL; + } + bitmap->nwords = 0; +} + + +void bit_set_multi(bitmap_t *bitmap, int bitno) +{ + int i = bitno >> TYPE_LONG_SHIFT; + + return bit_set( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); +} + +int bit_test_and_set_multi(bitmap_t *bitmap, int bitno) +{ + int i = bitno >> TYPE_LONG_SHIFT; + + return bit_test_and_set( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); +} + +int bit_test_and_reset_multi(bitmap_t *bitmap, int bitno) +{ + int i = bitno >> TYPE_LONG_SHIFT; + + return bit_test_and_reset( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); +} + +void bit_clear_multi(bitmap_t *bitmap, int bitno) +{ + int i = bitno >> TYPE_LONG_SHIFT; + + return bit_clear( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); +} + +int bit_find_msf_multi(bitmap_t *bitmap, int mbit) +{ + int i, r; + unsigned long word; + + if (mbit < 0) + return -1; + else if (mbit >= bitmap->nwords * BITS_PER_LONG) + mbit = bitmap->nwords * BITS_PER_LONG - 1; + + i = mbit >> TYPE_LONG_SHIFT; + word = bitmap->map[i] & (~0UL >> ( BITS_PER_LONG - 1 - MOD_POW2(mbit, BITS_PER_LONG) )); + r = bit_find_msf(word); + + while ((r == -1) && (--i >= 0)) { + if (bitmap->map[i]) + r = bit_find_msf(bitmap->map[i]); + } + + r = (r == -1) ? r : (i * BITS_PER_LONG + r); + + return r; +} + +int bit_find_lsf_multi(bitmap_t *bitmap, int lbit) +{ + int i, r; + unsigned long word; + + if (lbit >= bitmap->nwords * BITS_PER_LONG) + return -1; + else if (lbit < 0) + lbit = 0; + + i = lbit >> TYPE_LONG_SHIFT; + word = bitmap->map[i] & (~0UL << MOD_POW2(lbit, BITS_PER_LONG)); + r = bit_find_lsf(word); + + while ((r == -1) && (++i < bitmap->nwords)) { + if (bitmap->map[i]) + r = bit_find_lsf(bitmap->map[i]); + } + + r = (r == -1) ? r : (i * BITS_PER_LONG + r); + + return r; +} + +int bit_test_multi(bitmap_t *bitmap, int bitno) +{ + int i = bitno >> TYPE_LONG_SHIFT; + + return bit_test( bitmap->map + i, MOD_POW2(bitno, BITS_PER_LONG) ); +} + +void bitrange_set_multi(bitmap_t *bitmap, int start_bit, int end_bit) +{ + int i1, i2; + unsigned long mask1, mask2, *p = bitmap->map; + + if (start_bit > end_bit) + return; + + i1 = start_bit >> TYPE_LONG_SHIFT; + mask1 = ~0UL << MOD_POW2(start_bit, BITS_PER_LONG); + + i2 = end_bit >> TYPE_LONG_SHIFT; + mask2 = ~0UL >> (BITS_PER_LONG - 1 - MOD_POW2(end_bit, BITS_PER_LONG)); + + if (i1 == i2) + p[i1] |= mask1 & mask2; + else { + p[i1++] |= mask1; + + if (i2 - i1 > 0) + memset( p + i1, 0xFF, (i2 - i1) * sizeof(unsigned long) ); + + p[i2] |= mask2; + } +} + +void bitrange_clear_multi(bitmap_t *bitmap, int start_bit, int end_bit) +{ + int i1, i2; + unsigned long mask1, mask2, *p = bitmap->map; + + if (start_bit > end_bit) + return; + + i1 = start_bit >> TYPE_LONG_SHIFT; + mask1 = ( 1UL << (start_bit & MOD_POW2(start_bit, BITS_PER_LONG)) ) - 1; + + i2 = end_bit >> TYPE_LONG_SHIFT; + mask2 = ~0UL << (MOD_POW2(end_bit, BITS_PER_LONG) + 1); + + if (i1 == i2) + p[i1] &= mask1 | mask2; + else { + p[i1++] &= mask1; + + if (i2 - i1 > 0) + memset(p + i1, 0, (i2 - i1) * sizeof(unsigned long)); + + p[i2] &= mask2; + } +} diff --git a/lib/idx_allocator.c b/lib/idx_allocator.c new file mode 100644 index 0000000..0a57894 --- /dev/null +++ b/lib/idx_allocator.c @@ -0,0 +1,254 @@ +/* + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * (c) Copyright 2006,2007,2008 MString Core Team + * (c) Copyright 2009 Dan Kruchinin + * (c) Copyright 2009 Alexander Vdolainen (libc adaptation) + * (c) Copyright 2009 Dmitry Gromada (locking added) + * (c) Copyright 2013 Alexander Vdolainen (verios changes to make it run on linux) + * + * (c) Copyright 2012 - 2013, 2014 Askele Oy + * + * Index allocator + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Main idea of index allocator is quite simple: + * There is a group of tasks that requires dynamic allocation + * of unique non-negative integer identifiers. Where a set of such + * integers is relatively big (thousands of numbers), index allocator + * becomes a nifty solution. + * The core of allocator is two bitmaps. One of them called "indices bitmap" + * or "second level bitmap". Each bit of that bitmap corresponds to particular unique + * index. Since second-level bitmap is a large portion of continuous memory, searching + * of set/zero bit in it becomes relatively slow. For speeding-up search process we invented + * a first-level bitmap. Second-level array is splitted on groups each of them contains BYTES_PER_ITEM bytes. + * First-level(or main) bitmap establishes corresponding between particular group and its + * state(group may have free indices or not). + * So index allocation assumes at first searching of group index in a the first-level bitmap and only + * then searching an index in the second level bitmap starting from a group index. + */ + +#define MIN_IDA_SIZE (WORDS_PER_ITEM * sizeof(ulong_t)) +#define MAX_UNLOCKED_ATTEMPTS 3 + +/* there macros defined only on new glibc (from 12-jul-2013), let's use our own */ +#ifndef is_powerof2 +#define is_powerof2(num) (((num) & ~((num) - 1)) == (num)) +#endif +#ifndef round_up_pow2 +#define round_up_pow2(x) (!is_powerof2(x) ? (1 << (bit_find_msf(x) + 1)) : (x) ) +#endif + +static inline size_t __get_main_bmap_size(idx_allocator_t *ida) +{ + if (ida->ids_bmap != NULL) + return (round_up_pow2((ida->size * sizeof(ulong_t)) / BYTES_PER_ITEM)); + + return ida->size; +} + +ulong_t idx_allocate(idx_allocator_t *ida) +{ + ulong_t id = IDX_INVAL; + long fnfi = 0; + size_t i, main_offs = 0, main_sz; + int natm = 0; /* attempt number */ + + main_sz = __get_main_bmap_size(ida) / sizeof(ulong_t); + i = 0; + + if (ida->ids_bmap != NULL) { + for (;;) { + while (i < main_sz) { + fnfi = zero_bit_find_lsf(ida->main_bmap[i]); + if (fnfi >= 0) { + fnfi = (fnfi * WORDS_PER_ITEM) + i * WORDS_PER_ITEM * BITS_PER_LONG; + main_offs = i; + break; + } + + i++; + } + if ((fnfi >= 0) && (fnfi < ida->size)) { + int res_id, j, total_sz; + + total_sz = fnfi + WORDS_PER_ITEM; + j = fnfi; + while (j < total_sz) { + res_id = zero_bit_find_lsf(ida->ids_bmap[j]); + if (res_id < 0) { + j++; + continue; + } + + if (ida_lockable(ida) /*&& atomic_test_and_set_bit(ida->ids_bmap + j, res_id)*/) { + natm++; + if (natm == MAX_UNLOCKED_ATTEMPTS) + ida_lock(ida); + } else { + bit_set(ida->ids_bmap + j, res_id); + } + + id = res_id + j * BITS_PER_LONG; + if (id >= ida->max_id) { + bit_clear(ida->ids_bmap + j, res_id); + id = IDX_INVAL; + } + + goto out; + } + + bit_set(ida->main_bmap + main_offs, + (fnfi - (main_offs * WORDS_PER_ITEM * BITS_PER_LONG)) / WORDS_PER_ITEM); + if ((ida->main_bmap[i] & ~0UL) == ~0UL) + i++; + } + else + break; + } + } + else { + while (i < main_sz) { + fnfi = zero_bit_find_lsf(ida->main_bmap[i]); + if (fnfi >= 0) { + bit_set(ida->main_bmap + i, fnfi); + id = fnfi + i * BITS_PER_LONG; + if (id >= ida->max_id) { + bit_clear(ida->main_bmap + i, fnfi); + id = IDX_INVAL; + } + + break; + } + + i++; + } + } + + out: + if (natm == MAX_UNLOCKED_ATTEMPTS) + ida_unlock(ida); + + return id; +} + +void idx_reserve(idx_allocator_t *ida, ulong_t idx) +{ + int start_id, bitno; + ulong_t *ptr; + + start_id = idx / BITS_PER_LONG; + bitno = idx - start_id * BITS_PER_LONG; + if (ida->ids_bmap != NULL) + ptr = ida->ids_bmap + start_id; + else + ptr = ida->main_bmap + start_id; + + if (bit_test_and_set(ptr, bitno)) { + printf("[libc warning] Detected an attempt to reserve already busy index %ld " + "[function: %s]!\n", idx, __FUNCTION__); + } +} + +void idx_free(idx_allocator_t *ida, ulong_t idx) +{ + int start_id, bitno, main_id, main_bitno; + ulong_t *ptr; + + start_id = idx / BITS_PER_LONG; + bitno = idx - start_id * BITS_PER_LONG; + if (ida->ids_bmap != NULL) { + ptr = ida->ids_bmap + start_id; + main_id = start_id / WORDS_PER_ITEM; + main_bitno = start_id - main_id * WORDS_PER_ITEM; + bit_clear(ida->main_bmap + main_id, main_bitno); + } + else + ptr = ida->main_bmap + start_id; + + if (!bit_test_and_clear(ptr, bitno)) { + printf("[libc warning] Detected an attempt to free already fried index %ld " + "[function: %s]!\n", idx, __FUNCTION__); + } +} + +int idx_allocator_init(idx_allocator_t *ida, ulong_t idx_max, int lockable) +{ + size_t bmap_sz; + int err = -ENOMEM; + + bmap_sz = (round_up_pow2(idx_max) >> 3); + memset(ida, 0, sizeof(*ida)); + ida->size = bmap_sz / sizeof(ulong_t); + if (ida->size >= MIN_IDA_SIZE) { + ida->ids_bmap = malloc(bmap_sz); + if (!ida->ids_bmap) { + goto error; + } + + memset(ida->ids_bmap, 0, bmap_sz); + } + else + ida->size = (ida->size > 0) ? (ida->size * sizeof(ulong_t)) : sizeof(ulong_t); + + ida->main_bmap = malloc(__get_main_bmap_size(ida)); + if (!ida->main_bmap) { + goto error; + } + +#if 0 + if (lockable && ida_lock_init(&ida->lock)) + goto error; +#endif + ida->lck = 0; /* cutty, we don't use the lockable due to the very arch specifics */ + + memset(ida->main_bmap, 0, __get_main_bmap_size(ida)); + ida->max_id = idx_max; + return 0; + + error: + if (ida->ids_bmap) { + free(ida->ids_bmap); + } + if (ida->main_bmap) { + free(ida->main_bmap); + } + + return err; +} + +void idx_allocator_destroy(idx_allocator_t *ida) +{ + if (ida->ids_bmap != NULL) + free(ida->ids_bmap); + + free(ida->main_bmap); + + if (ida_lockable(ida)) + ida_lock_destroy(&ida->lock); +} + diff --git a/lib/libtdata-0.2.pc.in b/lib/libtdata-0.2.pc.in new file mode 100644 index 0000000..0467370 --- /dev/null +++ b/lib/libtdata-0.2.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +datarootdir=@datarootdir@ +datadir=@datadir@ +includedir=@includedir@ + +Name: liblibtdata +Description: Data structures used in a variety of Askele and Askele Ingria products (so called usrtc). +Version: @VERSION@ +Requires: +Libs: -L${libdir} -llibtdata +Cflags: -I${includedir} diff --git a/lib/lslist.c b/lib/lslist.c new file mode 100644 index 0000000..baeee9c --- /dev/null +++ b/lib/lslist.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * lslist.c + * Copyright (C) 2006-2013, 2014 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#include + +#include +#include + +#define list_first_priv(L) ((L)->sentinel.next) +#define list_last_priv(L) ((L)->sentinel.prev) +#define list_null_priv(L) (&(L)->sentinel) + +/*function prototypes*/ +static void list_init(usrtc_t *); +static void list_insert(usrtc_t *,usrtc_node_t *,const void *); +static void list_delete(usrtc_t *,usrtc_node_t *); +static usrtc_node_t *list_lookup(usrtc_t *,const void *); +static usrtc_node_t *list_lower_bound(usrtc_t *,const void *); +static usrtc_node_t *list_upper_bound(usrtc_t *,const void *); +static usrtc_node_t *list_first(usrtc_t *); +static usrtc_node_t *list_last(usrtc_t *); +static usrtc_node_t *list_next(usrtc_t *, usrtc_node_t *); +static usrtc_node_t *list_prev(usrtc_t *, usrtc_node_t *); +static void list_convert_to_list(usrtc_t *); +static void list_convert_from_list(usrtc_t *); + +usrtc_functions_t usrtc_list_fu = { + list_init, + list_insert, + list_delete, + list_lookup, + list_lower_bound, + list_upper_bound, + list_first, + list_last, + list_next, + list_prev, + list_convert_to_list, + list_convert_from_list, + usrtc_lst +}; + +static void insert_before(usrtc_t *,usrtc_node_t *,usrtc_node_t *); + +/*implementation*/ +static void list_init(usrtc_t *us) +{ + us->sentinel.next=&us->sentinel; + us->sentinel.prev=&us->sentinel; +} + +static void list_insert(usrtc_t *us,usrtc_node_t *newnode,const void *key) +{ + usrtc_node_t *succ; + + newnode->key=key; + + for(succ=list_first_priv(us);succ!=list_null_priv(us);succ=succ->next) { + if(us->compare(succ->key,key)>0) + break; + } + + insert_before(us,newnode,succ); +} + +static void list_delete(usrtc_t *us,usrtc_node_t *node) +{ + usrtc_node_t *pred=node->prev; + usrtc_node_t *succ=node->next; + + pred->next=succ; + succ->prev=pred; + /*check node count*/ + us->nodecount--; +} + +static usrtc_node_t *list_lookup(usrtc_t *us,const void *key) +{ + usrtc_node_t *node; + + for(node=list_first_priv(us);node!=list_null_priv(us);node=node->next) { + if(us->compare(node->key,key)==0) + return node; + } + + return NULL; +} + +static usrtc_node_t *list_lower_bound(usrtc_t *us,const void *key) +{ + usrtc_node_t *node; + + for(node=list_first_priv(us);node!=list_null_priv(us);node=node->next) { + if(us->compare(node->key,key) >= 0) + return node; + } + + return NULL; +} + +static usrtc_node_t *list_upper_bound(usrtc_t *us,const void *key) +{ + usrtc_node_t *node; + + for(node=list_first_priv(us);node!=list_null_priv(us);node=node->prev) { + if(us->compare(node->key,key) >= 0) + return node; + } + + return NULL; +} + +static usrtc_node_t *list_first(usrtc_t *us) +{ + return (list_first_priv(us) == list_null_priv(us)) ? 0 : list_first_priv(us); +} + +static usrtc_node_t *list_last(usrtc_t *us) +{ + return (list_last_priv(us) == list_null_priv(us)) ? 0 : list_last_priv(us); +} + +static usrtc_node_t *list_next(usrtc_t *us, usrtc_node_t *node) +{ + return (node->next == list_null_priv(us)) ? 0 : node->next; +} + +static usrtc_node_t *list_prev(usrtc_t *us, usrtc_node_t *node) +{ + return (node->prev == list_null_priv(us)) ? 0 : node->prev; +} + +static void list_convert_to_list(usrtc_t *us) +{ + /*dummy*/ +} + +static void list_convert_from_list(usrtc_t *us) +{ + /*dummy*/ +} + +/*internal function*/ +static void insert_before(usrtc_t *us,usrtc_node_t *newnode,usrtc_node_t *succ) +{ + usrtc_node_t *pred=succ->prev; + + newnode->prev=pred; + newnode->next=succ; + + pred->next=newnode; + succ->prev=newnode; + + /*TODO: check for maxcount*/ + us->nodecount++; +} + diff --git a/lib/redblack.c b/lib/redblack.c new file mode 100644 index 0000000..89ba2f1 --- /dev/null +++ b/lib/redblack.c @@ -0,0 +1,309 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * redblack.c + * Copyright (C) 2006-2013, 2014 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#include + +#include +#include +#include + +#define color usrtc_impldata.usrtc_rb_color + +/*function prototypes*/ +static void redblack_init(usrtc_t *); +static void redblack_insert(usrtc_t *, usrtc_node_t *, const void *); +static void redblack_delete(usrtc_t *, usrtc_node_t *); +static void redblack_convert_from_list(usrtc_t *); + +usrtc_functions_t usrtc_redblack_fu = { + redblack_init, + redblack_insert, + redblack_delete, + usrtc_tree_lookup, + usrtc_tree_lower_bound, + usrtc_tree_upper_bound, + usrtc_tree_first, + usrtc_tree_last, + usrtc_tree_next, + usrtc_tree_prev, + usrtc_tree_convert_to_list, + redblack_convert_from_list, + usrtc_bst +}; + +/*implementation*/ +static void redblack_init(usrtc_t *us) +{ + usrtc_tree_init(us); + us->sentinel.color = usrtc_black; +} + +static void redblack_insert(usrtc_t *us, usrtc_node_t *node, const void *key) +{ + usrtc_node_t *parent; + + /* simple bt insert */ + usrtc_tree_insert(us,node,key); + + /* implementation specific insert */ + node->color = usrtc_red; + parent=node->parent; + + while(parent->color==usrtc_red) { + usrtc_node_t *grandpa=parent->parent; + + if(parent==grandpa->left) { + usrtc_node_t *uncle=grandpa->right; + if(uncle->color==usrtc_red) { /*red parent->red uncle*/ + parent->color=usrtc_black; + uncle->color=usrtc_black; + grandpa->color=usrtc_red; + node=grandpa; + parent=grandpa->parent; + } else { /*red parent->black uncle */ + if(node==parent->right) { + usrtc_tree_rotate_left(node,parent); + parent=node; + if(grandpa!=parent->parent) + return; + } + parent->color=usrtc_black; + grandpa->color=usrtc_red; + usrtc_tree_rotate_right(parent,grandpa); + break; + } + } else { /*ooh,parent == parent->parent->right*/ + usrtc_node_t *uncle=grandpa->left; + if(uncle->color==usrtc_red) { + parent->color=usrtc_black; + uncle->color=usrtc_black; + grandpa->color=usrtc_red; + node=grandpa; + parent=grandpa->parent; + } else { + if(node==parent->left) { + usrtc_tree_rotate_right(node,parent); + parent=node; + + if(grandpa!=parent->parent) + return; + } + parent->color=usrtc_black; + grandpa->color=usrtc_red; + usrtc_tree_rotate_left(parent,grandpa); + break; + } + } + } + + tree_root_priv(us)->color=usrtc_black; +} + +static void redblack_delete(usrtc_t *us,usrtc_node_t *node) +{ + usrtc_node_t *swap; + usrtc_node_t *child; + usrtc_rb_color_t savecolor; + + /*basic bt delete*/ + usrtc_tree_delete(us,node,&swap,&child); + + /*implementation specific deletion*/ + savecolor=node->color; + node->color=swap->color; + swap->color=savecolor; + + if(node->color==usrtc_black) { /*black*/ + usrtc_node_t *parent; + usrtc_node_t *sister; + + tree_root_priv(us)->color=usrtc_red; + + while(child->color==usrtc_black) { + parent=child->parent; + if(child==parent->left) { + sister=parent->right; + if(sister==tree_null_priv(us)) + return; + + if(sister->color==usrtc_red) { + sister->color=usrtc_black; + parent->color=usrtc_red; + usrtc_tree_rotate_left(sister,parent); + sister=parent->right; + + if(sister==tree_null_priv(us)) + return; + } + if(sister->left->color==usrtc_black && sister->right->color==usrtc_black) { + sister->color=usrtc_red; + child=parent; + } else { + if(sister->right->color==usrtc_black) { + if(sister->left->color!=usrtc_red) + return; + + sister->left->color=usrtc_black; + sister->color=usrtc_red; + usrtc_tree_rotate_right(sister->left,sister); + sister=parent->right; + + if(sister==tree_null_priv(us)) + return; + } + sister->color=parent->color; + sister->right->color=usrtc_black; + parent->color=usrtc_black; + usrtc_tree_rotate_left(sister,parent); + break; + } + } else { /*!child == child->parent->right*/ + if(child!=parent->right) + return; + + sister=parent->left; + + if(sister==tree_null_priv(us)) + return; + + if(sister->color==usrtc_red) { + sister->color=usrtc_black; + parent->color=usrtc_red; + usrtc_tree_rotate_right(sister,parent); + sister = parent->left; + + if(sister==tree_null_priv(us)) + return; + } + if(sister->right->color==usrtc_black && sister->left->color==usrtc_black) { + sister->color=usrtc_red; + child=parent; + } else { + if(sister->left->color == usrtc_black) { + if(sister->right->color!=usrtc_red) + return; + + sister->right->color=usrtc_black; + sister->color=usrtc_red; + usrtc_tree_rotate_left(sister->right, sister); + sister=parent->left; + + if(sister==tree_null_priv(us)) + return; + } + sister->color=parent->color; + sister->left->color=usrtc_black; + parent->color=usrtc_black; + usrtc_tree_rotate_right(sister,parent); + break; + } + } + } + + child->color=usrtc_black; + tree_root_priv(us)->color=usrtc_black; + } + +} + +static void redblack_convert_from_list(usrtc_t *us) +{ + usrtc_node_t *tree[TREE_DEPTH_MAX] = { NULL }; + usrtc_node_t *curr; + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *next; + usrtc_node_t *complete=NULL; + usrtc_count_t fullcount=(usrtc_count_t)USRTC_COUNT_T_MAX; + usrtc_count_t nodecount=us->nodecount; + usrtc_count_t botrowcount; + unsigned int baselevel=0; + unsigned int level=0; + unsigned int i; + + if(usrtc_red!=0 && usrtc_black!=1) + return; + + while(fullcount>=nodecount && fullcount) /*calc*/ + fullcount >>= 1; + + botrowcount=nodecount-fullcount; + + for(curr=nil->next;curr!=nil;curr=next) { + next=curr->next; + + if(complete==NULL && botrowcount--==0) { + baselevel=level=1; + complete=tree[0]; + + if(complete!=NULL) { + tree[0]=NULL; + complete->right=nil; + while(tree[level]!=0) { + tree[level]->right=complete; + complete->parent=tree[level]; + complete=tree[level]; + tree[level++]=NULL; + } + } + } + + if(complete==NULL) { + curr->left=nil; + curr->right=nil; + curr->color=level%2; + complete=curr; + + if(level!=baselevel) + return; + + while(tree[level]!=NULL) { + tree[level]->right=complete; + complete->parent=tree[level]; + complete=tree[level]; + tree[level++]=NULL; + } + } else { + curr->left=complete; + curr->color=(level+1)%2; + complete->parent=curr; + tree[level]=curr; + complete=NULL; + level=baselevel; + } + } + + if(complete==NULL) + complete=nil; + + for (i=0;iright=complete; + complete->parent=tree[i]; + complete=tree[i]; + } + } + + nil->right=nil; + nil->left=complete; + nil->color=usrtc_black; + complete->parent=nil; + complete->color=usrtc_black; + +} + diff --git a/lib/splay.c b/lib/splay.c new file mode 100644 index 0000000..c391606 --- /dev/null +++ b/lib/splay.c @@ -0,0 +1,142 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * splay.c + * Copyright (C) 2006-2013, 2014 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#include +#include +#include + +/*prototypes*/ +static void splay_insert(usrtc_t *,usrtc_node_t *,const void *); +static void splay_delete(usrtc_t *,usrtc_node_t *); +static usrtc_node_t *splay_lookup(usrtc_t *,const void *); + +usrtc_functions_t usrtc_splay_fu = { + usrtc_tree_init, + splay_insert, + splay_delete, + splay_lookup, + usrtc_tree_lower_bound, + usrtc_tree_upper_bound, + usrtc_tree_first, + usrtc_tree_last, + usrtc_tree_next, + usrtc_tree_prev, + usrtc_tree_convert_to_list, + usrtc_tree_convert_from_list, + usrtc_bst +}; + +static void right_zig_zig(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); +static void left_zig_zig(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); +static void right_zig_zag(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); +static void left_zig_zag(usrtc_node_t *,usrtc_node_t *,usrtc_node_t *); +static void splay_node(usrtc_t *,usrtc_node_t *); + +/*implementation*/ + +static void splay_insert(usrtc_t *us,usrtc_node_t *node,const void *key) +{ + usrtc_tree_insert(us,node,key); + + while(node!=tree_root_priv(us)) + splay_node(us,node); +} + +static void splay_delete(usrtc_t *us,usrtc_node_t *node) +{ + usrtc_node_t *dummy; + usrtc_tree_delete(us,node,&dummy,&dummy); +} + +static usrtc_node_t *splay_lookup(usrtc_t *us,const void *key) +{ + usrtc_node_t *node=usrtc_tree_lookup(us,key); + + if(node) + while(node!=tree_root_priv(us)) + splay_node(us,node); + + return node; +} + +static void right_zig_zig(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) +{ + usrtc_tree_rotate_right(parent,grandpa); + usrtc_tree_rotate_right(child,parent); +} + +static void left_zig_zig(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) +{ + usrtc_tree_rotate_left(parent,grandpa); + usrtc_tree_rotate_left(child,parent); +} + +static void right_zig_zag(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) +{ + usrtc_tree_rotate_right(child,parent); + usrtc_tree_rotate_left(child,grandpa); +} + +static void left_zig_zag(usrtc_node_t *child,usrtc_node_t *parent,usrtc_node_t *grandpa) +{ + usrtc_tree_rotate_left(child,parent); + usrtc_tree_rotate_right(child,grandpa); +} + +static void splay_node(usrtc_t *us,usrtc_node_t *node) +{ + usrtc_node_t *root=tree_root_priv(us); + usrtc_node_t *parent=node->parent; + + if(parent->left==node) { + if(parent==root) { + usrtc_tree_rotate_right(node,parent); + } else { + usrtc_node_t *grandpa=parent->parent; + + if(grandpa->left==parent) + right_zig_zig(node,parent,grandpa); + else { + if(grandpa->right!=parent) + return; + + right_zig_zag(node,parent,grandpa); + } + } + } else { + if(parent->right!=node) + return; + + if(parent==root) { + usrtc_tree_rotate_left(node,parent); + } else { + usrtc_node_t *grandpa=parent->parent; + + if(grandpa->right==parent) { + left_zig_zig(node,parent,grandpa); + } else { + if(grandpa->left!=parent) + return; + + left_zig_zag(node,parent,grandpa); + } + } + + } +} diff --git a/lib/tree.c b/lib/tree.c new file mode 100644 index 0000000..8e30663 --- /dev/null +++ b/lib/tree.c @@ -0,0 +1,491 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * tree.c + * Copyright (C) 2006-2013, 2014 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#include + +#include +#include +#include + +/*local functions prototypes*/ +static void tree_delete(usrtc_t *, usrtc_node_t *); + +usrtc_functions_t usrtc_tree_fu = { + usrtc_tree_init, + usrtc_tree_insert, + tree_delete, + usrtc_tree_lookup, + usrtc_tree_lower_bound, + usrtc_tree_upper_bound, + usrtc_tree_first, + usrtc_tree_last, + usrtc_tree_next, + usrtc_tree_prev, + usrtc_tree_convert_to_list, + usrtc_tree_convert_from_list, + usrtc_bst +}; + +/*implementation*/ + +void usrtc_tree_init(usrtc_t *us) +{ + us->sentinel.left=&us->sentinel; + us->sentinel.right=&us->sentinel; + us->sentinel.parent=&us->sentinel; + + us->sentinel.impl_specific.usrtc_dummy=0; + us->sentinel.data=0; + us->sentinel.key=0; +} + +void usrtc_tree_insert(usrtc_t *us,usrtc_node_t *node,const void *key) +{ + usrtc_node_t *where=tree_root_priv(us); + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *parent=nil; + long res=-1; + + node->key=key; + + while(where!=nil) { + parent=where; + res=us->compare(key,where->key); + + if(us->dupes_allowed && !res) /*trying to put duplicate to the disabled dupe tree*/ + return; + + if(res<0) + where=where->left; + else + where=where->right; + } + + /*assert(where==nil);*/ + + if(res<0) + parent->left=node; + else + parent->right=node; + + node->parent=parent; + node->left=nil; + node->right=nil; + + us->nodecount++; +} + +void usrtc_tree_delete(usrtc_t *us,usrtc_node_t *node,usrtc_node_t **pswap,usrtc_node_t **pchild) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *child; + usrtc_node_t *delparent=node->parent; + usrtc_node_t *next=node; + usrtc_node_t *nextparent; + + if(node->left!=nil && node->right!=nil) { + next=usrtc_tree_next(us,node); + nextparent=next->parent; + + /*if(next!=nil && next->parent!=nil && next->parent==nil) + return;*/ + + child=next->right; + child->parent=nextparent; + + if(nextparent->left==next) + nextparent->left=child; + else { + //if(nextparent->right!=next) + //return; + nextparent->right=child; + } + + next->parent=delparent; + next->left=node->left; + next->right=node->right; + next->left->parent=next; + next->right->parent=next; + + if(delparent->left==node) { + delparent->left=next; + } else { + //if(delparent->right!=node) + // return; + delparent->right = next; + } + + } else { + /*if(node==nil) + return; + if(node->left!=nil && node->right!=nil) + return;*/ + + child=(node->left!=nil) ? node->left : node->right; + + child->parent=delparent=node->parent; + + if(node==delparent->left) { + delparent->left=child; + } else { + /*if(node!=delparent->right) + return;*/ + delparent->right=child; + } + } + + node->parent=0; + node->right=0; + node->left=0; + + us->nodecount--; + + *pswap = next; + *pchild = child; +} + +usrtc_node_t *usrtc_tree_lookup(usrtc_t *us,const void *key) +{ + usrtc_node_t *root=tree_root_priv(us); + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *saved; + long res; + + while (root!=nil) { + res=us->compare(key,root->key); + if(res<0) + root=root->left; + else if(res>0) + root=root->right; + else { + if(!us->dupes_allowed) + return root; /*no duplicates*/ + else { /*duplicate, then find left occurence*/ + do { + saved=root; + root=root->left; + while(root!=nil && us->compare(key,root->key)) + root=root->right; + } while(root!=nil); + return saved; + } + } + } + + return NULL; +} + +usrtc_node_t *usrtc_tree_lower_bound(usrtc_t *us,const void *key) +{ + usrtc_node_t *root=tree_root_priv(us); + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *tentative=NULL; + long res; + + while(root!=nil) { + res=us->compare(key,root->key); + + if(res>0) { + root=root->right; + } else if(res<0) { + tentative=root; + root=root->left; + } else { + if (!us->dupes_allowed) + return root; + else { + tentative=root; + root=root->left; + } + } + } + + return tentative; +} + +usrtc_node_t *usrtc_tree_upper_bound(usrtc_t *us,const void *key) +{ + usrtc_node_t *root=tree_root_priv(us); + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *tentative=NULL; + long res; + + while(root!=nil) { + res=us->compare(key,root->key); + + if(res>0) { + root=root->left; + } else if(res<0) { + tentative=root; + root=root->right; + } else { + if (!us->dupes_allowed) + return root; + else { + tentative=root; + root=root->right; + } + } + } + + return tentative; +} + +usrtc_node_t *usrtc_tree_first(usrtc_t *us) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *root=tree_root_priv(us); + usrtc_node_t *left; + + if(root!=nil) + while((left=root->left)!=nil) + root=left; + + return (root==nil) ? NULL : root; +} + +usrtc_node_t *usrtc_tree_last(usrtc_t *us) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *root=tree_root_priv(us); + usrtc_node_t *right; + + if(root!=nil) + while((right=root->right)!=nil) + root=right; + + return (root==nil) ? NULL : root; +} + +usrtc_node_t *usrtc_tree_next(usrtc_t *us, usrtc_node_t *curr) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *parent; + usrtc_node_t *left; + + if(curr->right!=nil) { + curr=curr->right; + while((left=curr->left)!=nil) + curr=left; + return curr; + } + + parent=curr->parent; + + while(parent!=nil && curr==parent->right) { + curr=parent; + parent=curr->parent; + } + + return (parent==nil) ? NULL : parent; +} + +usrtc_node_t *usrtc_tree_prev(usrtc_t *us, usrtc_node_t *curr) +{ + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *parent; + usrtc_node_t *right; + + if(curr->left!=nil) { + curr=curr->left; + while((right=curr->right)!=nil) + curr=right; + return curr; + } + + parent=curr->parent; + + while(parent!=nil && curr==parent->left) { + curr=parent; + parent=curr->parent; + } + + return (parent==nil) ? NULL : parent; +} + +/*uff, convertation between trees and lists*/ +void usrtc_tree_convert_to_list(usrtc_t *us) +{ + usrtc_node_t *node; + usrtc_node_t tempsentinel; + usrtc_node_t *nil=&tempsentinel; + usrtc_node_t *tail,*next; + usrtc_node_t *treenil=tree_null_priv(us); + + if(us->nodecount==0) /* no nodes */ + return; + + tempsentinel.next=nil; + tempsentinel.prev=nil; + + /* two passes */ + for(tail=nil,node=usrtc_tree_first(us);node!=0;tail=node,node=next) { + next=usrtc_tree_next(us,node); + node->prev=tail; + } + + nil->prev=tail; + + for(tail=nil,node=nil->prev;node!=nil;tail=node,node=node->prev) + node->next=tail; + + nil->next=tail; + + us->sentinel.next=tempsentinel.next; + us->sentinel.prev=tempsentinel.prev; + us->sentinel.next->prev=treenil; + us->sentinel.prev->next=treenil; +} + +void usrtc_tree_convert_from_list(usrtc_t *us) +{ + usrtc_node_t *tree[TREE_DEPTH_MAX]={ 0 }; + usrtc_node_t *curr; + usrtc_node_t *nil=tree_null_priv(us); + usrtc_node_t *next; + usrtc_node_t *complete=NULL; + usrtc_count_t fullcount=(usrtc_count_t)USRTC_COUNT_T_MAX; + usrtc_count_t nodecount=us->nodecount; + usrtc_count_t botrowcount; + int baselevel=0; + int level=0; + int i=0; + + while (fullcount>=nodecount && fullcount) /* calc */ + fullcount>>=1; + + botrowcount=nodecount-fullcount; + + for(curr=nil->next;curr!=nil;curr=next) { + next=curr->next; + + if(complete==NULL && botrowcount-- ==0) { + baselevel=level=1; + complete=tree[0]; + + if(complete!=NULL) { + tree[0]=0; + complete->right=nil; + while(tree[level]!=NULL) { + tree[level]->right=complete; + complete->parent=tree[level]; + complete=tree[level]; + tree[level++]=0; + } + } + } + + if(complete==NULL) { + curr->left=nil; + curr->right=nil; + complete=curr; + + if(level!=baselevel) + return; + while(tree[level]!=NULL) { + tree[level]->right=complete; + complete->parent=tree[level]; + complete=tree[level]; + tree[level++]=0; + } + } else { + curr->left=complete; + complete->parent=curr; + tree[level]=curr; + complete=NULL; + level=baselevel; + } + } + + if(complete==NULL) + complete=nil; + + for(i=0;iright=complete; + complete->parent=tree[i]; + complete=tree[i]; + } + } + + nil->right=nil; + nil->left=complete; + complete->parent=nil; + +} + +void usrtc_tree_rotate_left(usrtc_node_t *child,usrtc_node_t *parent) +{ + usrtc_node_t *leftgrandchild; + usrtc_node_t *grandpa; + + if(parent->right!=child) + return; + + child=parent->right; + parent->right=leftgrandchild=child->left; + leftgrandchild->parent=parent; + + child->parent=grandpa=parent->parent; + + if(parent==grandpa->left) { + grandpa->left=child; + } else { + if(parent!=grandpa->right) + return; + grandpa->right=child; + } + + child->left=parent; + parent->parent=child; +} + +void usrtc_tree_rotate_right(usrtc_node_t *child,usrtc_node_t *parent) +{ + usrtc_node_t *rightgrandchild; + usrtc_node_t *grandpa; + + if(parent->left!=child) + return; + + parent->left=rightgrandchild=child->right; + rightgrandchild->parent=parent; + + child->parent=grandpa=parent->parent; + + if(parent==grandpa->right) { + grandpa->right=child; + } else { + if(parent!=grandpa->left) + return; + grandpa->left=child; + } + + child->right=parent; + parent->parent=child; +} + +/* local functions */ +static void tree_delete(usrtc_t *us, usrtc_node_t *node) +{ + usrtc_node_t *dummy; + + usrtc_tree_delete(us, node, &dummy, &dummy); +} + diff --git a/lib/usrtc.c b/lib/usrtc.c new file mode 100644 index 0000000..46a74ad --- /dev/null +++ b/lib/usrtc.c @@ -0,0 +1,243 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* + * usrtc.c + * Copyright (C) 2006-2013, 2014 Askele inc. + * + * libtdata is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libtdata is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see ."; + */ + +#include +#include +#include + +#include +#include + +/* so, if you want to add your implementation of the data + * structure please add this here, like the following. + */ + +#define MAX_IMPL 4 + +extern usrtc_functions_t usrtc_list_fu; +extern usrtc_functions_t usrtc_tree_fu; +extern usrtc_functions_t usrtc_redblack_fu; +extern usrtc_functions_t usrtc_splay_fu; +extern usrtc_functions_t usrtc_avl_fu; + +static usrtc_functions_t *impl_table[] = { + &usrtc_list_fu,&usrtc_tree_fu, + &usrtc_redblack_fu,&usrtc_splay_fu, + &usrtc_avl_fu }; + +static usrtc_node_t *default_node_alloc(void *context) +{ + return malloc(sizeof *default_node_alloc(context)); +} + +static void default_node_free(void *context,usrtc_node_t *node) +{ + free(node); +} + +void usrtc_init(usrtc_t *us,int impl,usrtc_count_t maxcount,usrtc_compare_t compare) +{ + if(!us) + return; + if(impl>MAX_IMPL) + return; + + us->nodecount=0; + us->maxcount=maxcount; + us->dupes_allowed=0; + us->compare=compare; + us->node_alloc=default_node_alloc; + us->node_free=default_node_free; + us->context=0; + us->futable=impl_table[impl]; + us->futable->usrtc_init(us); +} + +usrtc_t *usrtc_create(int impl,usrtc_count_t maxcount,usrtc_compare_t compare) +{ + usrtc_t *newrtc=(usrtc_t*)malloc(sizeof *newrtc); + + if(newrtc) + usrtc_init(newrtc,impl,maxcount,compare); + + return newrtc; +} + +void usrtc_destroy(usrtc_t *us) +{ + /*assert(usrtc_isempty(us));*/ + if(!us) + return; + + free(us); +} + +void usrtc_convert_to(usrtc_t *us,int impl) +{ + if(impl_table[impl]==us->futable) + return; + + if(us->futable->usrtc_type==usrtc_bst && (impl==USRTC_BST || impl==USRTC_SPLAY)) { + us->futable=impl_table[impl]; + return; + } + + us->futable->usrtc_convert_to_list(us); + us->futable=impl_table[impl]; + + if(impl_table[impl]->usrtc_type==usrtc_lst) + return; + + us->futable->usrtc_convert_from_list(us); +} + +usrtc_count_t usrtc_count(usrtc_t *us) +{ + return us->nodecount; +} + +int usrtc_isempty(usrtc_t *us) +{ + return us->nodecount == 0; +} + +int usrtc_isfull(usrtc_t *us) +{ + return us->nodecount == us->maxcount; +} + +int usrtc_alloc_insert(usrtc_t *us,const void *key,void *data) +{ + usrtc_node_t *newnode=us->node_alloc(us->context); + + if(newnode!=NULL) { + newnode->data=data; + us->futable->usrtc_insert(us,newnode,key); + } + + return newnode!=NULL; +} + +void usrtc_delete_free(usrtc_t *us,usrtc_node_t *node) +{ + us->futable->usrtc_delete(us,node); + us->node_free(us->context,node); +} + +void usrtc_set_allocator(usrtc_t *us,usrtc_node_alloc_t alloc,usrtc_node_free_t n_free,void *context) +{ + us->node_alloc=alloc; + us->node_free=n_free; + us->context=context; +} + +void usrtc_allow_dupes(usrtc_t *us) +{ + /*assert(us->nodecount == 0);*/ + if(!us->nodecount) + return; + + us->dupes_allowed=1; +} + +void usrtc_node_init(usrtc_node_t *node,void *data) +{ + node->data=data; + node->impl_specific.usrtc_dummy=0; + node->left=NULL; + node->right=NULL; + node->parent=NULL; +} + +usrtc_node_t *usrtc_node_create(void *data) +{ + usrtc_node_t *newnode=(usrtc_node_t*)malloc(sizeof *newnode); + + if(newnode!=NULL) + newnode->data=data; + + return newnode; +} + +void usrtc_node_destroy(usrtc_node_t *node) +{ + free(node); +} + +void *usrtc_node_getdata(usrtc_node_t *node) +{ + return node->data; +} + +void usrtc_node_setdata(usrtc_node_t *node,void *data) +{ + node->data=data; +} + +const void *usrtc_node_getkey(usrtc_node_t *node) +{ + return node->key; +} + +void usrtc_insert(usrtc_t *us,usrtc_node_t *node,const void *key) +{ + us->futable->usrtc_insert(us,node,key); +} + +void usrtc_delete(usrtc_t *us,usrtc_node_t *node) +{ + us->futable->usrtc_delete(us,node); +} + +usrtc_node_t *usrtc_lookup(usrtc_t *us,const void *key) +{ + return us->futable->usrtc_lookup(us,key); +} + +usrtc_node_t *usrtc_lower_bound(usrtc_t *us,const void *key) +{ + return us->futable->usrtc_lower_bound(us,key); +} + +usrtc_node_t *usrtc_upper_bound(usrtc_t *us,const void *key) +{ + return us->futable->usrtc_upper_bound(us,key); +} + +usrtc_node_t *usrtc_first(usrtc_t *us) +{ + return us->futable->usrtc_first(us); +} + +usrtc_node_t *usrtc_last(usrtc_t *us) +{ + return us->futable->usrtc_last(us); +} + +usrtc_node_t *usrtc_next(usrtc_t *us,usrtc_node_t *node) +{ + return us->futable->usrtc_next(us,node); +} + +usrtc_node_t *usrtc_prev(usrtc_t *us,usrtc_node_t *node) +{ + return us->futable->usrtc_prev(us,node); +} + + diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..bc8cbb0 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +# please keep this list sorted alphabetically +# diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..17fc5de --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,3 @@ +# List of source files containing translatable strings. + +