diff --git a/debian/copyright b/debian/copyright index b3e6c6692b..3d1499eeed 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1725,24 +1725,6 @@ Files: src/switch_dso.c Copyright: 2008 Michael Jerris License: BSD-like -Files: libs/libks/* - libs/libscgi/src/include/scgi_oop.h - libs/libscgi/src/scgi.c -Copyright: 2007-2013, Anthony Minessale II - 2007 Michael Jerris - 1996-2000 Gray Watson -License: BSD-3-clause - -Files: libs/libks/*/ks_json.[ch] - src/include/switch_json.h - src/switch_json.c -Copyright: 2009 Dave Gamble -License: MIT/X11 (BSD like) - -Files: libs/libks/*/simclist.[ch] -Copyright: 2007-2011 Mij -License: ISC - Files: libs/libtpl-1.5/src/tpl.[ch] Copyright: 2005-2010, Troy D. Hanson License: BSD-2-clause diff --git a/libs/libks/Makefile b/libs/libks/Makefile deleted file mode 100644 index f5aa325965..0000000000 --- a/libs/libks/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -PWD=$(shell pwd) -INCS=-I$(PWD)/src/include -DEBUG=-g -ggdb -BASE_FLAGS=$(INCS) $(DEBUG) -I$(LIBEDIT_DIR)/src/ -fPIC -PICKY=-O2 -CFLAGS=$(BASE_FLAGS) $(PICKY) -CXXFLAGS=$(BASE_FLAGS) -MYLIB=libks.a -LIBS=-lncurses -lks -lpthread -lm -LDFLAGS=-L. -OBJS=src/ks.o src/ks_threadmutex.o src/ks_config.o src/ks_json.o src/ks_buffer.o src/mpool.o src/table.o src/table_util.o src/simclist.o -SRC=src/ks.c src/ks_json.c src/ks_threadmutex.c src/ks_config.c src/ks_json.c src/ks_buffer.c src/mpool.c src/table.c src/table_util.c src/simclist.c -HEADERS=src/include/ks_config.h src/include/ks.h src/include/ks_threadmutex.h src/include/ks_json.h src/include/ks_buffer.h src/include/mpool.h src/include/mpool_loc.h src/include/table.h src/include/table_loc.h src/include/simclist.h -SOLINK=-shared -Xlinker -x - -all: $(MYLIB) - -$(MYLIB): $(OBJS) $(HEADERS) $(SRC) - ar rcs $(MYLIB) $(OBJS) - ranlib $(MYLIB) - -%.o: %.c $(HEADERS) - $(CC) $(CC_CFLAGS) $(CFLAGS) $(CXFLAGS) -c $< -o $@ - -test-clean: - rm -f test/testpools - -clean: test-clean - rm -f *.o src/*.o libks.a *~ src/*~ src/include/*~ - -test/testpools: $(MYLIB) test/testpools.c - $(CC) $(CXFLAGS) test/testpools.c -Isrc/include/ libks.a -o test/testpools - -test-all: test/testpools diff --git a/libs/libks/libks.props b/libs/libks/libks.props deleted file mode 100644 index 35b74ad4dd..0000000000 --- a/libs/libks/libks.props +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - SIMCLIST_NO_DUMPRESTORE;_CRT_SECURE_NO_WARNINGS;KS_EXPORTS;%(PreprocessorDefinitions) - $(ProjectDir)\src\include;$(ProjectDir)\src\win\sys;$(ProjectDir)\src\win;%(AdditionalIncludeDirectories) - 4574;4100;4127;4668;4255;4706;4710;4820 - - - - \ No newline at end of file diff --git a/libs/libks/libks.sln b/libs/libks/libks.sln deleted file mode 100644 index fe03d30e74..0000000000 --- a/libs/libks/libks.sln +++ /dev/null @@ -1,41 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libks", "libks.vcxproj", "{70D178D8-1100-4152-86C0-809A91CFF832}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testpools", "test\testpools\testpools.vcxproj", "{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}" - ProjectSection(ProjectDependencies) = postProject - {70D178D8-1100-4152-86C0-809A91CFF832} = {70D178D8-1100-4152-86C0-809A91CFF832} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {70D178D8-1100-4152-86C0-809A91CFF832}.Debug|x64.ActiveCfg = Debug|x64 - {70D178D8-1100-4152-86C0-809A91CFF832}.Debug|x64.Build.0 = Debug|x64 - {70D178D8-1100-4152-86C0-809A91CFF832}.Debug|x86.ActiveCfg = Debug|Win32 - {70D178D8-1100-4152-86C0-809A91CFF832}.Debug|x86.Build.0 = Debug|Win32 - {70D178D8-1100-4152-86C0-809A91CFF832}.Release|x64.ActiveCfg = Release|x64 - {70D178D8-1100-4152-86C0-809A91CFF832}.Release|x64.Build.0 = Release|x64 - {70D178D8-1100-4152-86C0-809A91CFF832}.Release|x86.ActiveCfg = Release|Win32 - {70D178D8-1100-4152-86C0-809A91CFF832}.Release|x86.Build.0 = Release|Win32 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x64.ActiveCfg = Debug|x64 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x64.Build.0 = Debug|x64 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x86.ActiveCfg = Debug|Win32 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Debug|x86.Build.0 = Debug|Win32 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x64.ActiveCfg = Release|x64 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x64.Build.0 = Release|x64 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x86.ActiveCfg = Release|Win32 - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libs/libks/libks.vcxproj b/libs/libks/libks.vcxproj deleted file mode 100644 index 1a40dd2f02..0000000000 --- a/libs/libks/libks.vcxproj +++ /dev/null @@ -1,156 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {70D178D8-1100-4152-86C0-809A91CFF832} - Win32Proj - 8.1 - - - - DynamicLibrary - true - v140 - - - DynamicLibrary - false - v140 - - - DynamicLibrary - true - v140 - - - DynamicLibrary - false - v140 - - - - - - - - - - - - - - - - - - - - - - - - - true - $(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\ - - - true - $(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\ - - - - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - EnableAllWarnings - ProgramDatabase - Disabled - %(AdditionalIncludeDirectories) - - - MachineX86 - true - Windows - - - - - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL - EnableAllWarnings - ProgramDatabase - %(AdditionalIncludeDirectories) - - - MachineX86 - true - Windows - true - true - - - - - %(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions) - ProgramDatabase - EnableAllWarnings - - - - - %(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions) - EnableAllWarnings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/libks/libks.vcxproj.filters b/libs/libks/libks.vcxproj.filters deleted file mode 100644 index 3b2d013492..0000000000 --- a/libs/libks/libks.vcxproj.filters +++ /dev/null @@ -1,93 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/libs/libks/src/include/cc.h b/libs/libks/src/include/cc.h deleted file mode 100644 index 44666193c6..0000000000 --- a/libs/libks/src/include/cc.h +++ /dev/null @@ -1,2 +0,0 @@ -const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; - diff --git a/libs/libks/src/include/ks.h b/libs/libks/src/include/ks.h deleted file mode 100644 index 16dffd024a..0000000000 --- a/libs/libks/src/include/ks.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _KS_H_ -#define _KS_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -#define ks_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1) -#define ks_set_string(_x, _y) ks_copy_string(_x, _y, sizeof(_x)) - - -#if (_MSC_VER >= 1400) // VC8+ -#define ks_assert(expr) assert(expr);__analysis_assume( expr ) -#endif - -#ifndef ks_assert -#define ks_assert(_x) assert(_x) -#endif - -#define ks_safe_free(_x) if (_x) free(_x); _x = NULL -#define ks_strlen_zero(s) (!s || *(s) == '\0') -#define ks_strlen_zero_buf(s) (*(s) == '\0') -#define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1) - -#include "math.h" -#include "ks_json.h" - -#define BUF_CHUNK 65536 * 50 -#define BUF_START 65536 * 100 - -#include -#include - -#define ks_test_flag(obj, flag) ((obj)->flags & flag) -#define ks_set_flag(obj, flag) (obj)->flags |= (flag) -#define ks_clear_flag(obj, flag) (obj)->flags &= ~(flag) - - -KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap); - -KS_DECLARE_DATA extern ks_logger_t ks_log; - -/*! Sets the logger for libks. Default is the null_logger */ -KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger); -/*! Sets the default log level for libks */ -KS_DECLARE(void) ks_global_set_default_logger(int level); - - -#include "ks_threadmutex.h" -#include "ks_config.h" -#include "ks_buffer.h" -#include "mpool.h" -#include "simclist.h" -#include "table.h" - -KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len); -KS_DECLARE(char *)ks_url_decode(char *s); -KS_DECLARE(const char *)ks_stristr(const char *instr, const char *str); -KS_DECLARE(int) ks_toupper(int c); -KS_DECLARE(int) ks_tolower(int c); -KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...); - - -KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags); - -KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen); - -#define ks_recv(_h) ks_recv_event(_h, 0, NULL) -#define ks_recv_timed(_h, _ms) ks_recv_event_timed(_h, _ms, 0, NULL) - -static __inline__ int ks_safe_strcasecmp(const char *s1, const char *s2) -{ - if (!(s1 && s2)) { - return 1; - } - - return strcasecmp(s1, s2); -} - -#ifdef __cplusplus -} -#endif /* defined(__cplusplus) */ - - -#endif /* defined(_KS_H_) */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/ks_buffer.h b/libs/libks/src/include/ks_buffer.h deleted file mode 100644 index 41c08c9a97..0000000000 --- a/libs/libks/src/include/ks_buffer.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2010-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "ks.h" -#ifndef KS_BUFFER_H -#define KS_BUFFER_H -/** - * @defgroup ks_buffer Buffer Routines - * @ingroup buffer - * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers - * throughout the application. - * @{ - */ -struct ks_buffer; -typedef struct ks_buffer ks_buffer_t; - -/*! \brief Allocate a new dynamic ks_buffer - * \param buffer returned pointer to the new buffer - * \param blocksize length to realloc by as data is added - * \param start_len ammount of memory to reserve initially - * \param max_len length the buffer is allowed to grow to - * \return status - */ -KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksize, ks_size_t start_len, ks_size_t max_len); - -/*! \brief Get the length of a ks_buffer_t - * \param buffer any buffer of type ks_buffer_t - * \return int size of the buffer. - */ -KS_DECLARE(ks_size_t) ks_buffer_len(ks_buffer_t *buffer); - -/*! \brief Get the freespace of a ks_buffer_t - * \param buffer any buffer of type ks_buffer_t - * \return int freespace in the buffer. - */ -KS_DECLARE(ks_size_t) ks_buffer_freespace(ks_buffer_t *buffer); - -/*! \brief Get the in use amount of a ks_buffer_t - * \param buffer any buffer of type ks_buffer_t - * \return int ammount of buffer curently in use - */ -KS_DECLARE(ks_size_t) ks_buffer_inuse(ks_buffer_t *buffer); - -/*! \brief Read data from a ks_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer. - * \param buffer any buffer of type ks_buffer_t - * \param data pointer to the read data to be returned - * \param datalen amount of data to be returned - * \return int ammount of data actually read - */ -KS_DECLARE(ks_size_t) ks_buffer_read(ks_buffer_t *buffer, void *data, ks_size_t datalen); - -KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_size_t maxlen); -KS_DECLARE(ks_size_t) ks_buffer_packet_count(ks_buffer_t *buffer); - -/*! \brief Read data endlessly from a ks_buffer_t - * \param buffer any buffer of type ks_buffer_t - * \param data pointer to the read data to be returned - * \param datalen amount of data to be returned - * \return int ammount of data actually read - * \note Once you have read all the data from the buffer it will loop around. - */ -KS_DECLARE(ks_size_t) ks_buffer_read_loop(ks_buffer_t *buffer, void *data, ks_size_t datalen); - -/*! \brief Assign a number of loops to read - * \param buffer any buffer of type ks_buffer_t - * \param loops the number of loops (-1 for infinite) - */ -KS_DECLARE(void) ks_buffer_set_loops(ks_buffer_t *buffer, int32_t loops); - -/*! \brief Write data into a ks_buffer_t up to the length of datalen - * \param buffer any buffer of type ks_buffer_t - * \param data pointer to the data to be written - * \param datalen amount of data to be written - * \return int amount of buffer used after the write, or 0 if no space available - */ -KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_size_t datalen); - -/*! \brief Remove data from the buffer - * \param buffer any buffer of type ks_buffer_t - * \param datalen amount of data to be removed - * \return int size of buffer, or 0 if unable to toss that much data - */ -KS_DECLARE(ks_size_t) ks_buffer_toss(ks_buffer_t *buffer, ks_size_t datalen); - -/*! \brief Remove all data from the buffer - * \param buffer any buffer of type ks_buffer_t - */ -KS_DECLARE(void) ks_buffer_zero(ks_buffer_t *buffer); - -/*! \brief Destroy the buffer - * \param buffer buffer to destroy - * \note only neccessary on dynamic buffers (noop on pooled ones) - */ -KS_DECLARE(void) ks_buffer_destroy(ks_buffer_t **buffer); - -/*! \brief Seek to offset from the beginning of the buffer - * \param buffer buffer to seek - * \param datalen offset in bytes - * \return new position - */ -KS_DECLARE(ks_size_t) ks_buffer_seek(ks_buffer_t *buffer, ks_size_t datalen); - -/** @} */ - -KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen); - -#endif -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/ks_config.h b/libs/libks/src/include/ks_config.h deleted file mode 100644 index 2a5a330418..0000000000 --- a/libs/libks/src/include/ks_config.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @defgroup config Config File Parser - * @ingroup config - * This module implements a basic interface and file format parser - * - *
- *
- * EXAMPLE 
- * 
- * [category1]
- * var1 => val1
- * var2 => val2
- * \# lines that begin with \# are comments
- * \#var3 => val3
- * 
- * @{ - */ - -#ifndef KS_CONFIG_H -#define KS_CONFIG_H - -#include "ks.h" - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - - -#define KS_URL_SEPARATOR "://" - - -#ifdef WIN32 -#define KS_PATH_SEPARATOR "\\" -#ifndef KS_CONFIG_DIR -#define KS_CONFIG_DIR "c:\\openks" -#endif -#define ks_is_file_path(file) (*(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR)) -#else -#define KS_PATH_SEPARATOR "/" -#ifndef KS_CONFIG_DIR -#define KS_CONFIG_DIR "/etc/openks" -#endif -#define ks_is_file_path(file) ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR)) -#endif - -/*! - \brief Evaluate the truthfullness of a string expression - \param expr a string expression - \return true or false -*/ -#define ks_true(expr)\ -(expr && ( !strcasecmp(expr, "yes") ||\ -!strcasecmp(expr, "on") ||\ -!strcasecmp(expr, "true") ||\ -!strcasecmp(expr, "enabled") ||\ -!strcasecmp(expr, "active") ||\ -!strcasecmp(expr, "allow") ||\ -atoi(expr))) ? 1 : 0 - -/*! - \brief Evaluate the falsefullness of a string expression - \param expr a string expression - \return true or false -*/ -#define ks_false(expr)\ -(expr && ( !strcasecmp(expr, "no") ||\ -!strcasecmp(expr, "off") ||\ -!strcasecmp(expr, "false") ||\ -!strcasecmp(expr, "disabled") ||\ -!strcasecmp(expr, "inactive") ||\ -!strcasecmp(expr, "disallow") ||\ -!atoi(expr))) ? 1 : 0 - -typedef struct ks_config ks_config_t; - -/*! \brief A simple file handle representing an open configuration file **/ -struct ks_config { - /*! FILE stream buffer to the opened file */ - FILE *file; - /*! path to the file */ - char path[512]; - /*! current category */ - char category[256]; - /*! current section */ - char section[256]; - /*! buffer of current line being read */ - char buf[1024]; - /*! current line number in file */ - int lineno; - /*! current category number in file */ - int catno; - /*! current section number in file */ - int sectno; - - int lockto; -}; - -/*! - \brief Open a configuration file - \param cfg (ks_config_t *) config handle to use - \param file_path path to the file - \return 1 (true) on success 0 (false) on failure -*/ -KS_DECLARE(int) ks_config_open_file(ks_config_t * cfg, const char *file_path); - -/*! - \brief Close a previously opened configuration file - \param cfg (ks_config_t *) config handle to use -*/ -KS_DECLARE(void) ks_config_close_file(ks_config_t * cfg); - -/*! - \brief Retrieve next name/value pair from configuration file - \param cfg (ks_config_t *) config handle to use - \param var pointer to aim at the new variable name - \param val pointer to aim at the new value -*/ -KS_DECLARE(int) ks_config_next_pair(ks_config_t * cfg, char **var, char **val); - -/*! - \brief Retrieve the CAS bits from a configuration string value - \param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx) - \param outbits pointer to aim at the CAS bits -*/ -KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits); - - -/** @} */ - -#ifdef __cplusplus -} -#endif /* defined(__cplusplus) */ - -#endif /* defined(KS_CONFIG_H) */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/ks_json.h b/libs/libks/src/include/ks_json.h deleted file mode 100755 index 1ad116e980..0000000000 --- a/libs/libks/src/include/ks_json.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -#include "ks.h" -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* cJSON Types: */ -#define cJSON_False 0 -#define cJSON_True 1 -#define cJSON_NULL 2 -#define cJSON_Number 3 -#define cJSON_String 4 -#define cJSON_Array 5 -#define cJSON_Object 6 - -#define cJSON_IsReference 256 - -/* The cJSON structure: */ -typedef struct cJSON { - struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - - int type; /* The type of the item, as above. */ - - char *valuestring; /* The item's string, if type==cJSON_String */ - int valueint; /* The item's number, if type==cJSON_Number */ - double valuedouble; /* The item's number, if type==cJSON_Number */ - - char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ -} cJSON; - -typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -/* Supply malloc, realloc and free functions to cJSON */ -KS_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks); - - -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ -KS_DECLARE(cJSON *)cJSON_Parse(const char *value); -/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ -KS_DECLARE(char *)cJSON_Print(cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ -KS_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item); -/* Delete a cJSON entity and all subentities. */ -KS_DECLARE(void) cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -KS_DECLARE(int) cJSON_GetArraySize(cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -KS_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item); -/* Get item "string" from object. Case insensitive. */ -KS_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string); - -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -KS_DECLARE(const char *)cJSON_GetErrorPtr(); - -/* These calls create a cJSON item of the appropriate type. */ -KS_DECLARE(cJSON *)cJSON_CreateNull(); -KS_DECLARE(cJSON *)cJSON_CreateTrue(); -KS_DECLARE(cJSON *)cJSON_CreateFalse(); -KS_DECLARE(cJSON *)cJSON_CreateBool(int b); -KS_DECLARE(cJSON *)cJSON_CreateNumber(double num); -KS_DECLARE(cJSON *)cJSON_CreateString(const char *string); -KS_DECLARE(cJSON *)cJSON_CreateArray(); -KS_DECLARE(cJSON *)cJSON_CreateObject(); - -/* These utilities create an Array of count items. */ -KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count); -KS_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count); -KS_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count); -KS_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count); - -/* Append item to the specified array/object. */ -KS_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); -KS_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -KS_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -KS_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -KS_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which); -KS_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which); -KS_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string); -KS_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string); - -/* Update array items. */ -KS_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); -KS_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libs/libks/src/include/ks_platform.h b/libs/libks/src/include/ks_platform.h deleted file mode 100644 index a310e474d0..0000000000 --- a/libs/libks/src/include/ks_platform.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _KS_PLATFORM_H_ -#define _KS_PLATFORM_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) -#define _XOPEN_SOURCE 600 -#endif - -#ifndef HAVE_STRINGS_H -#define HAVE_STRINGS_H 1 -#endif -#ifndef HAVE_SYS_SOCKET_H -#define HAVE_SYS_SOCKET_H 1 -#endif - -#ifndef __WINDOWS__ -#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) -#define __WINDOWS__ -#endif -#endif - -#ifdef _MSC_VER -#ifndef __inline__ -#define __inline__ __inline -#endif -#if (_MSC_VER >= 1400) /* VC8+ */ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif -#ifndef strcasecmp -#define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif -#ifndef strncasecmp -#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) -#endif -#if (_MSC_VER < 1900) /* VC 2015 */ -#ifndef snprintf -#define snprintf _snprintf -#endif -#endif -#ifndef S_IRUSR -#define S_IRUSR _S_IREAD -#endif -#ifndef S_IWUSR -#define S_IWUSR _S_IWRITE -#endif -#undef HAVE_STRINGS_H -#undef HAVE_SYS_SOCKET_H -#endif - -#include -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include -#ifndef WIN32 -#include -#include -#include -#include -#include -#include -#endif - -#ifdef HAVE_STRINGS_H -#include -#endif -#include - - -#ifdef WIN32 -#include -#include -typedef SOCKET ks_socket_t; -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -typedef intptr_t ks_ssize_t; -typedef int ks_filehandle_t; -#define KS_SOCK_INVALID INVALID_SOCKET -#define strerror_r(num, buf, size) strerror_s(buf, size, num) -#if defined(KS_DECLARE_STATIC) -#define KS_DECLARE(type) type __stdcall -#define KS_DECLARE_NONSTD(type) type __cdecl -#define KS_DECLARE_DATA -#elif defined(KS_EXPORTS) -#define KS_DECLARE(type) __declspec(dllexport) type __stdcall -#define KS_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl -#define KS_DECLARE_DATA __declspec(dllexport) -#else -#define KS_DECLARE(type) __declspec(dllimport) type __stdcall -#define KS_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl -#define KS_DECLARE_DATA __declspec(dllimport) -#endif -#else // !WIN32 -#define KS_DECLARE(type) type -#define KS_DECLARE_NONSTD(type) type -#define KS_DECLARE_DATA -#include -#include -#include -#include -#include -#include -#include -#define KS_SOCK_INVALID -1 -typedef int ks_socket_t; -typedef ssize_t ks_ssize_t; -typedef int ks_filehandle_t; -#endif - - - -#ifdef __cplusplus -} -#endif /* defined(__cplusplus) */ -#endif /* defined(_KS_PLATFORM_H_) */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/ks_threadmutex.h b/libs/libks/src/include/ks_threadmutex.h deleted file mode 100644 index fb3eadab21..0000000000 --- a/libs/libks/src/include/ks_threadmutex.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Cross Platform Thread/Mutex abstraction - * Copyright(C) 2007 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - */ - - -#ifndef _KS_THREADMUTEX_H -#define _KS_THREADMUTEX_H - -#include "ks.h" - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -typedef struct ks_mutex ks_mutex_t; -typedef struct ks_thread ks_thread_t; -typedef void *(*ks_thread_function_t) (ks_thread_t *, void *); - -KS_DECLARE(ks_status_t) ks_thread_create_detached(ks_thread_function_t func, void *data); -ks_status_t ks_thread_create_detached_ex(ks_thread_function_t func, void *data, size_t stack_size); -void ks_thread_override_default_stacksize(size_t size); -KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex); -KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutex); -KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex); -KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex); -KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex); - -#ifdef __cplusplus -} -#endif /* defined(__cplusplus) */ - -#endif /* defined(_KS_THREADMUTEX_H) */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/ks_types.h b/libs/libks/src/include/ks_types.h deleted file mode 100644 index ec25e35265..0000000000 --- a/libs/libks/src/include/ks_types.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _KS_TYPES_H_ -#define _KS_TYPES_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -#include - -#define KS_VA_NONE "%s", "" - - -typedef enum { - KS_POLL_READ = (1 << 0), - KS_POLL_WRITE = (1 << 1), - KS_POLL_ERROR = (1 << 2) -} ks_poll_t; - -#ifdef WIN32 -#define KS_SEQ_FWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY -#define KS_SEQ_BWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE -#define KS_SEQ_FRED FOREGROUND_RED | FOREGROUND_INTENSITY -#define KS_SEQ_BRED FOREGROUND_RED -#define KS_SEQ_FMAGEN FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY -#define KS_SEQ_BMAGEN FOREGROUND_BLUE | FOREGROUND_RED -#define KS_SEQ_FCYAN FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY -#define KS_SEQ_BCYAN FOREGROUND_GREEN | FOREGROUND_BLUE -#define KS_SEQ_FGREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY -#define KS_SEQ_BGREEN FOREGROUND_GREEN -#define KS_SEQ_FYELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY -#define KS_SEQ_BYELLOW FOREGROUND_RED | FOREGROUND_GREEN -#define KS_SEQ_DEFAULT_COLOR KS_SEQ_FWHITE -#define KS_SEQ_FBLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY -#define KS_SEQ_BBLUE FOREGROUND_BLUE -#define KS_SEQ_FBLACK 0 | FOREGROUND_INTENSITY -#define KS_SEQ_BBLACK 0 -#else -#define KS_SEQ_ESC "\033[" -/* Ansi Control character suffixes */ -#define KS_SEQ_HOME_CHAR 'H' -#define KS_SEQ_HOME_CHAR_STR "H" -#define KS_SEQ_CLEARLINE_CHAR '1' -#define KS_SEQ_CLEARLINE_CHAR_STR "1" -#define KS_SEQ_CLEARLINEEND_CHAR "K" -#define KS_SEQ_CLEARSCR_CHAR0 '2' -#define KS_SEQ_CLEARSCR_CHAR1 'J' -#define KS_SEQ_CLEARSCR_CHAR "2J" -#define KS_SEQ_DEFAULT_COLOR KS_SEQ_ESC KS_SEQ_END_COLOR /* Reset to Default fg/bg color */ -#define KS_SEQ_AND_COLOR ";" /* To add multiple color definitions */ -#define KS_SEQ_END_COLOR "m" /* To end color definitions */ -/* Foreground colors values */ -#define KS_SEQ_F_BLACK "30" -#define KS_SEQ_F_RED "31" -#define KS_SEQ_F_GREEN "32" -#define KS_SEQ_F_YELLOW "33" -#define KS_SEQ_F_BLUE "34" -#define KS_SEQ_F_MAGEN "35" -#define KS_SEQ_F_CYAN "36" -#define KS_SEQ_F_WHITE "37" -/* Background colors values */ -#define KS_SEQ_B_BLACK "40" -#define KS_SEQ_B_RED "41" -#define KS_SEQ_B_GREEN "42" -#define KS_SEQ_B_YELLOW "43" -#define KS_SEQ_B_BLUE "44" -#define KS_SEQ_B_MAGEN "45" -#define KS_SEQ_B_CYAN "46" -#define KS_SEQ_B_WHITE "47" -/* Preset escape sequences - Change foreground colors only */ -#define KS_SEQ_FBLACK KS_SEQ_ESC KS_SEQ_F_BLACK KS_SEQ_END_COLOR -#define KS_SEQ_FRED KS_SEQ_ESC KS_SEQ_F_RED KS_SEQ_END_COLOR -#define KS_SEQ_FGREEN KS_SEQ_ESC KS_SEQ_F_GREEN KS_SEQ_END_COLOR -#define KS_SEQ_FYELLOW KS_SEQ_ESC KS_SEQ_F_YELLOW KS_SEQ_END_COLOR -#define KS_SEQ_FBLUE KS_SEQ_ESC KS_SEQ_F_BLUE KS_SEQ_END_COLOR -#define KS_SEQ_FMAGEN KS_SEQ_ESC KS_SEQ_F_MAGEN KS_SEQ_END_COLOR -#define KS_SEQ_FCYAN KS_SEQ_ESC KS_SEQ_F_CYAN KS_SEQ_END_COLOR -#define KS_SEQ_FWHITE KS_SEQ_ESC KS_SEQ_F_WHITE KS_SEQ_END_COLOR -#define KS_SEQ_BBLACK KS_SEQ_ESC KS_SEQ_B_BLACK KS_SEQ_END_COLOR -#define KS_SEQ_BRED KS_SEQ_ESC KS_SEQ_B_RED KS_SEQ_END_COLOR -#define KS_SEQ_BGREEN KS_SEQ_ESC KS_SEQ_B_GREEN KS_SEQ_END_COLOR -#define KS_SEQ_BYELLOW KS_SEQ_ESC KS_SEQ_B_YELLOW KS_SEQ_END_COLOR -#define KS_SEQ_BBLUE KS_SEQ_ESC KS_SEQ_B_BLUE KS_SEQ_END_COLOR -#define KS_SEQ_BMAGEN KS_SEQ_ESC KS_SEQ_B_MAGEN KS_SEQ_END_COLOR -#define KS_SEQ_BCYAN KS_SEQ_ESC KS_SEQ_B_CYAN KS_SEQ_END_COLOR -#define KS_SEQ_BWHITE KS_SEQ_ESC KS_SEQ_B_WHITE KS_SEQ_END_COLOR -/* Preset escape sequences */ -#define KS_SEQ_HOME KS_SEQ_ESC KS_SEQ_HOME_CHAR_STR -#define KS_SEQ_CLEARLINE KS_SEQ_ESC KS_SEQ_CLEARLINE_CHAR_STR -#define KS_SEQ_CLEARLINEEND KS_SEQ_ESC KS_SEQ_CLEARLINEEND_CHAR -#define KS_SEQ_CLEARSCR KS_SEQ_ESC KS_SEQ_CLEARSCR_CHAR KS_SEQ_HOME -#endif - -typedef int16_t ks_port_t; -typedef size_t ks_size_t; - -typedef enum { - KS_SUCCESS, - KS_FAIL, - KS_BREAK, - KS_DISCONNECTED, - KS_GENERR -} ks_status_t; - -/*! \brief Used internally for truth test */ -typedef enum { - KS_TRUE = 1, - KS_FALSE = 0 -} ks_bool_t; - -#ifndef __FUNCTION__ -#define __FUNCTION__ (const char *)__func__ -#endif - -#define KS_PRE __FILE__, __FUNCTION__, __LINE__ -#define KS_LOG_LEVEL_DEBUG 7 -#define KS_LOG_LEVEL_INFO 6 -#define KS_LOG_LEVEL_NOTICE 5 -#define KS_LOG_LEVEL_WARNING 4 -#define KS_LOG_LEVEL_ERROR 3 -#define KS_LOG_LEVEL_CRIT 2 -#define KS_LOG_LEVEL_ALERT 1 -#define KS_LOG_LEVEL_EMERG 0 - -#define KS_LOG_DEBUG KS_PRE, KS_LOG_LEVEL_DEBUG -#define KS_LOG_INFO KS_PRE, KS_LOG_LEVEL_INFO -#define KS_LOG_NOTICE KS_PRE, KS_LOG_LEVEL_NOTICE -#define KS_LOG_WARNING KS_PRE, KS_LOG_LEVEL_WARNING -#define KS_LOG_ERROR KS_PRE, KS_LOG_LEVEL_ERROR -#define KS_LOG_CRIT KS_PRE, KS_LOG_LEVEL_CRIT -#define KS_LOG_ALERT KS_PRE, KS_LOG_LEVEL_ALERT -#define KS_LOG_EMERG KS_PRE, KS_LOG_LEVEL_EMERG -typedef void (*ks_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...); -typedef void (*ks_listen_callback_t)(ks_socket_t server_sock, ks_socket_t client_sock, struct sockaddr_in *addr); - - -#ifdef __cplusplus -} -#endif /* defined(__cplusplus) */ - - -#endif /* defined(_KS_TYPES_H_) */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/libks/src/include/mpool.h b/libs/libks/src/include/mpool.h deleted file mode 100644 index b1c1ba7c58..0000000000 --- a/libs/libks/src/include/mpool.h +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Memory pool defines. - * - * Copyright 1996 by Gray Watson. - * - * This file is part of the mpool package. - * - * Permission to use, copy, modify, and distribute this software for - * any purpose and without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies, and that the name of Gray Watson not be used in advertising - * or publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: mpool.h,v 1.4 2006/05/31 20:26:11 gray Exp $ - */ - -#ifndef __MPOOL_H__ -#define __MPOOL_H__ - -#include "ks.h" -#include - -/* - * mpool flags to mpool_alloc or mpool_set_attr - */ - -/* - * Choose a best fit algorithm not first fit. This takes more CPU - * time but will result in a tighter heap. - */ -#define MPOOL_FLAG_BEST_FIT (1<<0) - -/* - * By default the library adds 2 bytes onto all allocations to insert - * a magic number that it can look for to determine how large a freed - * memory chunk is. This flag indicates that few if any frees are - * going to be performed on the pool and to not waste memory on these - * bytes. - */ -#define MPOOL_FLAG_NO_FREE (1<<1) - -/* - * This enables very heavy packing at the possible expense of CPU. - * This affects a number of parts of the library. - * - * By default the 1st page of memory is reserved for the main mpool - * structure. This flag will cause the rest of the 1st block to be - * available for use as user memory. - * - * By default the library looks through the memory when freed looking - * for a magic value. There is an internal max size that it will look - * and then it will give up. This flag forces it to look until it - * finds it. - */ -#define MPOOL_FLAG_HEAVY_PACKING (1<<2) - -/* - * Use MMAP_ANONYMOUS instead of /dev/zero - */ -#define MPOOL_FLAG_ANONYMOUS (1<<3) - -/* - * Mpool error codes - */ -#define MPOOL_ERROR_NONE 1 /* no error */ -#define MPOOL_ERROR_ARG_NULL 2 /* function argument is null */ -#define MPOOL_ERROR_ARG_INVALID 3 /* function argument is invalid */ -#define MPOOL_ERROR_PNT 4 /* invalid mpool pointer */ -#define MPOOL_ERROR_POOL_OVER 5 /* mpool structure was overwritten */ -#define MPOOL_ERROR_PAGE_SIZE 6 /* could not get system page-size */ -#define MPOOL_ERROR_OPEN_ZERO 7 /* could not open /dev/zero */ -#define MPOOL_ERROR_NO_MEM 8 /* no memory available */ -#define MPOOL_ERROR_MMAP 9 /* problems with mmap */ -#define MPOOL_ERROR_SIZE 10 /* error processing requested size */ -#define MPOOL_ERROR_TOO_BIG 11 /* allocation exceeded max size */ -#define MPOOL_ERROR_MEM 12 /* invalid memory address */ -#define MPOOL_ERROR_MEM_OVER 13 /* memory lower bounds overwritten */ -#define MPOOL_ERROR_NOT_FOUND 14 /* memory block not found in pool */ -#define MPOOL_ERROR_IS_FREE 15 /* memory block already free */ -#define MPOOL_ERROR_BLOCK_STAT 16 /* invalid internal block status */ -#define MPOOL_ERROR_FREE_ADDR 17 /* invalid internal free address */ -#define MPOOL_ERROR_UNUSED 18 /* UNUSED */ -#define MPOOL_ERROR_NO_PAGES 19 /* ran out of pages in pool */ -#define MPOOL_ERROR_ALLOC 20 /* calloc,malloc,free,realloc failed */ -#define MPOOL_ERROR_PNT_OVER 21 /* pointer structure was overwritten */ - -/* - * Mpool function IDs for the mpool_log_func callback function. - */ -#define MPOOL_FUNC_CLOSE 1 /* mpool_close function called */ -#define MPOOL_FUNC_CLEAR 2 /* mpool_clear function called */ -#define MPOOL_FUNC_ALLOC 3 /* mpool_alloc function called */ -#define MPOOL_FUNC_CALLOC 4 /* mpool_calloc function called */ -#define MPOOL_FUNC_FREE 5 /* mpool_free function called */ -#define MPOOL_FUNC_RESIZE 6 /* mpool_resize function called */ - -/* - * void mpool_log_func_t - * - * DESCRIPTION: - * - * Mpool transaction log function. - * - * RETURNS: - * - * None. - * - * ARGUMENT: - * - * mp_p -> Associated mpool address. - * - * func_id -> Integer function ID which identifies which mpool - * function is being called. - * - * byte_size -> Optionally specified byte size. - * - * ele_n -> Optionally specified element number. For mpool_calloc - * only. - * - * new_addr -> Optionally specified new address. For mpool_alloc, - * mpool_calloc, and mpool_resize only. - * - * old_addr -> Optionally specified old address. For mpool_resize and - * mpool_free only. - * - * old_byte_size -> Optionally specified old byte size. For - * mpool_resize only. - */ -typedef void (*mpool_log_func_t)(const void *mp_p, - const int func_id, - const unsigned long byte_size, - const unsigned long ele_n, - const void *old_addr, const void *new_addr, - const unsigned long old_byte_size); - -#ifdef MPOOL_MAIN - -#include "mpool_loc.h" - -#else - -/* generic mpool type */ -typedef void mpool_t; - -#endif - -/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ - -/* - * mpool_t *mpool_open - * - * DESCRIPTION: - * - * Open/allocate a new memory pool. - * - * RETURNS: - * - * Success - Pool pointer which must be passed to mpool_close to - * deallocate. - * - * Failure - NULL - * - * ARGUMENTS: - * - * flags -> Flags to set attributes of the memory pool. See the top - * of mpool.h. - * - * page_size -> Set the internal memory page-size. This must be a - * multiple of the getpagesize() value. Set to 0 for the default. - * - * start_addr -> Starting address to try and allocate memory pools. - * This is ignored if the MPOOL_FLAG_USE_SBRK is enabled. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(mpool_t *) mpool_open(const unsigned int flags, const unsigned int page_size, - void *start_addr, int *error_p); - -/* - * int mpool_close - * - * DESCRIPTION: - * - * Close/free a memory allocation pool previously opened with - * mpool_open. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to our memory pool. - */ -KS_DECLARE(int) mpool_close(mpool_t *mp_p); - -/* - * int mpool_clear - * - * DESCRIPTION: - * - * Wipe an opened memory pool clean so we can start again. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to our memory pool. - */ -KS_DECLARE(int) mpool_clear(mpool_t *mp_p); - -/* - * void *mpool_alloc - * - * DESCRIPTION: - * - * Allocate space for bytes inside of an already open memory pool. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal malloc. - * - * byte_size -> Number of bytes to allocate in the pool. Must be >0. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(void *) mpool_alloc(mpool_t *mp_p, const unsigned long byte_size, - int *error_p); - -/* - * void *mpool_calloc - * - * DESCRIPTION: - * - * Allocate space for elements of bytes in the memory pool and zero - * the space afterwards. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal calloc. - * - * ele_n -> Number of elements to allocate. - * - * ele_size -> Number of bytes per element being allocated. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(void *)mpool_calloc(mpool_t *mp_p, const unsigned long ele_n, - const unsigned long ele_size, int *error_p); - -/* - * int mpool_free - * - * DESCRIPTION: - * - * Free an address from a memory pool. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal free. - * - * addr <-> Address to free. - * - * size -> Size of the address being freed. - */ - -KS_DECLARE(int) mpool_free(mpool_t *mp_p, void *addr, const unsigned long size); - -/* - * void *mpool_resize - * - * DESCRIPTION: - * - * Reallocate an address in a mmeory pool to a new size. This is - * different from realloc in that it needs the old address' size. If - * you don't have it then you need to allocate new space, copy the - * data, and free the old pointer yourself. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal realloc. - * - * old_addr -> Previously allocated address. - * - * old_byte_size -> Size of the old address. Must be known, cannot be - * 0. - * - * new_byte_size -> New size of the allocation. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(void *) mpool_resize(mpool_t *mp_p, void *old_addr, - const unsigned long old_byte_size, - const unsigned long new_byte_size, - int *error_p); - -/* - * int mpool_stats - * - * DESCRIPTION: - * - * Return stats from the memory pool. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p -> Pointer to the memory pool. - * - * page_size_p <- Pointer to an unsigned integer which, if not NULL, - * will be set to the page-size of the pool. - * - * num_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the number of pointers currently allocated in pool. - * - * user_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the number of user bytes allocated in this pool. - * - * max_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the maximum number of user bytes that have been - * allocated in this pool. - * - * tot_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the total amount of space (including administrative - * overhead) used by the pool. - */ -KS_DECLARE(int) mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p, - unsigned long *num_alloced_p, - unsigned long *user_alloced_p, - unsigned long *max_alloced_p, - unsigned long *tot_alloced_p); - -/* - * int mpool_set_log_func - * - * DESCRIPTION: - * - * Set a logging callback function to be called whenever there was a - * memory transaction. See mpool_log_func_t. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * log_func -> Log function (defined in mpool.h) which will be called - * with each mpool transaction. - */ -KS_DECLARE(int) mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func); - -/* - * int mpool_set_max_pages - * - * DESCRIPTION: - * - * Set the maximum number of pages that the library will use. Once it - * hits the limit it will return MPOOL_ERROR_NO_PAGES. - * - * NOTE: if the MPOOL_FLAG_HEAVY_PACKING is set then this max-pages - * value will include the page with the mpool header structure in it. - * If the flag is _not_ set then the max-pages will not include this - * first page. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * max_pages -> Maximum number of pages used by the library. - */ -KS_DECLARE(int) mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages); - -/* - * const char *mpool_strerror - * - * DESCRIPTION: - * - * Return the corresponding string for the error number. - * - * RETURNS: - * - * Success - String equivalient of the error. - * - * Failure - String "invalid error code" - * - * ARGUMENTS: - * - * error -> Error number that we are converting. - */ -KS_DECLARE(const char *) mpool_strerror(const int error); - -/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ - -#endif /* ! __MPOOL_H__ */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/mpool_loc.h b/libs/libks/src/include/mpool_loc.h deleted file mode 100644 index a3fdbda3db..0000000000 --- a/libs/libks/src/include/mpool_loc.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Memory pool local defines. - * - * Copyright 1996 by Gray Watson. - * - * This file is part of the mpool package. - * - * Permission to use, copy, modify, and distribute this software for - * any purpose and without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies, and that the name of Gray Watson not be used in advertising - * or publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: mpool_loc.h,v 1.2 2005/05/20 20:08:54 gray Exp $ - */ - -#ifndef __MPOOL_LOC_H__ -#define __MPOOL_LOC_H__ - -#define MPOOL_MAGIC 0xABACABA /* magic for struct */ -#define BLOCK_MAGIC 0xB1B1007 /* magic for blocks */ -#define FENCE_MAGIC0 (unsigned char)(0xFAU) /* 1st magic mem byte */ -#define FENCE_MAGIC1 (unsigned char)(0xD3U) /* 2nd magic mem byte */ - -#define FENCE_SIZE 2 /* fence space */ -#define MIN_ALLOCATION (sizeof(mpool_free_t)) /* min alloc */ -#define MAX_FREE_SEARCH 10240 /* max size to search */ -#define MAX_FREE_LIST_SEARCH 100 /* max looking for free mem */ - -/* - * bitflag tools for Variable and a Flag - */ -#define BIT_FLAG(x) (1 << (x)) -#define BIT_SET(v,f) (v) |= (f) -#define BIT_CLEAR(v,f) (v) &= ~(f) -#define BIT_IS_SET(v,f) ((v) & (f)) -#define BIT_TOGGLE(v,f) (v) ^= (f) - -#define SET_POINTER(pnt, val) \ - do { \ - if ((pnt) != NULL) { \ - (*(pnt)) = (val); \ - } \ - } while(0) - -#define BLOCK_FLAG_USED BIT_FLAG(0) /* block is used */ -#define BLOCK_FLAG_FREE BIT_FLAG(1) /* block is free */ - -#define DEFAULT_PAGE_MULT 16 /* pagesize = this * getpagesize*/ - -/* How many pages SIZE bytes resides in. We add in the block header. */ -#define PAGES_IN_SIZE(mp_p, size) (((size) + sizeof(mpool_block_t) + \ - (mp_p)->mp_page_size - 1) / \ - (mp_p)->mp_page_size) -#define SIZE_OF_PAGES(mp_p, page_n) ((page_n) * (mp_p)->mp_page_size) -#define MAX_BITS 30 /* we only can allocate 1gb chunks */ - -#define MAX_BLOCK_USER_MEMORY(mp_p) ((mp_p)->mp_page_size - \ - sizeof(mpool_block_t)) -#define FIRST_ADDR_IN_BLOCK(block_p) (void *)((char *)(block_p) + \ - sizeof(mpool_block_t)) -#define MEMORY_IN_BLOCK(block_p) ((char *)(block_p)->mb_bounds_p - \ - ((char *)(block_p) + \ - sizeof(mpool_block_t))) - -typedef struct { - unsigned int mp_magic; /* magic number for struct */ - unsigned int mp_flags; /* flags for the struct */ - unsigned int mp_mmflags; /* flags for mmap */ - unsigned long mp_alloc_c; /* number of allocations */ - unsigned long mp_user_alloc; /* user bytes allocated */ - unsigned long mp_max_alloc; /* maximum user bytes allocated */ - unsigned int mp_page_c; /* number of pages allocated */ - unsigned int mp_max_pages; /* maximum number of pages to use */ - unsigned int mp_page_size; /* page-size of our system */ - int mp_fd; /* fd for /dev/zero if mmap-ing */ - off_t mp_top; /* top of our allocations in fd */ - mpool_log_func_t mp_log_func; /* log callback function */ - void *mp_addr; /* current address for mmaping */ - void *mp_min_p; /* min address in pool for checks */ - void *mp_bounds_p; /* max address in pool for checks */ - struct mpool_block_st *mp_first_p; /* first memory block we are using */ - struct mpool_block_st *mp_last_p; /* last memory block we are using */ - struct mpool_block_st *mp_free[MAX_BITS + 1]; /* free lists based on size */ - unsigned int mp_magic2; /* upper magic for overwrite sanity */ -} mpool_t; - -/* for debuggers to be able to interrogate the generic type in the .h file */ -typedef mpool_t mpool_ext_t; - -/* - * Block header structure. This structure *MUST* be long-word - * aligned. - */ -typedef struct mpool_block_st { - unsigned int mb_magic; /* magic number for block header */ - void *mb_bounds_p; /* block boundary location */ - struct mpool_block_st *mb_next_p; /* linked list next pointer */ - unsigned int mb_magic2; /* upper magic for overwrite sanity */ -} mpool_block_t; - -/* - * Free list structure. - */ -typedef struct { - void *mf_next_p; /* pointer to the next free address */ - unsigned long mf_size; /* size of the free block */ -} mpool_free_t; - -#endif /* ! __MPOOL_LOC_H__ */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/simclist.h b/libs/libks/src/include/simclist.h deleted file mode 100755 index 1b99ad9c43..0000000000 --- a/libs/libks/src/include/simclist.h +++ /dev/null @@ -1,990 +0,0 @@ -/* - * Copyright (c) 2007,2008 Mij - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -/* - * SimCList library. See http://mij.oltrelinux.com/devel/simclist - */ - - -#ifndef SIMCLIST_H -#define SIMCLIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#ifndef SIMCLIST_NO_DUMPRESTORE -# ifndef _WIN32 -# include /* list_dump_info_t's struct timeval */ -# else -# include -# endif -#endif - - - /* Be friend of both C90 and C99 compilers */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - /* "inline" and "restrict" are keywords */ -#else -# define inline /* inline */ -# define restrict /* restrict */ -#endif - - - /** - * Type representing list hashes. - * - * This is a signed integer value. - */ - typedef int32_t list_hash_t; - -#ifndef SIMCLIST_NO_DUMPRESTORE - typedef struct { - uint16_t version; /* dump version */ - struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */ - uint32_t list_size; - uint32_t list_numels; - list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */ - uint32_t dumpsize; - int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */ - } list_dump_info_t; -#endif - - /** - * a comparator of elements. - * - * A comparator of elements is a function that: - * -# receives two references to elements a and b - * -# returns {<0, 0, >0} if (a > b), (a == b), (a < b) respectively - * - * It is responsability of the function to handle possible NULL values. - */ - typedef int (*element_comparator)(const void *a, const void *b); - - /** - * a seeker of elements. - * - * An element seeker is a function that: - * -# receives a reference to an element el - * -# receives a reference to some indicator data - * -# returns non-0 if the element matches the indicator, 0 otherwise - * - * It is responsability of the function to handle possible NULL values in any - * argument. - */ - typedef int (*element_seeker)(const void *el, const void *indicator); - - /** - * an element lenght meter. - * - * An element meter is a function that: - * -# receives the reference to an element el - * -# returns its size in bytes - * - * It is responsability of the function to handle possible NULL values. - */ - typedef size_t (*element_meter)(const void *el); - - /** - * a function computing the hash of elements. - * - * An hash computing function is a function that: - * -# receives the reference to an element el - * -# returns a hash value for el - * - * It is responsability of the function to handle possible NULL values. - */ - typedef list_hash_t (*element_hash_computer)(const void *el); - - /** - * a function for serializing an element. - * - * A serializer function is one that gets a reference to an element, - * and returns a reference to a buffer that contains its serialization - * along with the length of this buffer. - * It is responsability of the function to handle possible NULL values, - * returning a NULL buffer and a 0 buffer length. - * - * These functions have 3 goals: - * -# "freeze" and "flatten" the memory representation of the element - * -# provide a portable (wrt byte order, or type size) representation of the element, if the dump can be used on different sw/hw combinations - * -# possibly extract a compressed representation of the element - * - * @param el reference to the element data - * @param serialize_buffer reference to fill with the length of the buffer - * @return reference to the buffer with the serialized data - */ - typedef void *(*element_serializer)(const void *restrict el, uint32_t *restrict serializ_len); - - /** - * a function for un-serializing an element. - * - * An unserializer function accomplishes the inverse operation of the - * serializer function. An unserializer function is one that gets a - * serialized representation of an element and turns it backe to the original - * element. The serialized representation is passed as a reference to a buffer - * with its data, and the function allocates and returns the buffer containing - * the original element, and it sets the length of this buffer into the - * integer passed by reference. - * - * @param data reference to the buffer with the serialized representation of the element - * @param data_len reference to the location where to store the length of the data in the buffer returned - * @return reference to a buffer with the original, unserialized representation of the element - */ - typedef void *(*element_unserializer)(const void *restrict data, uint32_t *restrict data_len); - - /* [private-use] list entry -- olds actual user datum */ - struct list_entry_s { - void *data; - - /* doubly-linked list service references */ - struct list_entry_s *next; - struct list_entry_s *prev; - }; - - /* [private-use] list attributes */ - struct list_attributes_s { - /* user-set routine for comparing list elements */ - element_comparator comparator; - /* user-set routing for seeking elements */ - element_seeker seeker; - /* user-set routine for determining the length of an element */ - element_meter meter; - int copy_data; - /* user-set routine for computing the hash of an element */ - element_hash_computer hasher; - /* user-set routine for serializing an element */ - element_serializer serializer; - /* user-set routine for unserializing an element */ - element_unserializer unserializer; - }; - - /** list object */ - typedef struct { - struct list_entry_s *head_sentinel; - struct list_entry_s *tail_sentinel; - struct list_entry_s *mid; - - unsigned int numels; - - /* array of spare elements */ - struct list_entry_s **spareels; - unsigned int spareelsnum; - -#ifdef SIMCLIST_WITH_THREADS - /* how many threads are currently running */ - unsigned int threadcount; -#endif - - /* service variables for list iteration */ - int iter_active; - unsigned int iter_pos; - struct list_entry_s *iter_curentry; - - /* list attributes */ - struct list_attributes_s attrs; - } list_t; - - /** - * initialize a list object for use. - * - * @param l must point to a user-provided memory location - * @return 0 for success. -1 for failure - */ - int list_init(list_t *restrict l); - - /** - * completely remove the list from memory. - * - * This function is the inverse of list_init(). It is meant to be called when - * the list is no longer going to be used. Elements and possible memory taken - * for internal use are freed. - * - * @param l list to destroy - */ - void list_destroy(list_t *restrict l); - - /** - * set the comparator function for list elements. - * - * Comparator functions are used for searching and sorting. If NULL is passed - * as reference to the function, the comparator is disabled. - * - * @param l list to operate - * @param comparator_fun pointer to the actual comparator function - * @return 0 if the attribute was successfully set; -1 otherwise - * - * @see element_comparator() - */ - int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun); - - /** - * set a seeker function for list elements. - * - * Seeker functions are used for finding elements. If NULL is passed as reference - * to the function, the seeker is disabled. - * - * @param l list to operate - * @param seeker_fun pointer to the actual seeker function - * @return 0 if the attribute was successfully set; -1 otherwise - * - * @see element_seeker() - */ - int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun); - - /** - * require to free element data when list entry is removed (default: don't free). - * - * [ advanced preference ] - * - * By default, when an element is removed from the list, it disappears from - * the list by its actual data is not free()d. With this option, every - * deletion causes element data to be freed. - * - * It is responsability of this function to correctly handle NULL values, if - * NULL elements are inserted into the list. - * - * @param l list to operate - * @param metric_fun pointer to the actual metric function - * @param copy_data 0: do not free element data (default); non-0: do free - * @return 0 if the attribute was successfully set; -1 otherwise - * - * @see element_meter() - * @see list_meter_int8_t() - * @see list_meter_int16_t() - * @see list_meter_int32_t() - * @see list_meter_int64_t() - * @see list_meter_uint8_t() - * @see list_meter_uint16_t() - * @see list_meter_uint32_t() - * @see list_meter_uint64_t() - * @see list_meter_float() - * @see list_meter_double() - * @see list_meter_string() - */ - int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data); - - /** - * set the element hash computing function for the list elements. - * - * [ advanced preference ] - * - * An hash can be requested depicting the list status at a given time. An hash - * only depends on the elements and their order. By default, the hash of an - * element is only computed on its reference. With this function, the user can - * set a custom function computing the hash of an element. If such function is - * provided, the list_hash() function automatically computes the list hash using - * the custom function instead of simply referring to element references. - * - * @param l list to operate - * @param hash_computer_fun pointer to the actual hash computing function - * @return 0 if the attribute was successfully set; -1 otherwise - * - * @see element_hash_computer() - */ - int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun); - - /** - * set the element serializer function for the list elements. - * - * [ advanced preference ] - * - * Serialize functions are used for dumping the list to some persistent - * storage. The serializer function is called for each element; it is passed - * a reference to the element and a reference to a size_t object. It will - * provide (and return) the buffer with the serialization of the element and - * fill the size_t object with the length of this serialization data. - * - * @param l list to operate - * @param serializer_fun pointer to the actual serializer function - * @return 0 if the attribute was successfully set; -1 otherwise - * - * @see element_serializer() - * @see list_dump_filedescriptor() - * @see list_restore_filedescriptor() - */ - int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun); - - /** - * set the element unserializer function for the list elements. - * - * [ advanced preference ] - * - * Unserialize functions are used for restoring the list from some persistent - * storage. The unserializer function is called for each element segment read - * from the storage; it is passed the segment and a reference to an integer. - * It shall allocate and return a buffer compiled with the resumed memory - * representation of the element, and set the integer value to the length of - * this buffer. - * - * @param l list to operate - * @param unserializer_fun pointer to the actual unserializer function - * @return 0 if the attribute was successfully set; -1 otherwise - * - * @see element_unserializer() - * @see list_dump_filedescriptor() - * @see list_restore_filedescriptor() - */ - int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun); - - /** - * append data at the end of the list. - * - * This function is useful for adding elements with a FIFO/queue policy. - * - * @param l list to operate - * @param data pointer to user data to append - * - * @return 1 for success. < 0 for failure - */ - int list_append(list_t *restrict l, const void *data); - - /** - * insert data in the head of the list. - * - * This function is useful for adding elements with a LIFO/Stack policy. - * - * @param l list to operate - * @param data pointer to user data to append - * - * @return 1 for success. < 0 for failure - */ - int list_prepend(list_t *restrict l, const void *restrict data); - - /** - * extract the element in the top of the list. - * - * This function is for using a list with a FIFO/queue policy. - * - * @param l list to operate - * @return reference to user datum, or NULL on errors - */ - void *list_fetch(list_t *restrict l); - - /** - * retrieve an element at a given position. - * - * @param l list to operate - * @param pos [0,size-1] position index of the element wanted - * @return reference to user datum, or NULL on errors - */ - void *list_get_at(const list_t *restrict l, unsigned int pos); - - /** - * return the maximum element of the list. - * - * @warning Requires a comparator function to be set for the list. - * - * Returns the maximum element with respect to the comparator function output. - * - * @see list_attributes_comparator() - * - * @param l list to operate - * @return the reference to the element, or NULL - */ - void *list_get_max(const list_t *restrict l); - - /** - * return the minimum element of the list. - * - * @warning Requires a comparator function to be set for the list. - * - * Returns the minimum element with respect to the comparator function output. - * - * @see list_attributes_comparator() - * - * @param l list to operate - * @return the reference to the element, or NULL - */ - void *list_get_min(const list_t *restrict l); - - /** - * retrieve and remove from list an element at a given position. - * - * @param l list to operate - * @param pos [0,size-1] position index of the element wanted - * @return reference to user datum, or NULL on errors - */ - void *list_extract_at(list_t *restrict l, unsigned int pos); - - /** - * insert an element at a given position. - * - * @param l list to operate - * @param data reference to data to be inserted - * @param pos [0,size-1] position index to insert the element at - * @return positive value on success. Negative on failure - */ - int list_insert_at(list_t *restrict l, const void *data, unsigned int pos); - - /** - * expunge the first found given element from the list. - * - * Inspects the given list looking for the given element; if the element - * is found, it is removed. Only the first occurence is removed. - * If a comparator function was not set, elements are compared by reference. - * Otherwise, the comparator is used to match the element. - * - * @param l list to operate - * @param data reference of the element to search for - * @return 0 on success. Negative value on failure - * - * @see list_attributes_comparator() - * @see list_delete_at() - */ - int list_delete(list_t *restrict l, const void *data); - - /** - * expunge an element at a given position from the list. - * - * @param l list to operate - * @param pos [0,size-1] position index of the element to be deleted - * @return 0 on success. Negative value on failure - */ - int list_delete_at(list_t *restrict l, unsigned int pos); - - /** - * expunge an array of elements from the list, given their position range. - * - * @param l list to operate - * @param posstart [0,size-1] position index of the first element to be deleted - * @param posend [posstart,size-1] position of the last element to be deleted - * @return the number of elements successfully removed on success, <0 on error - */ - int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend); - - /** - * clear all the elements off of the list. - * - * The element datums will not be freed. - * - * @see list_delete_range() - * @see list_size() - * - * @param l list to operate - * @return the number of elements removed on success, <0 on error - */ - int list_clear(list_t *restrict l); - - /** - * inspect the number of elements in the list. - * - * @param l list to operate - * @return number of elements currently held by the list - */ - unsigned int list_size(const list_t *restrict l); - - /** - * inspect whether the list is empty. - * - * @param l list to operate - * @return 0 iff the list is not empty - * - * @see list_size() - */ - int list_empty(const list_t *restrict l); - - /** - * find the position of an element in a list. - * - * @warning Requires a comparator function to be set for the list. - * - * Inspects the given list looking for the given element; if the element - * is found, its position into the list is returned. - * Elements are inspected comparing references if a comparator has not been - * set. Otherwise, the comparator is used to find the element. - * - * @param l list to operate - * @param data reference of the element to search for - * @return position of element in the list, or <0 if not found - * - * @see list_attributes_comparator() - * @see list_get_at() - */ - int list_locate(const list_t *restrict l, const void *data); - - /** - * returns an element given an indicator. - * - * @warning Requires a seeker function to be set for the list. - * - * Inspect the given list looking with the seeker if an element matches - * an indicator. If such element is found, the reference to the element - * is returned. - * - * @param l list to operate - * @param indicator indicator data to pass to the seeker along with elements - * @return reference to the element accepted by the seeker, or NULL if none found - */ - void *list_seek(list_t *restrict l, const void *indicator); - - /** - * inspect whether some data is member of the list. - * - * @warning Requires a comparator function to be set for the list. - * - * By default, a per-reference comparison is accomplished. That is, - * the data is in list if any element of the list points to the same - * location of data. - * A "semantic" comparison is accomplished, otherwise, if a comparator - * function has been set previously, with list_attributes_comparator(); - * in which case, the given data reference is believed to be in list iff - * comparator_fun(elementdata, userdata) == 0 for any element in the list. - * - * @param l list to operate - * @param data reference to the data to search - * @return 0 iff the list does not contain data as an element - * - * @see list_attributes_comparator() - */ - int list_contains(const list_t *restrict l, const void *data); - - /** - * concatenate two lists - * - * Concatenates one list with another, and stores the result into a - * user-provided list object, which must be different from both the - * lists to concatenate. Attributes from the original lists are not - * cloned. - * The destination list referred is threated as virgin room: if it - * is an existing list containing elements, memory leaks will happen. - * It is OK to specify the same list twice as source, for "doubling" - * it in the destination. - * - * @param l1 base list - * @param l2 list to append to the base - * @param dest reference to the destination list - * @return 0 for success, -1 for errors - */ - int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest); - - /** - * sort list elements. - * - * @warning Requires a comparator function to be set for the list. - * - * Sorts the list in ascending or descending order as specified by the versus - * flag. The algorithm chooses autonomously what algorithm is best suited for - * sorting the list wrt its current status. - * - * @param l list to operate - * @param versus positive: order small to big; negative: order big to small - * @return 0 iff sorting was successful - * - * @see list_attributes_comparator() - */ - int list_sort(list_t *restrict l, int versus); - - /** - * start an iteration session. - * - * This function prepares the list to be iterated. - * - * @param l list to operate - * @return 0 if the list cannot be currently iterated. >0 otherwise - * - * @see list_iterator_stop() - */ - int list_iterator_start(list_t *restrict l); - - /** - * return the next element in the iteration session. - * - * @param l list to operate - * @return element datum, or NULL on errors - */ - void *list_iterator_next(list_t *restrict l); - - /** - * inspect whether more elements are available in the iteration session. - * - * @param l list to operate - * @return 0 iff no more elements are available. - */ - int list_iterator_hasnext(const list_t *restrict l); - - /** - * end an iteration session. - * - * @param l list to operate - * @return 0 iff the iteration session cannot be stopped - */ - int list_iterator_stop(list_t *restrict l); - - /** - * return the hash of the current status of the list. - * - * @param l list to operate - * @param hash where the resulting hash is put - * - * @return 0 for success; <0 for failure - */ - int list_hash(const list_t *restrict l, list_hash_t *restrict hash); - -#ifndef SIMCLIST_NO_DUMPRESTORE - /** - * get meta informations on a list dump on filedescriptor. - * - * [ advanced function ] - * - * Extracts the meta information from a SimCList dump located in a file - * descriptor. The file descriptor must be open and positioned at the - * beginning of the SimCList dump block. - * - * @param fd file descriptor to get metadata from - * @param info reference to a dump metainformation structure to fill - * @return 0 for success; <0 for failure - * - * @see list_dump_filedescriptor() - */ - int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info); - - /** - * get meta informations on a list dump on file. - * - * [ advanced function ] - * - * Extracts the meta information from a SimCList dump located in a file. - * - * @param filename filename of the file to fetch from - * @param info reference to a dump metainformation structure to fill - * @return 0 for success; <0 for failure - * - * @see list_dump_filedescriptor() - */ - int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info); - - /** - * dump the list into an open, writable file descriptor. - * - * This function "dumps" the list to a persistent storage so it can be - * preserved across process terminations. - * When called, the file descriptor must be open for writing and positioned - * where the serialized data must begin. It writes its serialization of the - * list in a form which is portable across different architectures. Dump can - * be safely performed on stream-only (non seekable) descriptors. The file - * descriptor is not closed at the end of the operations. - * - * To use dump functions, either of these conditions must be satisfied: - * -# a metric function has been specified with list_attributes_copy() - * -# a serializer function has been specified with list_attributes_serializer() - * - * If a metric function has been specified, each element of the list is dumped - * as-is from memory, copying it from its pointer for its length down to the - * file descriptor. This might have impacts on portability of the dump to - * different architectures. - * - * If a serializer function has been specified, its result for each element is - * dumped to the file descriptor. - * - * - * @param l list to operate - * @param fd file descriptor to write to - * @param len location to store the resulting length of the dump (bytes), or NULL - * - * @return 0 if successful; -1 otherwise - * - * @see element_serializer() - * @see list_attributes_copy() - * @see list_attributes_serializer() - */ - int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len); - - /** - * dump the list to a file name. - * - * This function creates a filename and dumps the current content of the list - * to it. If the file exists it is overwritten. The number of bytes written to - * the file can be returned in a specified argument. - * - * @param l list to operate - * @param filename filename to write to - * @param len location to store the resulting length of the dump (bytes), or NULL - * - * @return 0 if successful; -1 otherwise - * - * @see list_attributes_copy() - * @see element_serializer() - * @see list_attributes_serializer() - * @see list_dump_filedescriptor() - * @see list_restore_file() - * - * This function stores a representation of the list - */ - int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len); - - /** - * restore the list from an open, readable file descriptor to memory. - * - * This function is the "inverse" of list_dump_filedescriptor(). It restores - * the list content from a (open, read-ready) file descriptor to memory. An - * unserializer might be needed to restore elements from the persistent - * representation back into memory-consistent format. List attributes can not - * be restored and must be set manually. - * - * @see list_dump_filedescriptor() - * @see list_attributes_serializer() - * @see list_attributes_unserializer() - * - * @param l list to restore to - * @param fd file descriptor to read from. - * @param len location to store the length of the dump read (bytes), or NULL - * @return 0 if successful; -1 otherwise - */ - int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len); - - /** - * restore the list from a file name. - * - * This function restores the content of a list from a file into memory. It is - * the inverse of list_dump_file(). - * - * @see element_unserializer() - * @see list_attributes_unserializer() - * @see list_dump_file() - * @see list_restore_filedescriptor() - * - * @param l list to restore to - * @param filename filename to read data from - * @param len location to store the length of the dump read (bytes), or NULL - * @return 0 if successful; -1 otherwise - */ - int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len); -#endif - - /* ready-made comparators, meters and hash computers */ - /* comparator functions */ - /** - * ready-made comparator for int8_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_int8_t(const void *a, const void *b); - - /** - * ready-made comparator for int16_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_int16_t(const void *a, const void *b); - - /** - * ready-made comparator for int32_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_int32_t(const void *a, const void *b); - - /** - * ready-made comparator for int64_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_int64_t(const void *a, const void *b); - - /** - * ready-made comparator for uint8_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_uint8_t(const void *a, const void *b); - - /** - * ready-made comparator for uint16_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_uint16_t(const void *a, const void *b); - - /** - * ready-made comparator for uint32_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_uint32_t(const void *a, const void *b); - - /** - * ready-made comparator for uint64_t elements. - * @see list_attributes_comparator() - */ - int list_comparator_uint64_t(const void *a, const void *b); - - /** - * ready-made comparator for float elements. - * @see list_attributes_comparator() - */ - int list_comparator_float(const void *a, const void *b); - - /** - * ready-made comparator for double elements. - * @see list_attributes_comparator() - */ - int list_comparator_double(const void *a, const void *b); - - /** - * ready-made comparator for string elements. - * @see list_attributes_comparator() - */ - int list_comparator_string(const void *a, const void *b); - - /* metric functions */ - /** - * ready-made metric function for int8_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_int8_t(const void *el); - - /** - * ready-made metric function for int16_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_int16_t(const void *el); - - /** - * ready-made metric function for int32_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_int32_t(const void *el); - - /** - * ready-made metric function for int64_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_int64_t(const void *el); - - /** - * ready-made metric function for uint8_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_uint8_t(const void *el); - - /** - * ready-made metric function for uint16_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_uint16_t(const void *el); - - /** - * ready-made metric function for uint32_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_uint32_t(const void *el); - - /** - * ready-made metric function for uint64_t elements. - * @see list_attributes_copy() - */ - size_t list_meter_uint64_t(const void *el); - - /** - * ready-made metric function for float elements. - * @see list_attributes_copy() - */ - size_t list_meter_float(const void *el); - - /** - * ready-made metric function for double elements. - * @see list_attributes_copy() - */ - size_t list_meter_double(const void *el); - - /** - * ready-made metric function for string elements. - * @see list_attributes_copy() - */ - size_t list_meter_string(const void *el); - - /* hash functions */ - /** - * ready-made hash function for int8_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_int8_t(const void *el); - - /** - * ready-made hash function for int16_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_int16_t(const void *el); - - /** - * ready-made hash function for int32_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_int32_t(const void *el); - - /** - * ready-made hash function for int64_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_int64_t(const void *el); - - /** - * ready-made hash function for uint8_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_uint8_t(const void *el); - - /** - * ready-made hash function for uint16_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_uint16_t(const void *el); - - /** - * ready-made hash function for uint32_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_uint32_t(const void *el); - - /** - * ready-made hash function for uint64_t elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_uint64_t(const void *el); - - /** - * ready-made hash function for float elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_float(const void *el); - - /** - * ready-made hash function for double elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_double(const void *el); - - /** - * ready-made hash function for string elements. - * @see list_attributes_hash_computer() - */ - list_hash_t list_hashcomputer_string(const void *el); - -#ifdef __cplusplus -} -#endif - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/table.h b/libs/libks/src/include/table.h deleted file mode 100644 index 181cacb906..0000000000 --- a/libs/libks/src/include/table.h +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * Generic table defines... - * - * Copyright 2000 by Gray Watson. - * - * This file is part of the table package. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose and without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, - * and that the name of Gray Watson not be used in advertising or - * publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: table.h,v 1.11 2000/03/09 03:30:42 gray Exp $ - */ - -#ifndef __TABLE_H__ -#define __TABLE_H__ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - /* - * To build a "key" in any of the below routines, pass in a pointer to - * the key and its size [i.e. sizeof(int), etc]. With any of the - * "key" or "data" arguments, if their size is < 0, it will do an - * internal strlen of the item and add 1 for the \0. - * - * If you are using firstkey() and nextkey() functions, be careful if, - * after starting your firstkey loop, you use delete or insert, it - * will not crash but may produce interesting results. If you are - * deleting from firstkey to NULL it will work fine. - */ - - /* return types for table functions */ -#define TABLE_ERROR_NONE 1 /* no error from function */ -#define TABLE_ERROR_PNT 2 /* bad table pointer */ -#define TABLE_ERROR_ARG_NULL 3 /* buffer args were null */ -#define TABLE_ERROR_SIZE 4 /* size of data was bad */ -#define TABLE_ERROR_OVERWRITE 5 /* key exists and we cant overwrite */ -#define TABLE_ERROR_NOT_FOUND 6 /* key does not exist */ -#define TABLE_ERROR_ALLOC 7 /* memory allocation error */ -#define TABLE_ERROR_LINEAR 8 /* no linear access started */ -#define TABLE_ERROR_OPEN 9 /* could not open file */ -#define TABLE_ERROR_SEEK 10 /* could not seek to pos in file */ -#define TABLE_ERROR_READ 11 /* could not read from file */ -#define TABLE_ERROR_WRITE 12 /* could not write to file */ -#define TABLE_ERROR_MMAP_NONE 13 /* no mmap support */ -#define TABLE_ERROR_MMAP 14 /* could not mmap file */ -#define TABLE_ERROR_MMAP_OP 15 /* can't perform operation on mmap */ -#define TABLE_ERROR_EMPTY 16 /* table is empty */ -#define TABLE_ERROR_NOT_EMPTY 17 /* table contains data */ -#define TABLE_ERROR_ALIGNMENT 18 /* invalid alignment value */ -#define TABLE_ERROR_COMPARE 19 /* problems with internal comparison */ -#define TABLE_ERROR_FREE 20 /* memory free error */ - - /* - * Table flags set with table_attr. - */ - - /* - * Automatically adjust the number of table buckets on the fly. - * Whenever the number of entries gets above some threshold, the - * number of buckets is realloced to a new size and each entry is - * re-hashed. Although this may take some time when it re-hashes, the - * table will perform better over time. - */ -#define TABLE_FLAG_AUTO_ADJUST (1<<0) - - /* - * If the above auto-adjust flag is set, also adjust the number of - * table buckets down as we delete entries. - */ -#define TABLE_FLAG_ADJUST_DOWN (1<<1) - - /* structure to walk through the fields in a linear order */ - typedef struct { - unsigned int tl_magic; /* magic structure to ensure correct init */ - unsigned int tl_bucket_c; /* where in the table buck array we are */ - unsigned int tl_entry_c; /* in the bucket, which entry we are on */ - } table_linear_t; - - /* - * int (*table_compare_t) - * - * DESCRIPTION - * - * Comparison function which compares two key/data pairs for table - * order. - * - * RETURNS: - * - * -1, 0, or 1 if key1 is <, ==, or > than key2. - * - * ARGUMENTS: - * - * key1 - Pointer to the first key entry. - * - * key1_size - Pointer to the size of the first key entry. - * - * data1 - Pointer to the first data entry. - * - * data1_size - Pointer to the size of the first data entry. - * - * key2 - Pointer to the second key entry. - * - * key2_size - Pointer to the size of the second key entry. - * - * data2 - Pointer to the second data entry. - * - * data2_size - Pointer to the size of the second data entry. - */ - typedef int (*table_compare_t)(const void *key1, const int key1_size, - const void *data1, const int data1_size, - const void *key2, const int key2_size, - const void *data2, const int data2_size); - - /* - * int (*table_mem_alloc_t) - * - * DESCRIPTION - * - * Function to override the table's allocation function. - * - * RETURNS: - * - * Success - Newly allocated pointer. - * - * Failure - NULL - * - * ARGUMENTS: - * - * pool_p <-> Pointer to our memory pool. If no pool is set then this - * will be NULL. - * - * size -> Number of bytes that needs to be allocated. - */ - typedef void *(*table_mem_alloc_t)(void *pool_p, const unsigned long size); - - /* - * int (*table_mem_resize_t) - * - * DESCRIPTION - * - * Function to override the table's memory resize function. The - * difference between this and realloc is that this provides the - * previous allocation size. You can specify NULL for this function - * in which cause the library will allocate, copy, and free itself. - * - * RETURNS: - * - * Success - Newly allocated pointer. - * - * Failure - NULL - * - * ARGUMENTS: - * - * pool_p <-> Pointer to our memory pool. If no pool is set then this - * will be NULL. - * - * old_addr -> Previously allocated address. - * - * old_size -> Size of the old address. Since the system is - * lightweight, it does not store size information on the pointer. - * - * new_size -> New size of the allocation. - */ - typedef void *(*table_mem_resize_t)(void *pool_p, void *old_addr, - const unsigned long old_size, - const unsigned long new_size); - - /* - * int (*table_mem_free_t) - * - * DESCRIPTION - * - * Function to override the table's free function. - * - * RETURNS: - * - * Success - 1 - * - * Failure - 0 - * - * ARGUMENTS: - * - * pool_p <-> Pointer to our memory pool. If no pool is set then this - * will be NULL. - * - * addr -> Address that we are freeing. - * - * min_size -> Minimum size of the address being freed or 0 if not - * known. This can also be the exact size if known. - */ - typedef int (*table_mem_free_t)(void *pool_p, void *addr, - const unsigned long min_size); - -#ifdef TABLE_MAIN - -#include "table_loc.h" - -#else - - /* generic table type */ - typedef void table_t; - - /* generic table entry type */ - typedef void table_entry_t; - -#endif - - /*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ - - /* - * table_t *table_alloc - * - * DESCRIPTION: - * - * Allocate a new table structure. - * - * RETURNS: - * - * A pointer to the new table structure which must be passed to - * table_free to be deallocated. On error a NULL is returned. - * - * ARGUMENTS: - * - * bucket_n - Number of buckets for the hash table. Our current hash - * value works best with base two numbers. Set to 0 to take the - * library default of 1024. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ - extern - table_t *table_alloc(const unsigned int bucket_n, int *error_p); - - /* - * table_t *table_alloc_in_pool - * - * DESCRIPTION: - * - * Allocate a new table structure in a memory pool or using - * alternative allocation and free functions. - * - * RETURNS: - * - * A pointer to the new table structure which must be passed to - * table_free to be deallocated. On error a NULL is returned. - * - * ARGUMENTS: - * - * bucket_n - Number of buckets for the hash table. Our current hash - * value works best with base two numbers. Set to 0 to take the - * library default of 1024. - * - * mem_pool <-> Memory pool to associate with the table. Can be NULL. - * - * alloc_func -> Allocate function we are overriding malloc() with. - * - * resize_func -> Resize function we are overriding the standard - * memory resize/realloc with. This can be NULL in which cause the - * library will allocate, copy, and free itself. - * - * free_func -> Free function we are overriding free() with. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ - extern - table_t *table_alloc_in_pool(const unsigned int bucket_n, - void *mem_pool, - table_mem_alloc_t alloc_func, - table_mem_resize_t resize_func, - table_mem_free_t free_func, int *error_p); - - /* - * int table_attr - * - * DESCRIPTION: - * - * Set the attributes for the table. The available attributes are - * specified at the top of table.h. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to a table structure which we will be altering. - * - * attr - Attribute(s) that we will be applying to the table. - */ - extern - int table_attr(table_t *table_p, const int attr); - - /* - * int table_set_data_alignment - * - * DESCRIPTION: - * - * Set the alignment for the data in the table. This is used when you - * want to store binary data types and refer to them directly out of - * the table storage. For instance if you are storing integers as - * data in the table and want to be able to retrieve the location of - * the interger and then increment it as (*loc_p)++. Otherwise you - * would have to memcpy it out to an integer, increment it, and memcpy - * it back. If you are storing character data, no alignment is - * necessary. - * - * For most data elements, sizeof(long) is recommended unless you use - * smaller data types exclusively. - * - * WARNING: If necessary, you must set the data alignment before any - * data gets put into the table. Otherwise a TABLE_ERROR_NOT_EMPTY - * error will be returned. - * - * NOTE: there is no way to set the key data alignment although it - * should automatically be long aligned. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to a table structure which we will be altering. - * - * alignment - Alignment requested for the data. Must be a power of - * 2. Set to 0 for none. - */ - extern - int table_set_data_alignment(table_t *table_p, const int alignment); - - /* - * int table_clear - * - * DESCRIPTION: - * - * Clear out and free all elements in a table structure. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer that we will be clearing. - */ - extern - int table_clear(table_t *table_p); - - /* - * int table_free - * - * DESCRIPTION: - * - * Deallocates a table structure. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer that we will be freeing. - */ - extern - int table_free(table_t *table_p); - - /* - * int table_insert_kd - * - * DESCRIPTION: - * - * Like table_insert except it passes back a pointer to the key and - * the data buffers after they have been inserted into the table - * structure. - * - * This routine adds a key/data pair both of which are made up of a - * buffer of bytes and an associated size. Both the key and the data - * will be copied into buffers allocated inside the table. If the key - * exists already, the associated data will be replaced if the - * overwrite flag is set, otherwise an error is returned. - * - * NOTE: be very careful changing the values since the table library - * provides the pointers to its memory. The key can _never_ be - * changed otherwise you will not find it again. The data can be - * changed but its length can never be altered unless you delete and - * re-insert it into the table. - * - * WARNING: The pointers to the key and data are not in any specific - * alignment. Accessing the key and/or data as an short, integer, or - * long pointer directly can cause problems. - * - * WARNING: Replacing a data cell (not inserting) will cause the table - * linked list to be temporarily invalid. Care must be taken with - * multiple threaded programs which are relying on the first/next - * linked list to be always valid. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer into which we will be inserting a - * new key/data pair. - * - * key_buf - Buffer of bytes of the key that we are inserting. If you - * are storing an (int) as the key (for example) then key_buf should - * be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are storing an (int) as the key (for example) then key_size should - * be sizeof(int). - * - * data_buf - Buffer of bytes of the data that we are inserting. If - * it is NULL then the library will allocate space for the data in the - * table without copying in any information. If data_buf is NULL and - * data_size is 0 then the library will associate a NULL data pointer - * with the key. If you are storing a (long) as the data (for - * example) then data_buf should be a (long *). - * - * data_size - Size of the data_buf buffer. If set to < 0 then the - * library will do a strlen of data_buf and add 1 for the '\0'. If - * you are storing an (long) as the key (for example) then key_size - * should be sizeof(long). - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the key storage that was allocated in the table. If you are - * storing an (int) as the key (for example) then key_buf_p should be - * (int **) i.e. the address of a (int *). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table. If you are - * storing an (long) as the data (for example) then data_buf_p should - * be (long **) i.e. the address of a (long *). - * - * overwrite - Flag which, if set to 1, will allow the overwriting of - * the data in the table with the new data if the key already exists - * in the table. - */ - extern - int table_insert_kd(table_t *table_p, - const void *key_buf, const int key_size, - const void *data_buf, const int data_size, - void **key_buf_p, void **data_buf_p, - const char overwrite_b); - - /* - * int table_insert - * - * DESCRIPTION: - * - * Exactly the same as table_insert_kd except it does not pass back a - * pointer to the key after they have been inserted into the table - * structure. This is still here for backwards compatibility. - * - * See table_insert_kd for more information. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer into which we will be inserting a - * new key/data pair. - * - * key_buf - Buffer of bytes of the key that we are inserting. If you - * are storing an (int) as the key (for example) then key_buf should - * be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are storing an (int) as the key (for example) then key_size should - * be sizeof(int). - * - * data_buf - Buffer of bytes of the data that we are inserting. If - * it is NULL then the library will allocate space for the data in the - * table without copying in any information. If data_buf is NULL and - * data_size is 0 then the library will associate a NULL data pointer - * with the key. If you are storing a (long) as the data (for - * example) then data_buf should be a (long *). - * - * data_size - Size of the data_buf buffer. If set to < 0 then the - * library will do a strlen of data_buf and add 1 for the '\0'. If - * you are storing an (long) as the key (for example) then key_size - * should be sizeof(long). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table. If you are - * storing an (long) as the data (for example) then data_buf_p should - * be (long **) i.e. the address of a (long *). - * - * overwrite - Flag which, if set to 1, will allow the overwriting of - * the data in the table with the new data if the key already exists - * in the table. - */ - extern - int table_insert(table_t *table_p, - const void *key_buf, const int key_size, - const void *data_buf, const int data_size, - void **data_buf_p, const char overwrite_b); - - /* - * int table_retrieve - * - * DESCRIPTION: - * - * This routine looks up a key made up of a buffer of bytes and an - * associated size in the table. If found then it returns the - * associated data information. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer into which we will be searching - * for the key. - * - * key_buf - Buffer of bytes of the key that we are searching for. If - * you are looking for an (int) as the key (for example) then key_buf - * should be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are looking for an (int) as the key (for example) then key_size - * should be sizeof(int). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table and that is - * associated with the key. If a (long) was stored as the data (for - * example) then data_buf_p should be (long **) i.e. the address of a - * (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data stored in the table that is associated with - * the key. - */ - extern - int table_retrieve(table_t *table_p, - const void *key_buf, const int key_size, - void **data_buf_p, int *data_size_p); - - /* - * int table_delete - * - * DESCRIPTION: - * - * This routine looks up a key made up of a buffer of bytes and an - * associated size in the table. If found then it will be removed - * from the table. The associated data can be passed back to the user - * if requested. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * NOTE: this could be an allocation error if the library is to return - * the data to the user. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we will be deleteing - * the key. - * - * key_buf - Buffer of bytes of the key that we are searching for to - * delete. If you are deleting an (int) key (for example) then - * key_buf should be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are deleting an (int) key (for example) then key_size should be - * sizeof(int). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table and that was - * associated with the key. If a (long) was stored as the data (for - * example) then data_buf_p should be (long **) i.e. the address of a - * (long *). If a pointer is passed in, the caller is responsible for - * freeing it after use. If data_buf_p is NULL then the library will - * free up the data allocation itself. - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that was stored in the table and that was - * associated with the key. - */ - extern - int table_delete(table_t *table_p, - const void *key_buf, const int key_size, - void **data_buf_p, int *data_size_p); - - /* - * int table_delete_first - * - * DESCRIPTION: - * - * This is like the table_delete routines except it deletes the first - * key/data pair in the table instead of an entry corresponding to a - * particular key. The associated key and data information can be - * passed back to the user if requested. This routines is handy to - * clear out a table. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * NOTE: this could be an allocation error if the library is to return - * the data to the user. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we will be deleteing - * the first key. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the first key that was allocated in the table. - * If an (int) was stored as the first key (for example) then - * key_buf_p should be (int **) i.e. the address of a (int *). If a - * pointer is passed in, the caller is responsible for freeing it - * after use. If key_buf_p is NULL then the library will free up the - * key allocation itself. - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that was stored in the table and that was - * associated with the key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table and that was - * associated with the key. If a (long) was stored as the data (for - * example) then data_buf_p should be (long **) i.e. the address of a - * (long *). If a pointer is passed in, the caller is responsible for - * freeing it after use. If data_buf_p is NULL then the library will - * free up the data allocation itself. - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that was stored in the table and that was - * associated with the key. - */ - extern - int table_delete_first(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * int table_info - * - * DESCRIPTION: - * - * Get some information about a table_p structure. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting - * information. - * - * num_buckets_p - Pointer to an integer which, if not NULL, will - * contain the number of buckets in the table. - * - * num_entries_p - Pointer to an integer which, if not NULL, will - * contain the number of entries stored in the table. - */ - extern - int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p); - - /* - * int table_adjust - * - * DESCRIPTION: - * - * Set the number of buckets in a table to a certain value. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer of which we are adjusting. - * - * bucket_n - Number buckets to adjust the table to. Set to 0 to - * adjust the table to its number of entries. - */ - extern - int table_adjust(table_t *table_p, const int bucket_n); - - /* - * int table_type_size - * - * DESCRIPTION: - * - * Return the size of the internal table type. - * - * RETURNS: - * - * The size of the table_t type. - * - * ARGUMENTS: - * - * None. - */ - extern - int table_type_size(void); - - /* - * int table_first - * - * DESCRIPTION: - * - * Find first element in a table and pass back information about the - * key/data pair. If any of the key/data pointers are NULL then they - * are ignored. - * - * NOTE: This function is not reentrant. More than one thread cannot - * be doing a first and next on the same table at the same time. Use - * the table_first_r version below for this. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * first element. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the first key that is allocated in the table. If - * an (int) is stored as the first key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the first key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the first key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the first key. - */ - extern - int table_first(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * int table_next - * - * DESCRIPTION: - * - * Find the next element in a table and pass back information about - * the key/data pair. If any of the key/data pointers are NULL then - * they are ignored. - * - * NOTE: This function is not reentrant. More than one thread cannot - * be doing a first and next on the same table at the same time. Use - * the table_next_r version below for this. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * next element. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the next key that is allocated in the table. If - * an (int) is stored as the next key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the next key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the next key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the next key. - */ - extern - int table_next(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * int table_this - * - * DESCRIPTION: - * - * Find the current element in a table and pass back information about - * the key/data pair. If any of the key/data pointers are NULL then - * they are ignored. - * - * NOTE: This function is not reentrant. Use the table_current_r - * version below. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * current element. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the current key that is allocated in the table. - * If an (int) is stored as the current key (for example) then - * key_buf_p should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the current key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the current key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the current key. - */ - extern - int table_this(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * int table_first_r - * - * DESCRIPTION: - * - * Reetrant version of the table_first routine above. Find first - * element in a table and pass back information about the key/data - * pair. If any of the key/data pointers are NULL then they are - * ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * first element. - * - * linear_p - Pointer to a table linear structure which is initialized - * here. The same pointer should then be passed to table_next_r - * below. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the first key that is allocated in the table. If - * an (int) is stored as the first key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the first key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the first key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the first key. - */ - extern - int table_first_r(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * int table_next_r - * - * DESCRIPTION: - * - * Reetrant version of the table_next routine above. Find next - * element in a table and pass back information about the key/data - * pair. If any of the key/data pointers are NULL then they are - * ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * next element. - * - * linear_p - Pointer to a table linear structure which is incremented - * here. The same pointer must have been passed to table_first_r - * first so that it can be initialized. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the next key that is allocated in the table. If - * an (int) is stored as the next key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL will be set - * to the size of the key that is stored in the table and that is - * associated with the next key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the next key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the next key. - */ - extern - int table_next_r(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * int table_this_r - * - * DESCRIPTION: - * - * Reetrant version of the table_this routine above. Find current - * element in a table and pass back information about the key/data - * pair. If any of the key/data pointers are NULL then they are - * ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * current element. - * - * linear_p - Pointer to a table linear structure which is accessed - * here. The same pointer must have been passed to table_first_r - * first so that it can be initialized. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the current key that is allocated in the table. - * If an (int) is stored as the current key (for example) then - * key_buf_p should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the current key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the current key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the current key. - */ - extern - int table_this_r(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * table_t *table_mmap - * - * DESCRIPTION: - * - * Mmap a table from a file that had been written to disk earlier via - * table_write. - * - * RETURNS: - * - * A pointer to the new table structure which must be passed to - * table_munmap to be deallocated. On error a NULL is returned. - * - * ARGUMENTS: - * - * path - Table file to mmap in. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ - extern - table_t *table_mmap(const char *path, int *error_p); - - /* - * int table_munmap - * - * DESCRIPTION: - * - * Unmmap a table that was previously mmapped using table_mmap. - * - * RETURNS: - * - * Returns table error codes. - * - * ARGUMENTS: - * - * table_p - Mmaped table pointer to unmap. - */ - extern - int table_munmap(table_t *table_p); - - /* - * int table_read - * - * DESCRIPTION: - * - * Read in a table from a file that had been written to disk earlier - * via table_write. - * - * RETURNS: - * - * Success - Pointer to the new table structure which must be passed - * to table_free to be deallocated. - * - * Failure - NULL - * - * ARGUMENTS: - * - * path - Table file to read in. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ - extern - table_t *table_read(const char *path, int *error_p); - - /* - * int table_write - * - * DESCRIPTION: - * - * Write a table from memory to file. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to the table that we are writing to the file. - * - * path - Table file to write out to. - * - * mode - Mode of the file. This argument is passed on to open when - * the file is created. - */ - extern - int table_write(const table_t *table_p, const char *path, const int mode); - - /* - * table_entry_t *table_order - * - * DESCRIPTION: - * - * Order a table by building an array of table entry pointers and then - * sorting this array using the qsort function. To retrieve the - * sorted entries, you can then use the table_entry routine to access - * each entry in order. - * - * NOTE: This routine is thread safe and makes use of an internal - * status qsort function. - * - * RETURNS: - * - * Success - An allocated list of table-linear structures which must - * be freed by table_order_free later. - * - * Failure - NULL - * - * ARGUMENTS: - * - * table_p - Pointer to the table that we are ordering. - * - * compare - Comparison function defined by the user. Its definition - * is at the top of the table.h file. If this is NULL then it will - * order the table my memcmp-ing the keys. - * - * num_entries_p - Pointer to an integer which, if not NULL, will - * contain the number of entries in the returned entry pointer array. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ - extern - table_entry_t **table_order(table_t *table_p, table_compare_t compare, - int *num_entries_p, int *error_p); - - /* - * int table_order_free - * - * DESCRIPTION: - * - * Free the pointer returned by the table_order or table_order_pos - * routines. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to the table. - * - * table_entries - Allocated list of entry pointers returned by - * table_order. - * - * entry_n - Number of entries in the array as passed back by - * table_order or table_order_pos in num_entries_p. - */ - extern - int table_order_free(table_t *table_p, table_entry_t **table_entries, - const int entry_n); - - /* - * int table_entry - * - * DESCRIPTION: - * - * Get information about an element. The element is one from the - * array returned by the table_order function. If any of the key/data - * pointers are NULL then they are ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * element. - * - * entry_p - Pointer to a table entry from the array returned by the - * table_order function. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of this entry that is allocated in the table. If an - * (int) is stored as this entry (for example) then key_buf_p should - * be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage of this entry that is allocated in the table. - * If a (long) is stored as this entry data (for example) then - * data_buf_p should be (long **) i.e. the address of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table. - */ - extern - int table_entry(table_t *table_p, table_entry_t *entry_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * table_linear_t *table_order_pos - * - * DESCRIPTION: - * - * Order a table by building an array of table linear structures and - * then sorting this array using the qsort function. To retrieve the - * sorted entries, you can then use the table_entry_pos routine to - * access each entry in order. - * - * NOTE: This routine is thread safe and makes use of an internal - * status qsort function. - * - * RETURNS: - * - * Success - An allocated list of table-linear structures which must - * be freed by table_order_pos_free later. - * - * Failure - NULL - * - * ARGUMENTS: - * - * table_p - Pointer to the table that we are ordering. - * - * compare - Comparison function defined by the user. Its definition - * is at the top of the table.h file. If this is NULL then it will - * order the table my memcmp-ing the keys. - * - * num_entries_p - Pointer to an integer which, if not NULL, will - * contain the number of entries in the returned entry pointer array. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ - extern - table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare, - int *num_entries_p, int *error_p); - - /* - * int table_order_pos_free - * - * DESCRIPTION: - * - * Free the pointer returned by the table_order or table_order_pos - * routines. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to the table. - * - * table_entries - Allocated list of entry pointers returned by - * table_order_pos. - * - * entry_n - Number of entries in the array as passed back by - * table_order or table_order_pos in num_entries_p. - */ - extern - int table_order_pos_free(table_t *table_p, table_linear_t *table_entries, - const int entry_n); - - /* - * int table_entry_pos - * - * DESCRIPTION: - * - * Get information about an element. The element is one from the - * array returned by the table_order function. If any of the key/data - * pointers are NULL then they are ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * element. - * - * linear_p - Pointer to a table linear structure from the array - * returned by the table_order function. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of this entry that is allocated in the table. If an - * (int) is stored as this entry (for example) then key_buf_p should - * be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage of this entry that is allocated in the table. - * If a (long) is stored as this entry data (for example) then - * data_buf_p should be (long **) i.e. the address of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table. - */ - extern - int table_entry_pos(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p); - - /* - * const char *table_strerror - * - * DESCRIPTION: - * - * Return the corresponding string for the error number. - * - * RETURNS: - * - * Success - String equivalient of the error. - * - * Failure - String "invalid error code" - * - * ARGUMENTS: - * - * error - Error number that we are converting. - */ - extern - const char *table_strerror(const int error); - - /*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! __TABLE_H__ */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/include/table_loc.h b/libs/libks/src/include/table_loc.h deleted file mode 100644 index 95149db971..0000000000 --- a/libs/libks/src/include/table_loc.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * local defines for the table module - * - * Copyright 2000 by Gray Watson. - * - * This file is part of the table package. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose and without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, - * and that the name of Gray Watson not be used in advertising or - * publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: table_loc.h,v 1.11 2000/03/09 03:30:42 gray Exp $ - */ - -#ifndef __TABLE_LOC_H__ -#define __TABLE_LOC_H__ - -#ifndef unix -#define NO_MMAP -#endif - -#ifndef BITSPERBYTE -#define BITSPERBYTE 8 -#endif -#ifndef BITS -#define BITS(type) (BITSPERBYTE * (int)sizeof(type)) -#endif - -#define TABLE_MAGIC 0xBADF00D /* very magic magicness */ -#define LINEAR_MAGIC 0xAD00D00 /* magic value for linear struct */ -#define DEFAULT_SIZE 1024 /* default table size */ -#define MAX_ALIGNMENT 128 /* max alignment value */ - -/* - * Maximum number of splits. This should mean that these routines can - * handle at least 2^128 different values (that's _quite_ a few). And - * then you can always increase the value. - */ -#define MAX_QSORT_SPLITS 128 - -/* - * Maximum number of entries that must be in list for it to be - * partitioned. If there are fewer elements then just do our - * insertion sort. - */ -#define MAX_QSORT_MANY 8 - -/* - * Macros. - */ - -/* returns 1 when we should grow or shrink the table */ -#define SHOULD_TABLE_GROW(tab) ((tab)->ta_entry_n > (tab)->ta_bucket_n * 2) -#define SHOULD_TABLE_SHRINK(tab) ((tab)->ta_entry_n < (tab)->ta_bucket_n / 2) - -/* - * void HASH_MIX - * - * DESCRIPTION: - * - * Mix 3 32-bit values reversibly. For every delta with one or two - * bits set, and the deltas of all three high bits or all three low - * bits, whether the original value of a,b,c is almost all zero or is - * uniformly distributed. - * - * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c - * have at least 1/4 probability of changing. If mix() is run - * forward, every bit of c will change between 1/3 and 2/3 of the - * time. (Well, 22/100 and 78/100 for some 2-bit deltas.) - * - * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a - * superscalar machine (like a Pentium or a Sparc). No faster mixer - * seems to work, that's the result of my brute-force search. There - * were about 2^68 hashes to choose from. I only tested about a - * billion of those. - */ -#define HASH_MIX(a, b, c) \ - do { \ - a -= b; a -= c; a ^= (c >> 13); \ - b -= c; b -= a; b ^= (a << 8); \ - c -= a; c -= b; c ^= (b >> 13); \ - a -= b; a -= c; a ^= (c >> 12); \ - b -= c; b -= a; b ^= (a << 16); \ - c -= a; c -= b; c ^= (b >> 5); \ - a -= b; a -= c; a ^= (c >> 3); \ - b -= c; b -= a; b ^= (a << 10); \ - c -= a; c -= b; c ^= (b >> 15); \ - } while(0) - -#define SET_POINTER(pnt, val) \ - do { \ - if ((pnt) != NULL) { \ - (*(pnt)) = (val); \ - } \ - } while(0) - -/* - * The following macros take care of the mmap case. When we are - * mmaping a table from a disk file, all of the pointers in the table - * structures are replaced with offsets into the file. The following - * macro, for each pointer, adds the starting address of the mmaped - * section onto each pointer/offset turning it back into a legitimate - * pointer. - */ -#ifdef NO_MMAP - -#define TABLE_POINTER(table, type, pnt) (pnt) - -#else - -#define TABLE_POINTER(tab_p, type, pnt) \ - ((tab_p)->ta_mmap == NULL || (pnt) == NULL ? (pnt) : \ - (type)((char *)((tab_p)->ta_mmap) + (long)(pnt))) - -#endif - -/* - * Macros to get at the key and the data pointers - */ -#define ENTRY_KEY_BUF(entry_p) ((entry_p)->te_key_buf) -#define ENTRY_DATA_BUF(tab_p, entry_p) \ - (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size) - -/* - * Table structures... - */ - -/* - * HACK: this should be equiv as the table_entry_t without the key_buf - * char. We use this with the ENTRY_SIZE() macro above which solves - * the problem with the lack of the [0] GNU hack. We use the - * table_entry_t structure to better map the memory and make things - * faster. - */ -typedef struct table_shell_st { - unsigned int te_key_size; /* size of data */ - unsigned int te_data_size; /* size of data */ - struct table_shell_st *te_next_p; /* pointer to next in the list */ - /* NOTE: this does not have the te_key_buf field here */ -} table_shell_t; - -/* - * Elements in the bucket linked-lists. The key[1] is the start of - * the key with the rest of the key and all of the data information - * packed in memory directly after the end of this structure. - * - * NOTE: if this structure is changed, the table_shell_t must be - * changed to match. - */ -typedef struct table_entry_st { - unsigned int te_key_size; /* size of data */ - unsigned int te_data_size; /* size of data */ - struct table_entry_st *te_next_p; /* pointer to next in the list */ - unsigned char te_key_buf[1]; /* 1st byte of key buf */ -} table_entry_t; - -/* external structure for debuggers be able to see void */ -typedef table_entry_t table_entry_ext_t; - -/* main table structure */ -typedef struct table_st { - unsigned int ta_magic; /* magic number */ - unsigned int ta_flags; /* table's flags defined in table.h */ - unsigned int ta_bucket_n; /* num of buckets, should be 2^X */ - unsigned int ta_entry_n; /* num of entries in all buckets */ - unsigned int ta_data_align; /* data alignment value */ - table_entry_t **ta_buckets; /* array of linked lists */ - table_linear_t ta_linear; /* linear tracking */ - struct table_st *ta_mmap; /* mmaped table */ - unsigned long ta_file_size; /* size of on-disk space */ - - void *ta_mem_pool; /* pointer to some memory pool */ - table_mem_alloc_t ta_alloc_func; /* memory allocation function */ - table_mem_resize_t ta_resize_func; /* memory resize function */ - table_mem_free_t ta_free_func; /* memory free function */ -} table_t; - -/* external table structure for debuggers */ -typedef table_t table_ext_t; - -/* local comparison functions */ -typedef int (*compare_t)(const void *element1_p, const void *element2_p, - table_compare_t user_compare, - const table_t *table_p, int *err_bp); - -/* - * to map error to string - */ -typedef struct { - int es_error; /* error number */ - char *es_string; /* assocaited string */ -} error_str_t; - -static error_str_t errors[] = { - { TABLE_ERROR_NONE, "no error" }, - { TABLE_ERROR_PNT, "invalid table pointer" }, - { TABLE_ERROR_ARG_NULL, "buffer argument is null" }, - { TABLE_ERROR_SIZE, "incorrect size argument" }, - { TABLE_ERROR_OVERWRITE, "key exists and no overwrite" }, - { TABLE_ERROR_NOT_FOUND, "key does not exist" }, - { TABLE_ERROR_ALLOC, "error allocating memory" }, - { TABLE_ERROR_LINEAR, "linear access not in progress" }, - { TABLE_ERROR_OPEN, "could not open file" }, - { TABLE_ERROR_SEEK, "could not seek to position in file" }, - { TABLE_ERROR_READ, "could not read from file" }, - { TABLE_ERROR_WRITE, "could not write to file" }, - { TABLE_ERROR_MMAP_NONE, "no mmap support compiled in library" }, - { TABLE_ERROR_MMAP, "could not mmap the file" }, - { TABLE_ERROR_MMAP_OP, "operation not valid on mmap files" }, - { TABLE_ERROR_EMPTY, "table is empty" }, - { TABLE_ERROR_NOT_EMPTY, "table contains data" }, - { TABLE_ERROR_ALIGNMENT, "invalid alignment value" }, - { TABLE_ERROR_COMPARE, "problems with internal comparison" }, - { TABLE_ERROR_FREE, "memory free error" }, - { 0 } -}; - -#define INVALID_ERROR "invalid error code" - -#endif /* ! __TABLE_LOC_H__ */ - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ - diff --git a/libs/libks/src/ks.c b/libs/libks/src/ks.c deleted file mode 100644 index 2747bd43e9..0000000000 --- a/libs/libks/src/ks.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* Use select on windows and poll everywhere else. - Select is the devil. Especially if you are doing a lot of small socket connections. - If your FD number is bigger than 1024 you will silently create memory corruption. - - If you have build errors on your platform because you don't have poll find a way to detect it and #define KS_USE_SELECT and #undef KS_USE_POLL - All of this will be upgraded to autoheadache eventually. -*/ - -/* TBD for win32 figure out how to tell if you have WSAPoll (vista or higher) and use it when available by #defining KS_USE_WSAPOLL (see below) */ - -#ifdef _MSC_VER -#define FD_SETSIZE 8192 -#define KS_USE_SELECT -#else -#define KS_USE_POLL -#endif - -#include -#ifndef WIN32 -#define closesocket(x) shutdown(x, 2); close(x) -#include -#include -#else -#pragma warning (disable:6386) -/* These warnings need to be ignored warning in sdk header */ -#include -#include -#pragma comment(lib, "Ws2_32.lib") -#ifndef errno -#define errno WSAGetLastError() -#endif -#ifndef EINTR -#define EINTR WSAEINTR -#endif -#pragma warning (default:6386) -#endif - -#ifdef KS_USE_POLL -#include -#endif - -#ifndef KS_MIN -#define KS_MIN(x,y) ((x) < (y) ? (x) : (y)) -#endif -#ifndef KS_MAX -#define KS_MAX(x,y) ((x) > (y) ? (x) : (y)) -#endif -#ifndef KS_CLAMP -#define KS_CLAMP(min,max,val) (KS_MIN(max,KS_MAX(val,min))) -#endif - - -/* Written by Marc Espie, public domain */ -#define KS_CTYPE_NUM_CHARS 256 - -const short _ks_C_toupper_[1 + KS_CTYPE_NUM_CHARS] = { - EOF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -const short *_ks_toupper_tab_ = _ks_C_toupper_; - -KS_DECLARE(int) ks_toupper(int c) -{ - if ((unsigned int)c > 255) - return(c); - if (c < -1) - return EOF; - return((_ks_toupper_tab_ + 1)[c]); -} - -const short _ks_C_tolower_[1 + KS_CTYPE_NUM_CHARS] = { - EOF, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -const short *_ks_tolower_tab_ = _ks_C_tolower_; - -KS_DECLARE(int) ks_tolower(int c) -{ - if ((unsigned int)c > 255) - return(c); - if (c < -1) - return EOF; - return((_ks_tolower_tab_ + 1)[c]); -} - -KS_DECLARE(const char *)ks_stristr(const char *instr, const char *str) -{ -/* -** Rev History: 16/07/97 Greg Thayer Optimized -** 07/04/95 Bob Stout ANSI-fy -** 02/03/94 Fred Cole Original -** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback -** -** Hereby donated to public domain. -*/ - const char *pptr, *sptr, *start; - - if (!str || !instr) - return NULL; - - for (start = str; *start; start++) { - /* find start of pattern in string */ - for (; ((*start) && (ks_toupper(*start) != ks_toupper(*instr))); start++); - - if (!*start) - return NULL; - - pptr = instr; - sptr = start; - - while (ks_toupper(*sptr) == ks_toupper(*pptr)) { - sptr++; - pptr++; - - /* if end of pattern then pattern was found */ - if (!*pptr) - return (start); - - if (!*sptr) - return NULL; - } - } - return NULL; -} - -#ifdef WIN32 -#ifndef vsnprintf -#define vsnprintf _vsnprintf -#endif -#endif - - -int vasprintf(char **ret, const char *format, va_list ap); - -KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap) -{ -#if !defined(WIN32) && !defined(__sun) - return vasprintf(ret, fmt, ap); -#else - char *buf; - int len; - size_t buflen; - va_list ap2; - char *tmp = NULL; - -#ifdef _MSC_VER -#if _MSC_VER >= 1500 - /* hack for incorrect assumption in msvc header files for code analysis */ - __analysis_assume(tmp); -#endif - ap2 = ap; -#else - va_copy(ap2, ap); -#endif - - len = vsnprintf(tmp, 0, fmt, ap2); - - if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) { - len = vsnprintf(buf, buflen, fmt, ap); - *ret = buf; - } else { - *ret = NULL; - len = -1; - } - - va_end(ap2); - return len; -#endif -} - - - - -KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vsnprintf(buffer, count-1, fmt, ap); - if (ret < 0) - buffer[count-1] = '\0'; - va_end(ap); - return ret; -} - -static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) -{ - if (file && func && line && level && fmt) { - return; - } - return; -} - - -static const char *LEVEL_NAMES[] = { - "EMERG", - "ALERT", - "CRIT", - "ERROR", - "WARNING", - "NOTICE", - "INFO", - "DEBUG", - NULL -}; - -static int ks_log_level = 7; - -static const char *cut_path(const char *in) -{ - const char *p, *ret = in; - char delims[] = "/\\"; - char *i; - - for (i = delims; *i; i++) { - p = in; - while ((p = strchr(p, *i)) != 0) { - ret = ++p; - } - } - return ret; -} - - -static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) -{ - const char *fp; - char *data; - va_list ap; - int ret; - - if (level < 0 || level > 7) { - level = 7; - } - if (level > ks_log_level) { - return; - } - - fp = cut_path(file); - - va_start(ap, fmt); - - ret = ks_vasprintf(&data, fmt, ap); - - if (ret != -1) { - fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data); - free(data); - } - - va_end(ap); - -} - -ks_logger_t ks_log = null_logger; - -KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger) -{ - if (logger) { - ks_log = logger; - } else { - ks_log = null_logger; - } -} - -KS_DECLARE(void) ks_global_set_default_logger(int level) -{ - if (level < 0 || level > 7) { - level = 7; - } - - ks_log = default_logger; - ks_log_level = level; -} - -KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len) -{ - const char *p; - size_t x = 0; - const char urlunsafe[] = "\r\n \"#%&+:;<=>?@[\\]^`{|}"; - const char hex[] = "0123456789ABCDEF"; - - if (!buf) { - return 0; - } - - if (!url) { - return 0; - } - - len--; - - for (p = url; *p; p++) { - if (x >= len) { - break; - } - if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)) { - if ((x + 3) >= len) { - break; - } - buf[x++] = '%'; - buf[x++] = hex[*p >> 4]; - buf[x++] = hex[*p & 0x0f]; - } else { - buf[x++] = *p; - } - } - buf[x] = '\0'; - - return x; -} - -KS_DECLARE(char *)ks_url_decode(char *s) -{ - char *o; - unsigned int tmp; - - for (o = s; *s; s++, o++) { - if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) { - *o = (char) tmp; - s += 2; - } else { - *o = *s; - } - } - *o = '\0'; - return s; -} - - -static int ks_socket_reuseaddr(ks_socket_t socket) -{ -#ifdef WIN32 - BOOL reuse_addr = TRUE; - return setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse_addr, sizeof(reuse_addr)); -#else - int reuse_addr = 1; - return setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); -#endif -} - - -struct thread_handler { - ks_listen_callback_t callback; - ks_socket_t server_sock; - ks_socket_t client_sock; - struct sockaddr_in addr; -}; - -static void *client_thread(ks_thread_t *me, void *obj) -{ - struct thread_handler *handler = (struct thread_handler *) obj; - - handler->callback(handler->server_sock, handler->client_sock, &handler->addr); - free(handler); - - return NULL; - -} - -KS_DECLARE(ks_status_t) ks_listen(const char *host, ks_port_t port, ks_listen_callback_t callback) -{ - ks_socket_t server_sock = KS_SOCK_INVALID; - struct sockaddr_in addr; - ks_status_t status = KS_SUCCESS; - - if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - return KS_FAIL; - } - - ks_socket_reuseaddr(server_sock); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port); - - if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - status = KS_FAIL; - goto end; - } - - if (listen(server_sock, 10000) < 0) { - status = KS_FAIL; - goto end; - } - - for (;;) { - int client_sock; - struct sockaddr_in echoClntAddr; -#ifdef WIN32 - int clntLen; -#else - unsigned int clntLen; -#endif - - clntLen = sizeof(echoClntAddr); - - if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == KS_SOCK_INVALID) { - status = KS_FAIL; - goto end; - } - - callback(server_sock, client_sock, &echoClntAddr); - } - - end: - - if (server_sock != KS_SOCK_INVALID) { - closesocket(server_sock); - server_sock = KS_SOCK_INVALID; - } - - return status; - -} - -KS_DECLARE(ks_status_t) ks_listen_threaded(const char *host, ks_port_t port, ks_listen_callback_t callback, int max) -{ - ks_socket_t server_sock = KS_SOCK_INVALID; - struct sockaddr_in addr; - ks_status_t status = KS_SUCCESS; - struct thread_handler *handler = NULL; - - if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - return KS_FAIL; - } - - ks_socket_reuseaddr(server_sock); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port); - - if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - status = KS_FAIL; - goto end; - } - - if (listen(server_sock, max) < 0) { - status = KS_FAIL; - goto end; - } - - for (;;) { - int client_sock; - struct sockaddr_in echoClntAddr; -#ifdef WIN32 - int clntLen; -#else - unsigned int clntLen; -#endif - - clntLen = sizeof(echoClntAddr); - - if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == KS_SOCK_INVALID) { - status = KS_FAIL; - goto end; - } - - handler = malloc(sizeof(*handler)); - ks_assert(handler); - - memset(handler, 0, sizeof(*handler)); - handler->callback = callback; - handler->server_sock = server_sock; - handler->client_sock = client_sock; - handler->addr = echoClntAddr; - - ks_thread_create_detached(client_thread, handler); - } - - end: - - if (server_sock != KS_SOCK_INVALID) { - closesocket(server_sock); - server_sock = KS_SOCK_INVALID; - } - - return status; - -} - - -/* USE WSAPoll on vista or higher */ -#ifdef KS_USE_WSAPOLL -KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags) -{ -} -#endif - - -#ifdef KS_USE_SELECT -#ifdef WIN32 -#pragma warning( push ) -#pragma warning( disable : 6262 ) /* warning C6262: Function uses '98348' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap */ -#endif -KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags) -{ - int s = 0, r = 0; - fd_set rfds; - fd_set wfds; - fd_set efds; - struct timeval tv; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&efds); - -#ifndef WIN32 - /* Wouldn't you rather know?? */ - assert(sock <= FD_SETSIZE); -#endif - - if ((flags & KS_POLL_READ)) { - -#ifdef WIN32 -#pragma warning( push ) -#pragma warning( disable : 4127 ) - FD_SET(sock, &rfds); -#pragma warning( pop ) -#else - FD_SET(sock, &rfds); -#endif - } - - if ((flags & KS_POLL_WRITE)) { - -#ifdef WIN32 -#pragma warning( push ) -#pragma warning( disable : 4127 ) - FD_SET(sock, &wfds); -#pragma warning( pop ) -#else - FD_SET(sock, &wfds); -#endif - } - - if ((flags & KS_POLL_ERROR)) { - -#ifdef WIN32 -#pragma warning( push ) -#pragma warning( disable : 4127 ) - FD_SET(sock, &efds); -#pragma warning( pop ) -#else - FD_SET(sock, &efds); -#endif - } - - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * ms; - - s = select(sock + 1, (flags & KS_POLL_READ) ? &rfds : NULL, (flags & KS_POLL_WRITE) ? &wfds : NULL, (flags & KS_POLL_ERROR) ? &efds : NULL, &tv); - - if (s < 0) { - r = s; - } else if (s > 0) { - if ((flags & KS_POLL_READ) && FD_ISSET(sock, &rfds)) { - r |= KS_POLL_READ; - } - - if ((flags & KS_POLL_WRITE) && FD_ISSET(sock, &wfds)) { - r |= KS_POLL_WRITE; - } - - if ((flags & KS_POLL_ERROR) && FD_ISSET(sock, &efds)) { - r |= KS_POLL_ERROR; - } - } - - return r; - -} -#ifdef WIN32 -#pragma warning( pop ) -#endif -#endif - -#ifdef KS_USE_POLL -KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags) -{ - struct pollfd pfds[2] = { { 0 } }; - int s = 0, r = 0; - - pfds[0].fd = sock; - - if ((flags & KS_POLL_READ)) { - pfds[0].events |= POLLIN; - } - - if ((flags & KS_POLL_WRITE)) { - pfds[0].events |= POLLOUT; - } - - if ((flags & KS_POLL_ERROR)) { - pfds[0].events |= POLLERR; - } - - s = poll(pfds, 1, ms); - - if (s < 0) { - r = s; - } else if (s > 0) { - if ((pfds[0].revents & POLLIN)) { - r |= KS_POLL_READ; - } - if ((pfds[0].revents & POLLOUT)) { - r |= KS_POLL_WRITE; - } - if ((pfds[0].revents & POLLERR)) { - r |= KS_POLL_ERROR; - } - } - - return r; - -} -#endif - - -KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen) -{ - unsigned int count = 0; - char *d; - size_t dlen = strlen(delim); - - array[count++] = buf; - - while (count < arraylen && array[count - 1]) { - if ((d = strstr(array[count - 1], delim))) { - *d = '\0'; - d += dlen; - array[count++] = d; - } else - break; - } - - return count; -} - diff --git a/libs/libks/src/ks_buffer.c b/libs/libks/src/ks_buffer.c deleted file mode 100644 index b78584e984..0000000000 --- a/libs/libks/src/ks_buffer.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2010-2012, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "ks_buffer.h" - -static unsigned buffer_id = 0; - -struct ks_buffer { - unsigned char *data; - unsigned char *head; - ks_size_t used; - ks_size_t actually_used; - ks_size_t datalen; - ks_size_t max_len; - ks_size_t blocksize; - unsigned id; - int loops; -}; - - -KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksize, ks_size_t start_len, ks_size_t max_len) -{ - ks_buffer_t *new_buffer; - - new_buffer = malloc(sizeof(*new_buffer)); - if (new_buffer) { - memset(new_buffer, 0, sizeof(*new_buffer)); - - if (start_len) { - new_buffer->data = malloc(start_len); - if (!new_buffer->data) { - free(new_buffer); - return KS_FAIL; - } - memset(new_buffer->data, 0, start_len); - } - - new_buffer->max_len = max_len; - new_buffer->datalen = start_len; - new_buffer->id = buffer_id++; - new_buffer->blocksize = blocksize; - new_buffer->head = new_buffer->data; - - *buffer = new_buffer; - return KS_SUCCESS; - } - - return KS_FAIL; -} - -KS_DECLARE(ks_size_t) ks_buffer_len(ks_buffer_t *buffer) -{ - - ks_assert(buffer != NULL); - - return buffer->datalen; - -} - - -KS_DECLARE(ks_size_t) ks_buffer_freespace(ks_buffer_t *buffer) -{ - ks_assert(buffer != NULL); - - if (buffer->max_len) { - return (ks_size_t) (buffer->max_len - buffer->used); - } - return 1000000; - -} - -KS_DECLARE(ks_size_t) ks_buffer_inuse(ks_buffer_t *buffer) -{ - ks_assert(buffer != NULL); - - return buffer->used; -} - -KS_DECLARE(ks_size_t) ks_buffer_seek(ks_buffer_t *buffer, ks_size_t datalen) -{ - ks_size_t reading = 0; - - ks_assert(buffer != NULL); - - if (buffer->used < 1) { - buffer->used = 0; - return 0; - } else if (buffer->used >= datalen) { - reading = datalen; - } else { - reading = buffer->used; - } - - buffer->used = buffer->actually_used - reading; - buffer->head = buffer->data + reading; - - return reading; -} - -KS_DECLARE(ks_size_t) ks_buffer_toss(ks_buffer_t *buffer, ks_size_t datalen) -{ - ks_size_t reading = 0; - - ks_assert(buffer != NULL); - - if (buffer->used < 1) { - buffer->used = 0; - return 0; - } else if (buffer->used >= datalen) { - reading = datalen; - } else { - reading = buffer->used; - } - - buffer->used -= reading; - buffer->head += reading; - - return buffer->used; -} - -KS_DECLARE(void) ks_buffer_set_loops(ks_buffer_t *buffer, int loops) -{ - buffer->loops = loops; -} - -KS_DECLARE(ks_size_t) ks_buffer_read_loop(ks_buffer_t *buffer, void *data, ks_size_t datalen) -{ - ks_size_t len; - if ((len = ks_buffer_read(buffer, data, datalen)) < datalen) { - if (buffer->loops == 0) { - return len; - } - buffer->head = buffer->data; - buffer->used = buffer->actually_used; - len = ks_buffer_read(buffer, (char*)data + len, datalen - len); - buffer->loops--; - } - return len; -} - -KS_DECLARE(ks_size_t) ks_buffer_read(ks_buffer_t *buffer, void *data, ks_size_t datalen) -{ - ks_size_t reading = 0; - - ks_assert(buffer != NULL); - ks_assert(data != NULL); - - - if (buffer->used < 1) { - buffer->used = 0; - return 0; - } else if (buffer->used >= datalen) { - reading = datalen; - } else { - reading = buffer->used; - } - - memcpy(data, buffer->head, reading); - buffer->used -= reading; - buffer->head += reading; - - /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */ - return reading; -} - - -KS_DECLARE(ks_size_t) ks_buffer_packet_count(ks_buffer_t *buffer) -{ - char *pe, *p, *e, *head = (char *) buffer->head; - ks_size_t x = 0; - - ks_assert(buffer != NULL); - - e = (head + buffer->used); - - for (p = head; p && *p && p < e; p++) { - if (*p == '\n') { - pe = p+1; - if (*pe == '\r') pe++; - if (pe <= e && *pe == '\n') { - p = pe++; - x++; - } - } - } - - return x; -} - -KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_size_t maxlen) -{ - char *pe, *p, *e, *head = (char *) buffer->head; - ks_size_t datalen = 0; - - ks_assert(buffer != NULL); - ks_assert(data != NULL); - - e = (head + buffer->used); - - for (p = head; p && *p && p < e; p++) { - if (*p == '\n') { - pe = p+1; - if (*pe == '\r') pe++; - if (pe <= e && *pe == '\n') { - pe++; - datalen = pe - head; - if (datalen > maxlen) { - datalen = maxlen; - } - break; - } - } - } - - return ks_buffer_read(buffer, data, datalen); -} - -KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_size_t datalen) -{ - ks_size_t freespace, actual_freespace; - - ks_assert(buffer != NULL); - ks_assert(data != NULL); - ks_assert(buffer->data != NULL); - - if (!datalen) { - return buffer->used; - } - - actual_freespace = buffer->datalen - buffer->actually_used; - if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) { - memmove(buffer->data, buffer->head, buffer->used); - buffer->head = buffer->data; - buffer->actually_used = buffer->used; - } - - freespace = buffer->datalen - buffer->used; - - /* - if (buffer->data != buffer->head) { - memmove(buffer->data, buffer->head, buffer->used); - buffer->head = buffer->data; - } - */ - - if (freespace < datalen) { - ks_size_t new_size, new_block_size; - void *data1; - - new_size = buffer->datalen + datalen; - new_block_size = buffer->datalen + buffer->blocksize; - - if (new_block_size > new_size) { - new_size = new_block_size; - } - buffer->head = buffer->data; - data1 = realloc(buffer->data, new_size); - if (!data1) { - return 0; - } - buffer->data = data1; - buffer->head = buffer->data; - buffer->datalen = new_size; - } - - - freespace = buffer->datalen - buffer->used; - - if (freespace < datalen) { - return 0; - } else { - memcpy(buffer->head + buffer->used, data, datalen); - buffer->used += datalen; - buffer->actually_used += datalen; - } - /* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */ - - return buffer->used; -} - -KS_DECLARE(void) ks_buffer_zero(ks_buffer_t *buffer) -{ - ks_assert(buffer != NULL); - ks_assert(buffer->data != NULL); - - buffer->used = 0; - buffer->actually_used = 0; - buffer->head = buffer->data; -} - -KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen) -{ - ks_size_t w; - - if (!(w = ks_buffer_write(buffer, data, datalen))) { - ks_buffer_zero(buffer); - return ks_buffer_write(buffer, data, datalen); - } - - return w; -} - -KS_DECLARE(void) ks_buffer_destroy(ks_buffer_t **buffer) -{ - if (*buffer) { - free((*buffer)->data); - free(*buffer); - } - - *buffer = NULL; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/ks_config.c b/libs/libks/src/ks_config.c deleted file mode 100644 index 3b25dd1634..0000000000 --- a/libs/libks/src/ks_config.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2007-2014, Anthony Minessale II - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the original author; nor the names of any contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ks.h" -#include "ks_config.h" - -KS_DECLARE(int) ks_config_open_file(ks_config_t *cfg, const char *file_path) -{ - FILE *f; - const char *path = NULL; - char path_buf[1024]; - - if (file_path[0] == '/') { - path = file_path; - } else { - ks_snprintf(path_buf, sizeof(path_buf), "%s%s%s", KS_CONFIG_DIR, KS_PATH_SEPARATOR, file_path); - path = path_buf; - } - - if (!path) { - return 0; - } - - memset(cfg, 0, sizeof(*cfg)); - cfg->lockto = -1; - ks_log(KS_LOG_DEBUG, "Configuration file is %s.\n", path); - f = fopen(path, "r"); - - if (!f) { - if (file_path[0] != '/') { - int last = -1; - char *var, *val; - - ks_snprintf(path_buf, sizeof(path_buf), "%s%sopenks.conf", KS_CONFIG_DIR, KS_PATH_SEPARATOR); - path = path_buf; - - if ((f = fopen(path, "r")) == 0) { - return 0; - } - - cfg->file = f; - ks_set_string(cfg->path, path); - - while (ks_config_next_pair(cfg, &var, &val)) { - if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) { - cfg->lockto = cfg->sectno; - return 1; - } - } - - ks_config_close_file(cfg); - memset(cfg, 0, sizeof(*cfg)); - return 0; - } - - return 0; - } else { - cfg->file = f; - ks_set_string(cfg->path, path); - return 1; - } -} - -KS_DECLARE(void) ks_config_close_file(ks_config_t *cfg) -{ - - if (cfg->file) { - fclose(cfg->file); - } - - memset(cfg, 0, sizeof(*cfg)); -} - - - -KS_DECLARE(int) ks_config_next_pair(ks_config_t *cfg, char **var, char **val) -{ - int ret = 0; - char *p, *end; - - *var = *val = NULL; - - if (!cfg || !cfg->file) { - return 0; - } - - for (;;) { - cfg->lineno++; - - if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) { - ret = 0; - break; - } - *var = cfg->buf; - - if (**var == '[' && (end = strchr(*var, ']')) != 0) { - *end = '\0'; - (*var)++; - if (**var == '+') { - (*var)++; - ks_copy_string(cfg->section, *var, sizeof(cfg->section)); - cfg->sectno++; - - if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) { - break; - } - cfg->catno = 0; - cfg->lineno = 0; - *var = (char *) ""; - *val = (char *) ""; - return 1; - } else { - ks_copy_string(cfg->category, *var, sizeof(cfg->category)); - cfg->catno++; - } - continue; - } - - - - if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') { - continue; - } - - if (!strncmp(*var, "__END__", 7)) { - break; - } - - - if ((end = strchr(*var, ';')) && *(end+1) == *end) { - *end = '\0'; - end--; - } else if ((end = strchr(*var, '\n')) != 0) { - if (*(end - 1) == '\r') { - end--; - } - *end = '\0'; - } - - p = *var; - while ((*p == ' ' || *p == '\t') && p != end) { - *p = '\0'; - p++; - } - *var = p; - - - if ((*val = strchr(*var, '=')) == 0) { - ret = -1; - /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */ - continue; - } else { - p = *val - 1; - *(*val) = '\0'; - (*val)++; - if (*(*val) == '>') { - *(*val) = '\0'; - (*val)++; - } - - while ((*p == ' ' || *p == '\t') && p != *var) { - *p = '\0'; - p--; - } - - p = *val; - while ((*p == ' ' || *p == '\t') && p != end) { - *p = '\0'; - p++; - } - *val = p; - ret = 1; - break; - } - } - - - return ret; - -} - -KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits) -{ - char cas_bits[5]; - unsigned char bit = 0x8; - char *double_colon = strchr(strvalue, ':'); - int x = 0; - - if (!double_colon) { - ks_log(KS_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); - return -1; - } - - double_colon++; - *outbits = 0; - cas_bits[4] = 0; - - if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) { - ks_log(KS_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); - return -1; - } - - ks_log(KS_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits); - - for (; cas_bits[x]; x++) { - if ('1' == cas_bits[x]) { - *outbits |= bit; - } else if ('0' != cas_bits[x]) { - ks_log(KS_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n"); - return -1; - } - bit >>= 1; - } - return 0; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/ks_json.c b/libs/libks/src/ks_json.c deleted file mode 100644 index 4ee4a84ef6..0000000000 --- a/libs/libks/src/ks_json.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -#include -#include -#include -#include -#include -#include -#include -#include "ks_json.h" -#include "ks.h" - -static const char *ep; - -KS_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;} - -static int cJSON_strcasecmp(const char *s1,const char *s2) -{ - if (!s1) return (s1==s2)?0:1;if (!s2) return 1; - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); -} - -static void *glue_malloc(size_t theSize) -{ - return(malloc(theSize)); -} - -static void glue_free(void *thePtr) -{ - free(thePtr); -} - -static void *(*cJSON_malloc)(size_t sz) = glue_malloc; -static void (*cJSON_free)(void *ptr) = glue_free; - -static char* cJSON_strdup(const char* str) -{ - size_t len; - char* copy; - const char *s = str ? str : ""; - - len = strlen(s) + 1; - if (!(copy = (char*)cJSON_malloc(len))) return 0; - memcpy(copy,s,len); - return copy; -} - -KS_DECLARE(void)cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (!hooks) { /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_free = free; - return; - } - - cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_free = (hooks->free_fn)?hooks->free_fn:free; -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item() -{ - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) memset(node,0,sizeof(cJSON)); - return node; -} - -/* Delete a cJSON structure. */ -KS_DECLARE(void)cJSON_Delete(cJSON *c) -{ - cJSON *next; - while (c) - { - next=c->next; - if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); - if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); - if (c->string) cJSON_free(c->string); - cJSON_free(c); - c=next; - } -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item,const char *num) -{ - double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; - - /* Could use sscanf for this? */ - if (*num=='-') sign=-1,num++; /* Has sign? */ - if (*num=='0') num++; /* is zero */ - if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ - if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ - if (*num=='e' || *num=='E') /* Exponent? */ - { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ - while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ - } - - n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ - - item->valuedouble=n; - item->valueint=(int)n; - item->type=cJSON_Number; - return num; -} - -/* Render the number nicely from the given item into a string. */ -static char *print_number(cJSON *item) -{ - char *str; - double d=item->valuedouble; - if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) - { - str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ - if (str) sprintf(str,"%d",item->valueint); - } - else - { - str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ - if (str) - { - if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d); - else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); - else sprintf(str,"%f",d); - } - } - return str; -} - -#define is_hexdigit(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) -static int scan_unicode(const char *ptr, unsigned int *uc) -{ - if (!is_hexdigit(*(ptr)) || !is_hexdigit(*(ptr+1)) || !is_hexdigit(*(ptr+2)) || !is_hexdigit(*(ptr+3))) return -1; - return sscanf(ptr, "%4x", uc); -} - -/* Parse the input text into an unescaped cstring, and populate item. */ -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -static const char *parse_string(cJSON *item,const char *str) -{ - const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; - if (*str!='\"') {ep=str;return 0;} /* not a string! */ - - while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ - - out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ - if (!out) return 0; - - ptr=str+1;ptr2=out; - while (*ptr!='\"' && *ptr) - { - if (*ptr!='\\') *ptr2++=*ptr++; - else - { - ptr++; - switch (*ptr) - { - case 'b': *ptr2++='\b'; break; - case 'f': *ptr2++='\f'; break; - case 'n': *ptr2++='\n'; break; - case 'r': *ptr2++='\r'; break; - case 't': *ptr2++='\t'; break; - case 'u': /* transcode utf16 to utf8. */ - if (scan_unicode(ptr+1, &uc) < 1) break; - ptr+=4; /* get the unicode char. */ - - if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid. - - if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs. - { - if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate. - if (scan_unicode(ptr+3,&uc2) < 1) break; - ptr+=6; - if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate. - uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF); - } - - len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; - - switch (len) { - case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 1: *--ptr2 =(char)(uc | firstByteMark[len]); - } - ptr2+=len; - break; - default: *ptr2++=*ptr; break; - } - if (*ptr) ptr++; - } - } - *ptr2=0; - if (*ptr=='\"') ptr++; - item->valuestring=out; - item->type=cJSON_String; - return ptr; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static char *print_string_ptr(const char *str) -{ - const char *ptr;char *ptr2,*out;int len=0;unsigned char token; - - if (!str) return cJSON_strdup(""); - ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} - - out=(char*)cJSON_malloc(len+3); - if (!out) return 0; - - ptr2=out;ptr=str; - *ptr2++='\"'; - while (*ptr) - { - if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; - else - { - *ptr2++='\\'; - switch (token=*ptr++) - { - case '\\': *ptr2++='\\'; break; - case '\"': *ptr2++='\"'; break; - case '\b': *ptr2++='b'; break; - case '\f': *ptr2++='f'; break; - case '\n': *ptr2++='n'; break; - case '\r': *ptr2++='r'; break; - case '\t': *ptr2++='t'; break; - default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ - } - } - } - *ptr2++='\"';*ptr2++=0; - return out; -} -/* Invote print_string_ptr (which is useful) on an item. */ -static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} - -/* Predeclare these prototypes. */ -static const char *parse_value(cJSON *item,const char *value); -static char *print_value(cJSON *item,int depth,int fmt); -static const char *parse_array(cJSON *item,const char *value); -static char *print_array(cJSON *item,int depth,int fmt); -static const char *parse_object(cJSON *item,const char *value); -static char *print_object(cJSON *item,int depth,int fmt); - -/* Utility to jump whitespace and cr/lf */ -static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} - -/* Parse an object - create a new root, and populate. */ -KS_DECLARE(cJSON *)cJSON_Parse(const char *value) -{ - cJSON *c=cJSON_New_Item(); - ep=0; - if (!c) return 0; /* memory fail */ - - if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;} - return c; -} - -/* Render a cJSON item/entity/structure to text. */ -KS_DECLARE(char *) cJSON_Print(cJSON *item) {return print_value(item,0,1);} -KS_DECLARE(char *) cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} - -/* Parser core - when encountering text, process appropriately. */ -static const char *parse_value(cJSON *item,const char *value) -{ - if (!value) return 0; /* Fail on null. */ - if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } - if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } - if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } - if (*value=='\"') { return parse_string(item,value); } - if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } - if (*value=='[') { return parse_array(item,value); } - if (*value=='{') { return parse_object(item,value); } - - ep=value;return 0; /* failure. */ -} - -/* Render a value to text. */ -static char *print_value(cJSON *item,int depth,int fmt) -{ - char *out=0; - if (!item) return 0; - switch ((item->type)&255) - { - case cJSON_NULL: out=cJSON_strdup("null"); break; - case cJSON_False: out=cJSON_strdup("false");break; - case cJSON_True: out=cJSON_strdup("true"); break; - case cJSON_Number: out=print_number(item);break; - case cJSON_String: out=print_string(item);break; - case cJSON_Array: out=print_array(item,depth,fmt);break; - case cJSON_Object: out=print_object(item,depth,fmt);break; - } - return out; -} - -/* Build an array from input text. */ -static const char *parse_array(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='[') {ep=value;return 0;} /* not an array! */ - - item->type=cJSON_Array; - value=skip(value+1); - if (*value==']') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; /* memory fail */ - value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item; - if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_value(child,skip(value+1))); - if (!value) return 0; /* memory fail */ - } - - if (*value==']') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an array to text */ -static char *print_array(cJSON *item,int depth,int fmt) -{ - char **entries; - char *out=0,*ptr,*ret;int len=5; - cJSON *child=item->child; - int numentries=0,i=0,fail=0; - - /* How many entries in the array? */ - while (child) numentries++,child=child->next; - /* Allocate an array to hold the values for each */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - memset(entries,0,numentries*sizeof(char*)); - /* Retrieve all the results: */ - child=item->child; - while (child && !fail) - { - ret=print_value(child,depth+1,fmt); - entries[i++]=ret; - if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; - child=child->next; - } - - /* If we didn't fail, try to malloc the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - /* If that fails, we fail. */ - if (!out) fail=1; - - /* Handle failure. */ - if (fail) - { - for (i=0;itype=cJSON_Object; - value=skip(value+1); - if (*value=='}') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; - value=skip(parse_string(child,skip(value))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item; - if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_string(child,skip(value+1))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - } - - if (*value=='}') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an object to text. */ -static char *print_object(cJSON *item,int depth,int fmt) -{ - char **entries=0,**names=0; - char *out=0,*ptr,*ret,*str;int len=7,i=0,j; - cJSON *child=item->child; - int numentries=0,fail=0; - /* Count the number of entries. */ - while (child) numentries++,child=child->next; - /* Allocate space for the names and the objects */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - names=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!names) {cJSON_free(entries);return 0;} - memset(entries,0,sizeof(char*)*numentries); - memset(names,0,sizeof(char*)*numentries); - - /* Collect all the results into our arrays: */ - child=item->child;depth++;if (fmt) len+=depth; - while (child) - { - names[i]=str=print_string_ptr(child->string); - entries[i++]=ret=print_value(child,depth,fmt); - if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; - child=child->next; - } - - /* Try to allocate the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - if (!out) fail=1; - - /* Handle failure */ - if (fail) - { - for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} -KS_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} -KS_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} -/* Utility for handling references. */ -static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} - -/* Add item to array/object. */ -KS_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} -KS_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} -KS_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} -KS_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} - -KS_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; - if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} -KS_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} -KS_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} -KS_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} - -/* Replace array/object items with new ones. */ -KS_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; - newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; - if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} -KS_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} - -/* Create basic types: */ -KS_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} -KS_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} -KS_DECLARE(cJSON *)cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} -KS_DECLARE(cJSON *)cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} -KS_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} -KS_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} -KS_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} -KS_DECLARE(cJSON *)cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} - -/* Create Arrays: */ -KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} -KS_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} -KS_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} -KS_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} diff --git a/libs/libks/src/ks_threadmutex.c b/libs/libks/src/ks_threadmutex.c deleted file mode 100644 index 414a07b6cb..0000000000 --- a/libs/libks/src/ks_threadmutex.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Cross Platform Thread/Mutex abstraction - * Copyright(C) 2007 Michael Jerris - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so. - * - * This work is provided under this license on an "as is" basis, without warranty of any kind, - * either expressed or implied, including, without limitation, warranties that the covered code - * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire - * risk as to the quality and performance of the covered code is with you. Should any covered - * code prove defective in any respect, you (not the initial developer or any other contributor) - * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty - * constitutes an essential part of this license. No use of any covered code is authorized hereunder - * except under this disclaimer. - * - */ - -#ifdef WIN32 -/* required for TryEnterCriticalSection definition. Must be defined before windows.h include */ -#define _WIN32_WINNT 0x0400 -#endif - -#include "ks.h" -#include "ks_threadmutex.h" - -#ifdef WIN32 -#include - -#define KS_THREAD_CALLING_CONVENTION __stdcall - -struct ks_mutex { - CRITICAL_SECTION mutex; -}; - -#else - -#include - -#define KS_THREAD_CALLING_CONVENTION - -struct ks_mutex { - pthread_mutex_t mutex; -}; - -#endif - -struct ks_thread { -#ifdef WIN32 - void *handle; -#else - pthread_t handle; -#endif - void *private_data; - ks_thread_function_t function; - size_t stack_size; -#ifndef WIN32 - pthread_attr_t attribute; -#endif -}; - -size_t thread_default_stacksize = 240 * 1024; - -void ks_thread_override_default_stacksize(size_t size) -{ - thread_default_stacksize = size; -} - -static void * KS_THREAD_CALLING_CONVENTION thread_launch(void *args) -{ - void *exit_val; - ks_thread_t *thread = (ks_thread_t *)args; - exit_val = thread->function(thread, thread->private_data); -#ifndef WIN32 - pthread_attr_destroy(&thread->attribute); -#endif - free(thread); - - return exit_val; -} - -KS_DECLARE(ks_status_t) ks_thread_create_detached(ks_thread_function_t func, void *data) -{ - return ks_thread_create_detached_ex(func, data, thread_default_stacksize); -} - -ks_status_t ks_thread_create_detached_ex(ks_thread_function_t func, void *data, size_t stack_size) -{ - ks_thread_t *thread = NULL; - ks_status_t status = KS_FAIL; - - if (!func || !(thread = (ks_thread_t *)malloc(sizeof(ks_thread_t)))) { - goto done; - } - - thread->private_data = data; - thread->function = func; - thread->stack_size = stack_size; - -#if defined(WIN32) - thread->handle = (void *)_beginthreadex(NULL, (unsigned)thread->stack_size, (unsigned int (__stdcall *)(void *))thread_launch, thread, 0, NULL); - if (!thread->handle) { - goto fail; - } - CloseHandle(thread->handle); - - status = KS_SUCCESS; - goto done; -#else - - if (pthread_attr_init(&thread->attribute) != 0) goto fail; - - if (pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0) goto failpthread; - - if (thread->stack_size && pthread_attr_setstacksize(&thread->attribute, thread->stack_size) != 0) goto failpthread; - - if (pthread_create(&thread->handle, &thread->attribute, thread_launch, thread) != 0) goto failpthread; - - status = KS_SUCCESS; - goto done; - - failpthread: - - pthread_attr_destroy(&thread->attribute); -#endif - - fail: - if (thread) { - free(thread); - } - done: - return status; -} - - -KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex) -{ - ks_status_t status = KS_FAIL; -#ifndef WIN32 - pthread_mutexattr_t attr; -#endif - ks_mutex_t *check = NULL; - - check = (ks_mutex_t *)malloc(sizeof(**mutex)); - if (!check) - goto done; -#ifdef WIN32 - InitializeCriticalSection(&check->mutex); -#else - if (pthread_mutexattr_init(&attr)) - goto done; - - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) - goto fail; - - if (pthread_mutex_init(&check->mutex, &attr)) - goto fail; - - goto success; - - fail: - pthread_mutexattr_destroy(&attr); - goto done; - - success: -#endif - *mutex = check; - status = KS_SUCCESS; - - done: - return status; -} - -KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutex) -{ - ks_mutex_t *mp = *mutex; - *mutex = NULL; - if (!mp) { - return KS_FAIL; - } -#ifdef WIN32 - DeleteCriticalSection(&mp->mutex); -#else - if (pthread_mutex_destroy(&mp->mutex)) - return KS_FAIL; -#endif - free(mp); - return KS_SUCCESS; -} - -KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex) -{ -#ifdef WIN32 - EnterCriticalSection(&mutex->mutex); -#else - if (pthread_mutex_lock(&mutex->mutex)) - return KS_FAIL; -#endif - return KS_SUCCESS; -} - -KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex) -{ -#ifdef WIN32 - if (!TryEnterCriticalSection(&mutex->mutex)) - return KS_FAIL; -#else - if (pthread_mutex_trylock(&mutex->mutex)) - return KS_FAIL; -#endif - return KS_SUCCESS; -} - -KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex) -{ -#ifdef WIN32 - LeaveCriticalSection(&mutex->mutex); -#else - if (pthread_mutex_unlock(&mutex->mutex)) - return KS_FAIL; -#endif - return KS_SUCCESS; -} - - - - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/mpool.c b/libs/libks/src/mpool.c deleted file mode 100644 index 31c7a166aa..0000000000 --- a/libs/libks/src/mpool.c +++ /dev/null @@ -1,1773 +0,0 @@ -/* - * Memory pool routines. - * - * Copyright 1996 by Gray Watson. - * - * This file is part of the mpool package. - * - * Permission to use, copy, modify, and distribute this software for - * any purpose and without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies, and that the name of Gray Watson not be used in advertising - * or publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $ - */ - -/* - * Memory-pool allocation routines. I got sick of the GNU mmalloc - * library which was close to what we needed but did not exactly do - * what I wanted. - * - * The following uses mmap from /dev/zero. It allows a number of - * allocations to be made inside of a memory pool then with a clear or - * close the pool can be reset without any memory fragmentation and - * growth problems. - */ - -#include -#include -#include -#include -#include -#ifdef _MSC_VER -#include -#ifndef open -#define open _open -#endif -#ifndef close -#define close _close -#endif -#else -#include -#endif -#include - -#ifdef DMALLOC -#include "dmalloc.h" -#endif - -#define MPOOL_MAIN - -#include "mpool.h" -#include "mpool_loc.h" - -#ifdef __GNUC__ -#ident "$Id: mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $" -#else -static char *rcs_id = "$Id: mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $"; -#endif - -/* version */ -static char *version = "mpool library version 2.1.0"; - -/* local variables */ -static int enabled_b = 0; /* lib initialized? */ -static unsigned int min_bit_free_next = 0; /* min size of next pnt */ -static unsigned int min_bit_free_size = 0; /* min size of next + size */ -static unsigned long bit_array[MAX_BITS + 1]; /* size -> bit */ - -#ifdef _MSC_VER -#include -long getpagesize(void) { - static long g_pagesize = 0; - if (!g_pagesize) { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - g_pagesize = system_info.dwPageSize; - } - return g_pagesize; -} -#endif -/****************************** local utilities ******************************/ - -/* - * static void startup - * - * DESCRIPTION: - * - * Perform any library level initialization. - * - * RETURNS: - * - * None. - * - * ARGUMENTS: - * - * None. - */ -static void startup(void) -{ - int bit_c; - unsigned long size = 1; - - if (enabled_b) { - return; - } - - /* allocate our free bit array list */ - for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) { - bit_array[bit_c] = size; - - /* - * Note our minimum number of bits that can store a pointer. This - * is smallest address that we can have a linked list for. - */ - if (min_bit_free_next == 0 && size >= sizeof(void *)) { - min_bit_free_next = bit_c; - } - /* - * Note our minimum number of bits that can store a pointer and - * the size of the block. - */ - if (min_bit_free_size == 0 && size >= sizeof(mpool_free_t)) { - min_bit_free_size = bit_c; - } - - size *= 2; - } - - enabled_b = 1; -} - -/* - * static int size_to_bits - * - * DESCRIPTION: - * - * Calculate the number of bits in a size. - * - * RETURNS: - * - * Number of bits. - * - * ARGUMENTS: - * - * size -> Size of memory of which to calculate the number of bits. - */ -static int size_to_bits(const unsigned long size) -{ - int bit_c = 0; - - for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) { - if (size <= bit_array[bit_c]) { - break; - } - } - - return bit_c; -} - -/* - * static int size_to_free_bits - * - * DESCRIPTION: - * - * Calculate the number of bits in a size going on the free list. - * - * RETURNS: - * - * Number of bits. - * - * ARGUMENTS: - * - * size -> Size of memory of which to calculate the number of bits. - */ -static int size_to_free_bits(const unsigned long size) -{ - int bit_c = 0; - - if (size == 0) { - return 0; - } - - for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) { - if (size < bit_array[bit_c]) { - break; - } - } - - return bit_c - 1; -} - -/* - * static int bits_to_size - * - * DESCRIPTION: - * - * Calculate the size represented by a number of bits. - * - * RETURNS: - * - * Number of bits. - * - * ARGUMENTS: - * - * bit_n -> Number of bits - */ -static unsigned long bits_to_size(const int bit_n) -{ - if (bit_n > MAX_BITS) { - return bit_array[MAX_BITS]; - } - else { - return bit_array[bit_n]; - } -} - -/* - * static void *alloc_pages - * - * DESCRIPTION: - * - * Allocate space for a number of memory pages in the memory pool. - * - * RETURNS: - * - * Success - New pages of memory - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to our memory pool. - * - * page_n -> Number of pages to alloc. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -static void *alloc_pages(mpool_t *mp_p, const unsigned int page_n, - int *error_p) -{ - void *mem; - unsigned long size; - int state; - - /* are we over our max-pages? */ - if (mp_p->mp_max_pages > 0 && mp_p->mp_page_c >= mp_p->mp_max_pages) { - SET_POINTER(error_p, MPOOL_ERROR_NO_PAGES); - return NULL; - } - - size = SIZE_OF_PAGES(mp_p, page_n); - -#ifdef DEBUG - (void)printf("allocating %u pages or %lu bytes\n", page_n, size); -#endif - - - state = MAP_PRIVATE; - -#if defined(MAP_FILE) - state |= MAP_FILE; -#endif - -#if defined(MAP_VARIABLE) - state |= MAP_VARIABLE; -#endif - - /* mmap from /dev/zero */ - mem = mmap(mp_p->mp_addr, size, PROT_READ | PROT_WRITE, state | mp_p->mp_mmflags, - mp_p->mp_fd, mp_p->mp_top); - if (mem == (void *)MAP_FAILED) { - if (errno == ENOMEM) { - SET_POINTER(error_p, MPOOL_ERROR_NO_MEM); - } else { - SET_POINTER(error_p, MPOOL_ERROR_MMAP); - } - return NULL; - } - - mp_p->mp_top += size; - - if (mp_p->mp_addr != NULL) { - mp_p->mp_addr = (char *)mp_p->mp_addr + size; - } - - mp_p->mp_page_c += page_n; - - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return mem; -} - -/* - * static int free_pages - * - * DESCRIPTION: - * - * Free previously allocated pages of memory. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * pages <-> Pointer to memory pages that we are freeing. - * - * size -> Size of the block that we are freeing. - * - * sbrk_b -> Set to one if the pages were allocated with sbrk else mmap. - */ -static int free_pages(void *pages, const unsigned long size) - -{ - (void)munmap(pages, size); - return MPOOL_ERROR_NONE; -} - -/* - * static int check_magic - * - * DESCRIPTION: - * - * Check for the existance of the magic ID in a memory pointer. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * addr -> Address inside of the block that we are tryign to locate. - * - * size -> Size of the block. - */ -static int check_magic(const void *addr, const unsigned long size) -{ - const unsigned char *mem_p; - - /* set our starting point */ - mem_p = (unsigned char *)addr + size; - - if (*mem_p == FENCE_MAGIC0 && *(mem_p + 1) == FENCE_MAGIC1) { - return MPOOL_ERROR_NONE; - } - else { - return MPOOL_ERROR_PNT_OVER; - } -} - -/* - * static void write_magic - * - * DESCRIPTION: - * - * Write the magic ID to the address. - * - * RETURNS: - * - * None. - * - * ARGUMENTS: - * - * addr -> Address where to write the magic. - */ -static void write_magic(const void *addr) -{ - *(unsigned char *)addr = FENCE_MAGIC0; - *((unsigned char *)addr + 1) = FENCE_MAGIC1; -} - -/* - * static void free_pointer - * - * DESCRIPTION: - * - * Moved a pointer into our free lists. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * addr <-> Address where to write the magic. We may write a next - * pointer to it. - * - * size -> Size of the address space. - */ -static int free_pointer(mpool_t *mp_p, void *addr, - const unsigned long size) -{ - unsigned int bit_n; - unsigned long real_size; - mpool_free_t free_pnt; - -#ifdef DEBUG - (void)printf("freeing a block at %lx of %lu bytes\n", (long)addr, size); -#endif - - if (size == 0) { - return MPOOL_ERROR_NONE; - } - - /* - * if the user size is larger then can fit in an entire block then - * we change the size - */ - if (size > MAX_BLOCK_USER_MEMORY(mp_p)) { - real_size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, size)) - - sizeof(mpool_block_t); - } - else { - real_size = size; - } - - /* - * We use a specific free bits calculation here because if we are - * freeing 10 bytes then we will be putting it into the 8-byte free - * list and not the 16 byte list. size_to_bits(10) will return 4 - * instead of 3. - */ - bit_n = size_to_free_bits(real_size); - - /* - * Minimal error checking. We could go all the way through the - * list however this might be prohibitive. - */ - if (mp_p->mp_free[bit_n] == addr) { - return MPOOL_ERROR_IS_FREE; - } - - /* add the freed pointer to the free list */ - if (bit_n < min_bit_free_next) { - /* - * Yes we know this will lose 99% of the allocations but what else - * can we do? No space for a next pointer. - */ - if (mp_p->mp_free[bit_n] == NULL) { - mp_p->mp_free[bit_n] = addr; - } - } - else if (bit_n < min_bit_free_size) { - /* we copy, not assign, to maintain the free list */ - memcpy(addr, mp_p->mp_free + bit_n, sizeof(void *)); - mp_p->mp_free[bit_n] = addr; - } - else { - - /* setup our free list structure */ - free_pnt.mf_next_p = mp_p->mp_free[bit_n]; - free_pnt.mf_size = real_size; - - /* we copy the structure in since we don't know about alignment */ - memcpy(addr, &free_pnt, sizeof(free_pnt)); - mp_p->mp_free[bit_n] = addr; - } - - return MPOOL_ERROR_NONE; -} - -/* - * static int split_block - * - * DESCRIPTION: - * - * When freeing space in a multi-block chunk we have to create new - * blocks out of the upper areas being freed. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * free_addr -> Address that we are freeing. - * - * size -> Size of the space that we are taking from address. - */ -static int split_block(mpool_t *mp_p, void *free_addr, - const unsigned long size) -{ - mpool_block_t *block_p, *new_block_p; - int ret, page_n; - void *end_p; - - /* - * 1st we find the block pointer from our free addr. At this point - * the pointer must be the 1st one in the block if it is spans - * multiple blocks. - */ - block_p = (mpool_block_t *)((char *)free_addr - sizeof(mpool_block_t)); - if (block_p->mb_magic != BLOCK_MAGIC - || block_p->mb_magic2 != BLOCK_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - page_n = PAGES_IN_SIZE(mp_p, size); - - /* we are creating a new block structure for the 2nd ... */ - new_block_p = (mpool_block_t *)((char *)block_p + - SIZE_OF_PAGES(mp_p, page_n)); - new_block_p->mb_magic = BLOCK_MAGIC; - /* New bounds is 1st block bounds. The 1st block's is reset below. */ - new_block_p->mb_bounds_p = block_p->mb_bounds_p; - /* Continue the linked list. The 1st block will point to us below. */ - new_block_p->mb_next_p = block_p->mb_next_p; - new_block_p->mb_magic2 = BLOCK_MAGIC; - - /* bounds for the 1st block are reset to the 1st page only */ - block_p->mb_bounds_p = (char *)new_block_p; - /* the next block pointer for the 1st block is now the new one */ - block_p->mb_next_p = new_block_p; - - /* only free the space in the 1st block if it is only 1 block in size */ - if (page_n == 1) { - /* now free the rest of the 1st block block */ - end_p = (char *)free_addr + size; - ret = free_pointer(mp_p, end_p, - (char *)block_p->mb_bounds_p - (char *)end_p); - if (ret != MPOOL_ERROR_NONE) { - return ret; - } - } - - /* now free the rest of the block */ - ret = free_pointer(mp_p, FIRST_ADDR_IN_BLOCK(new_block_p), - MEMORY_IN_BLOCK(new_block_p)); - if (ret != MPOOL_ERROR_NONE) { - return ret; - } - - return MPOOL_ERROR_NONE; -} - -/* - * static void *get_space - * - * DESCRIPTION: - * - * Moved a pointer into our free lists. - * - * RETURNS: - * - * Success - New address that we can use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * byte_size -> Size of the address space that we need. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -static void *get_space(mpool_t *mp_p, const unsigned long byte_size, - int *error_p) -{ - mpool_block_t *block_p; - mpool_free_t free_pnt; - int ret; - unsigned long size; - unsigned int bit_c, page_n, left; - void *free_addr = NULL, *free_end; - - size = byte_size; - while ((size & (sizeof(void *) - 1)) > 0) { - size++; - } - - /* - * First we check the free lists looking for something with enough - * pages. Maybe we should only look X bits higher in the list. - * - * XXX: this is where we'd do the best fit. We'd look for the - * closest match. We then could put the rest of the allocation that - * we did not use in a lower free list. Have a define which states - * how deep in the free list to go to find the closest match. - */ - for (bit_c = size_to_bits(size); bit_c <= MAX_BITS; bit_c++) { - if (mp_p->mp_free[bit_c] != NULL) { - free_addr = mp_p->mp_free[bit_c]; - break; - } - } - - /* - * If we haven't allocated any blocks or if the last block doesn't - * have enough memory then we need a new block. - */ - if (bit_c > MAX_BITS) { - - /* we need to allocate more space */ - - page_n = PAGES_IN_SIZE(mp_p, size); - - /* now we try and get the pages we need/want */ - block_p = alloc_pages(mp_p, page_n, error_p); - if (block_p == NULL) { - /* error_p set in alloc_pages */ - return NULL; - } - - /* init the block header */ - block_p->mb_magic = BLOCK_MAGIC; - block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(mp_p, page_n); - block_p->mb_next_p = mp_p->mp_first_p; - block_p->mb_magic2 = BLOCK_MAGIC; - - /* - * We insert it into the front of the queue. We could add it to - * the end but there is not much use. - */ - mp_p->mp_first_p = block_p; - if (mp_p->mp_last_p == NULL) { - mp_p->mp_last_p = block_p; - } - - free_addr = FIRST_ADDR_IN_BLOCK(block_p); - -#ifdef DEBUG - (void)printf("had to allocate space for %lx of %lu bytes\n", - (long)free_addr, size); -#endif - - free_end = (char *)free_addr + size; - left = (char *)block_p->mb_bounds_p - (char *)free_end; - } - else { - - if (bit_c < min_bit_free_next) { - mp_p->mp_free[bit_c] = NULL; - /* calculate the number of left over bytes */ - left = bits_to_size(bit_c) - size; - } - else if (bit_c < min_bit_free_next) { - /* grab the next pointer from the freed address into our list */ - memcpy(mp_p->mp_free + bit_c, free_addr, sizeof(void *)); - /* calculate the number of left over bytes */ - left = bits_to_size(bit_c) - size; - } - else { - /* grab the free structure from the address */ - memcpy(&free_pnt, free_addr, sizeof(free_pnt)); - mp_p->mp_free[bit_c] = free_pnt.mf_next_p; - - /* are we are splitting up a multiblock chunk into fewer blocks? */ - if (PAGES_IN_SIZE(mp_p, free_pnt.mf_size) > PAGES_IN_SIZE(mp_p, size)) { - ret = split_block(mp_p, free_addr, size); - if (ret != MPOOL_ERROR_NONE) { - SET_POINTER(error_p, ret); - return NULL; - } - /* left over memory was taken care of in split_block */ - left = 0; - } - else { - /* calculate the number of left over bytes */ - left = free_pnt.mf_size - size; - } - } - -#ifdef DEBUG - (void)printf("found a free block at %lx of %lu bytes\n", - (long)free_addr, left + size); -#endif - - free_end = (char *)free_addr + size; - } - - /* - * If we have memory left over then we free it so someone else can - * use it. We do not free the space if we just allocated a - * multi-block chunk because we need to have every allocation easily - * find the start of the block. Every user address % page-size - * should take us to the start of the block. - */ - if (left > 0 && size <= MAX_BLOCK_USER_MEMORY(mp_p)) { - /* free the rest of the block */ - ret = free_pointer(mp_p, free_end, left); - if (ret != MPOOL_ERROR_NONE) { - SET_POINTER(error_p, ret); - return NULL; - } - } - - /* update our bounds */ - if (free_addr > mp_p->mp_bounds_p) { - mp_p->mp_bounds_p = free_addr; - } - else if (free_addr < mp_p->mp_min_p) { - mp_p->mp_min_p = free_addr; - } - - return free_addr; -} - -/* - * static void *alloc_mem - * - * DESCRIPTION: - * - * Allocate space for bytes inside of an already open memory pool. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal malloc. - * - * byte_size -> Number of bytes to allocate in the pool. Must be >0. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -static void *alloc_mem(mpool_t *mp_p, const unsigned long byte_size, - int *error_p) -{ - unsigned long size, fence; - void *addr; - - /* make sure we have enough bytes */ - if (byte_size < MIN_ALLOCATION) { - size = MIN_ALLOCATION; - } - else { - size = byte_size; - } - - if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { - fence = 0; - } - else { - fence = FENCE_SIZE; - } - - /* get our free space + the space for the fence post */ - addr = get_space(mp_p, size + fence, error_p); - if (addr == NULL) { - /* error_p set in get_space */ - return NULL; - } - - if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { - write_magic((char *)addr + size); - } - - /* maintain our stats */ - mp_p->mp_alloc_c++; - mp_p->mp_user_alloc += size; - if (mp_p->mp_user_alloc > mp_p->mp_max_alloc) { - mp_p->mp_max_alloc = mp_p->mp_user_alloc; - } - - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return addr; -} - -/* - * static int free_mem - * - * DESCRIPTION: - * - * Free an address from a memory pool. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal free. - * - * addr <-> Address to free. - * - * size -> Size of the address being freed. - */ -static int free_mem(mpool_t *mp_p, void *addr, const unsigned long size) -{ - unsigned long old_size, fence; - int ret; - mpool_block_t *block_p; - - /* - * If the size is larger than a block then the allocation must be at - * the front of the block. - */ - if (size > MAX_BLOCK_USER_MEMORY(mp_p)) { - block_p = (mpool_block_t *)((char *)addr - sizeof(mpool_block_t)); - if (block_p->mb_magic != BLOCK_MAGIC - || block_p->mb_magic2 != BLOCK_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - } - - /* make sure we have enough bytes */ - if (size < MIN_ALLOCATION) { - old_size = MIN_ALLOCATION; - } - else { - old_size = size; - } - - /* if we are packing the pool smaller */ - if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { - fence = 0; - } - else { - /* find the user's magic numbers if they were written */ - ret = check_magic(addr, old_size); - if (ret != MPOOL_ERROR_NONE) { - return ret; - } - fence = FENCE_SIZE; - } - - /* now we free the pointer */ - ret = free_pointer(mp_p, addr, old_size + fence); - if (ret != MPOOL_ERROR_NONE) { - return ret; - } - mp_p->mp_user_alloc -= old_size; - - /* adjust our stats */ - mp_p->mp_alloc_c--; - - return MPOOL_ERROR_NONE; -} - -/***************************** exported routines *****************************/ - -/* - * mpool_t *mpool_open - * - * DESCRIPTION: - * - * Open/allocate a new memory pool. - * - * RETURNS: - * - * Success - Pool pointer which must be passed to mpool_close to - * deallocate. - * - * Failure - NULL - * - * ARGUMENTS: - * - * flags -> Flags to set attributes of the memory pool. See the top - * of mpool.h. - * - * page_size -> Set the internal memory page-size. This must be a - * multiple of the getpagesize() value. Set to 0 for the default. - * - * start_addr -> Starting address to try and allocate memory pools. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(mpool_t *) mpool_open(const unsigned int flags, const unsigned int page_size, - void *start_addr, int *error_p) -{ - mpool_block_t *block_p; - int page_n, ret; - mpool_t mp, *mp_p; - void *free_addr; - - if (! enabled_b) { - startup(); - } - - /* zero our temp struct */ - memset(&mp, 0, sizeof(mp)); - - mp.mp_magic = MPOOL_MAGIC; - mp.mp_flags = flags; - mp.mp_alloc_c = 0; - mp.mp_user_alloc = 0; - mp.mp_max_alloc = 0; - mp.mp_page_c = 0; - /* mp.mp_page_size set below */ - /* mp.mp_blocks_bit_n set below */ - /* mp.mp_fd set below */ - /* mp.mp_top set below */ - /* mp.mp_addr set below */ - mp.mp_log_func = NULL; - mp.mp_min_p = NULL; - mp.mp_bounds_p = NULL; - mp.mp_first_p = NULL; - mp.mp_last_p = NULL; - mp.mp_magic2 = MPOOL_MAGIC; - - /* get and sanity check our page size */ - if (page_size > 0) { - mp.mp_page_size = page_size; - if (mp.mp_page_size % getpagesize() != 0) { - SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); - return NULL; - } - } - else { - mp.mp_page_size = getpagesize() * DEFAULT_PAGE_MULT; - if (mp.mp_page_size % 1024 != 0) { - SET_POINTER(error_p, MPOOL_ERROR_PAGE_SIZE); - return NULL; - } - } - - mp.mp_mmflags = 0; - - if (BIT_IS_SET(flags, MPOOL_FLAG_ANONYMOUS)) { - mp.mp_fd = -1; - mp.mp_mmflags |= MAP_ANON; - } else { - /* open dev-zero for our mmaping */ - mp.mp_fd = open("/dev/zero", O_RDWR, 0); - if (mp.mp_fd < 0) { - SET_POINTER(error_p, MPOOL_ERROR_OPEN_ZERO); - return NULL; - } - } - mp.mp_addr = start_addr; - /* we start at the front of the file */ - mp.mp_top = 0; - - - /* - * Find out how many pages we need for our mpool structure. - * - * NOTE: this adds possibly unneeded space for mpool_block_t which - * may not be in this block. - */ - page_n = PAGES_IN_SIZE(&mp, sizeof(mpool_t)); - - /* now allocate us space for the actual struct */ - mp_p = alloc_pages(&mp, page_n, error_p); - if (mp_p == NULL) { - if (mp.mp_fd >= 0) { - (void)close(mp.mp_fd); - mp.mp_fd = -1; - } - return NULL; - } - - /* - * NOTE: we do not normally free the rest of the block here because - * we want to lesson the chance of an allocation overwriting the - * main structure. - */ - if (BIT_IS_SET(flags, MPOOL_FLAG_HEAVY_PACKING)) { - - /* we add a block header to the front of the block */ - block_p = (mpool_block_t *)mp_p; - - /* init the block header */ - block_p->mb_magic = BLOCK_MAGIC; - block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(&mp, page_n); - block_p->mb_next_p = NULL; - block_p->mb_magic2 = BLOCK_MAGIC; - - /* the mpool pointer is then the 2nd thing in the block */ - mp_p = FIRST_ADDR_IN_BLOCK(block_p); - free_addr = (char *)mp_p + sizeof(mpool_t); - - /* free the rest of the block */ - ret = free_pointer(&mp, free_addr, - (char *)block_p->mb_bounds_p - (char *)free_addr); - if (ret != MPOOL_ERROR_NONE) { - if (mp.mp_fd >= 0) { - (void)close(mp.mp_fd); - mp.mp_fd = -1; - } - /* NOTE: after this line mp_p will be invalid */ - (void)free_pages(block_p, SIZE_OF_PAGES(&mp, page_n)); - - SET_POINTER(error_p, ret); - return NULL; - } - - /* - * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool - * header is not on the block linked list. - */ - - /* now copy our tmp structure into our new memory area */ - memcpy(mp_p, &mp, sizeof(mpool_t)); - - /* we setup min/max to our current address which is as good as any */ - mp_p->mp_min_p = block_p; - mp_p->mp_bounds_p = block_p->mb_bounds_p; - } - else { - /* now copy our tmp structure into our new memory area */ - memcpy(mp_p, &mp, sizeof(mpool_t)); - - /* we setup min/max to our current address which is as good as any */ - mp_p->mp_min_p = mp_p; - mp_p->mp_bounds_p = (char *)mp_p + SIZE_OF_PAGES(mp_p, page_n); - } - - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return mp_p; -} - -/* - * int mpool_close - * - * DESCRIPTION: - * - * Close/free a memory allocation pool previously opened with - * mpool_open. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to our memory pool. - */ -KS_DECLARE(int) mpool_close(mpool_t *mp_p) -{ - mpool_block_t *block_p, *next_p; - void *addr; - unsigned long size; - int ret, final = MPOOL_ERROR_NONE; - - /* special case, just return no-error */ - if (mp_p == NULL) { - return MPOOL_ERROR_ARG_NULL; - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - return MPOOL_ERROR_PNT; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - if (mp_p->mp_log_func != NULL) { - mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLOSE, 0, 0, NULL, NULL, 0); - } - - /* - * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool - * header is not on the linked list. - */ - - /* free/invalidate the blocks */ - for (block_p = mp_p->mp_first_p; block_p != NULL; block_p = next_p) { - if (block_p->mb_magic != BLOCK_MAGIC - || block_p->mb_magic2 != BLOCK_MAGIC) { - final = MPOOL_ERROR_POOL_OVER; - break; - } - block_p->mb_magic = 0; - block_p->mb_magic2 = 0; - /* record the next pointer because it might be invalidated below */ - next_p = block_p->mb_next_p; - ret = free_pages(block_p, (char *)block_p->mb_bounds_p - (char *)block_p); - - if (ret != MPOOL_ERROR_NONE) { - final = ret; - } - } - - /* close /dev/zero if necessary */ - if (mp_p->mp_fd >= 0) { - (void)close(mp_p->mp_fd); - mp_p->mp_fd = -1; - } - - /* invalidate the mpool before we ditch it */ - mp_p->mp_magic = 0; - mp_p->mp_magic2 = 0; - - /* if we are heavy packing then we need to free the 1st block later */ - if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) { - addr = (char *)mp_p - sizeof(mpool_block_t); - } - else { - addr = mp_p; - } - size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, sizeof(mpool_t))); - - (void)munmap(addr, size); - - - return final; -} - -/* - * int mpool_clear - * - * DESCRIPTION: - * - * Wipe an opened memory pool clean so we can start again. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to our memory pool. - */ -KS_DECLARE(int) mpool_clear(mpool_t *mp_p) -{ - mpool_block_t *block_p; - int final = MPOOL_ERROR_NONE, bit_n, ret; - void *first_p; - - /* special case, just return no-error */ - if (mp_p == NULL) { - return MPOOL_ERROR_ARG_NULL; - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - return MPOOL_ERROR_PNT; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - if (mp_p->mp_log_func != NULL) { - mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLEAR, 0, 0, NULL, NULL, 0); - } - - /* reset all of our free lists */ - for (bit_n = 0; bit_n <= MAX_BITS; bit_n++) { - mp_p->mp_free[bit_n] = NULL; - } - - /* free the blocks */ - for (block_p = mp_p->mp_first_p; - block_p != NULL; - block_p = block_p->mb_next_p) { - if (block_p->mb_magic != BLOCK_MAGIC - || block_p->mb_magic2 != BLOCK_MAGIC) { - final = MPOOL_ERROR_POOL_OVER; - break; - } - - first_p = FIRST_ADDR_IN_BLOCK(block_p); - - /* free the memory */ - ret = free_pointer(mp_p, first_p, MEMORY_IN_BLOCK(block_p)); - if (ret != MPOOL_ERROR_NONE) { - final = ret; - } - } - - return final; -} - -/* - * void *mpool_alloc - * - * DESCRIPTION: - * - * Allocate space for bytes inside of an already open memory pool. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal malloc. - * - * byte_size -> Number of bytes to allocate in the pool. Must be >0. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(void *) mpool_alloc(mpool_t *mp_p, const unsigned long byte_size, - int *error_p) -{ - void *addr; - - if (mp_p == NULL) { - /* special case -- do a normal malloc */ - addr = (void *)malloc(byte_size); - if (addr == NULL) { - SET_POINTER(error_p, MPOOL_ERROR_ALLOC); - return NULL; - } - else { - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return addr; - } - } - - if (mp_p->mp_magic != MPOOL_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_PNT); - return NULL; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); - return NULL; - } - - if (byte_size == 0) { - SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); - return NULL; - } - - addr = alloc_mem(mp_p, byte_size, error_p); - - if (mp_p->mp_log_func != NULL) { - mp_p->mp_log_func(mp_p, MPOOL_FUNC_ALLOC, byte_size, 0, addr, NULL, 0); - } - - return addr; -} - -/* - * void *mpool_calloc - * - * DESCRIPTION: - * - * Allocate space for elements of bytes in the memory pool and zero - * the space afterwards. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal calloc. - * - * ele_n -> Number of elements to allocate. - * - * ele_size -> Number of bytes per element being allocated. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(void *) mpool_calloc(mpool_t *mp_p, const unsigned long ele_n, - const unsigned long ele_size, int *error_p) -{ - void *addr; - unsigned long byte_size; - - if (mp_p == NULL) { - /* special case -- do a normal calloc */ - addr = (void *)calloc(ele_n, ele_size); - if (addr == NULL) { - SET_POINTER(error_p, MPOOL_ERROR_ALLOC); - return NULL; - } - else { - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return addr; - } - - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_PNT); - return NULL; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); - return NULL; - } - - if (ele_n == 0 || ele_size == 0) { - SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); - return NULL; - } - - byte_size = ele_n * ele_size; - addr = alloc_mem(mp_p, byte_size, error_p); - if (addr != NULL) { - memset(addr, 0, byte_size); - } - - if (mp_p->mp_log_func != NULL) { - mp_p->mp_log_func(mp_p, MPOOL_FUNC_CALLOC, ele_size, ele_n, addr, NULL, 0); - } - - /* NOTE: error_p set above */ - return addr; -} - -/* - * int mpool_free - * - * DESCRIPTION: - * - * Free an address from a memory pool. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal free. - * - * addr <-> Address to free. - * - * size -> Size of the address being freed. - */ -KS_DECLARE(int) mpool_free(mpool_t *mp_p, void *addr, const unsigned long size) -{ - if (mp_p == NULL) { - /* special case -- do a normal free */ - free(addr); - return MPOOL_ERROR_NONE; - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - return MPOOL_ERROR_PNT; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - if (mp_p->mp_log_func != NULL) { - mp_p->mp_log_func(mp_p, MPOOL_FUNC_FREE, size, 0, NULL, addr, 0); - } - - if (addr == NULL) { - return MPOOL_ERROR_ARG_NULL; - } - if (size == 0) { - return MPOOL_ERROR_ARG_INVALID; - } - - return free_mem(mp_p, addr, size); -} - -/* - * void *mpool_resize - * - * DESCRIPTION: - * - * Reallocate an address in a mmeory pool to a new size. This is - * different from realloc in that it needs the old address' size. If - * you don't have it then you need to allocate new space, copy the - * data, and free the old pointer yourself. - * - * RETURNS: - * - * Success - Pointer to the address to use. - * - * Failure - NULL - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. If NULL then it will do a - * normal realloc. - * - * old_addr -> Previously allocated address. - * - * old_byte_size -> Size of the old address. Must be known, cannot be - * 0. - * - * new_byte_size -> New size of the allocation. - * - * error_p <- Pointer to integer which, if not NULL, will be set with - * a mpool error code. - */ -KS_DECLARE(void *) mpool_resize(mpool_t *mp_p, void *old_addr, - const unsigned long old_byte_size, - const unsigned long new_byte_size, - int *error_p) -{ - unsigned long copy_size, new_size, old_size, fence; - void *new_addr; - mpool_block_t *block_p; - int ret; - - if (mp_p == NULL) { - /* special case -- do a normal realloc */ - new_addr = (void *)realloc(old_addr, new_byte_size); - if (new_addr == NULL) { - SET_POINTER(error_p, MPOOL_ERROR_ALLOC); - return NULL; - } - else { - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return new_addr; - } - } - - if (mp_p->mp_magic != MPOOL_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_PNT); - return NULL; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); - return NULL; - } - - if (old_addr == NULL) { - SET_POINTER(error_p, MPOOL_ERROR_ARG_NULL); - return NULL; - } - if (old_byte_size == 0) { - SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); - return NULL; - } - - /* - * If the size is larger than a block then the allocation must be at - * the front of the block. - */ - if (old_byte_size > MAX_BLOCK_USER_MEMORY(mp_p)) { - block_p = (mpool_block_t *)((char *)old_addr - sizeof(mpool_block_t)); - if (block_p->mb_magic != BLOCK_MAGIC - || block_p->mb_magic2 != BLOCK_MAGIC) { - SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); - return NULL; - } - } - - /* make sure we have enough bytes */ - if (old_byte_size < MIN_ALLOCATION) { - old_size = MIN_ALLOCATION; - } - else { - old_size = old_byte_size; - } - - /* verify that the size matches exactly if we can */ - if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { - fence = 0; - } - else if (old_size > 0) { - ret = check_magic(old_addr, old_size); - if (ret != MPOOL_ERROR_NONE) { - SET_POINTER(error_p, ret); - return NULL; - } - fence = FENCE_SIZE; - } - - /* make sure we have enough bytes */ - if (new_byte_size < MIN_ALLOCATION) { - new_size = MIN_ALLOCATION; - } - else { - new_size = new_byte_size; - } - - /* - * NOTE: we could here see if the size is the same or less and then - * use the current memory and free the space above. This is harder - * than it sounds if we are changing the block size of the - * allocation. - */ - - /* we need to get another address */ - new_addr = alloc_mem(mp_p, new_byte_size, error_p); - if (new_addr == NULL) { - /* error_p set in mpool_alloc */ - return NULL; - } - - if (new_byte_size > old_byte_size) { - copy_size = old_byte_size; - } - else { - copy_size = new_byte_size; - } - memcpy(new_addr, old_addr, copy_size); - - /* free the old address */ - ret = free_mem(mp_p, old_addr, old_byte_size); - if (ret != MPOOL_ERROR_NONE) { - /* if the old free failed, try and free the new address */ - (void)free_mem(mp_p, new_addr, new_byte_size); - SET_POINTER(error_p, ret); - return NULL; - } - - if (mp_p->mp_log_func != NULL) { - mp_p->mp_log_func(mp_p, MPOOL_FUNC_RESIZE, new_byte_size, - 0, new_addr, old_addr, old_byte_size); - } - - SET_POINTER(error_p, MPOOL_ERROR_NONE); - return new_addr; -} - -/* - * int mpool_stats - * - * DESCRIPTION: - * - * Return stats from the memory pool. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p -> Pointer to the memory pool. - * - * page_size_p <- Pointer to an unsigned integer which, if not NULL, - * will be set to the page-size of the pool. - * - * num_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the number of pointers currently allocated in pool. - * - * user_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the number of user bytes allocated in this pool. - * - * max_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the maximum number of user bytes that have been - * allocated in this pool. - * - * tot_alloced_p <- Pointer to an unsigned long which, if not NULL, - * will be set to the total amount of space (including administrative - * overhead) used by the pool. - */ -KS_DECLARE(int) mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p, - unsigned long *num_alloced_p, - unsigned long *user_alloced_p, - unsigned long *max_alloced_p, - unsigned long *tot_alloced_p) -{ - if (mp_p == NULL) { - return MPOOL_ERROR_ARG_NULL; - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - return MPOOL_ERROR_PNT; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - SET_POINTER(page_size_p, mp_p->mp_page_size); - SET_POINTER(num_alloced_p, mp_p->mp_alloc_c); - SET_POINTER(user_alloced_p, mp_p->mp_user_alloc); - SET_POINTER(max_alloced_p, mp_p->mp_max_alloc); - SET_POINTER(tot_alloced_p, SIZE_OF_PAGES(mp_p, mp_p->mp_page_c)); - - return MPOOL_ERROR_NONE; -} - -/* - * int mpool_set_log_func - * - * DESCRIPTION: - * - * Set a logging callback function to be called whenever there was a - * memory transaction. See mpool_log_func_t. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * log_func -> Log function (defined in mpool.h) which will be called - * with each mpool transaction. - */ -KS_DECLARE(int) mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func) -{ - if (mp_p == NULL) { - return MPOOL_ERROR_ARG_NULL; - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - return MPOOL_ERROR_PNT; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - mp_p->mp_log_func = log_func; - - return MPOOL_ERROR_NONE; -} - -/* - * int mpool_set_max_pages - * - * DESCRIPTION: - * - * Set the maximum number of pages that the library will use. Once it - * hits the limit it will return MPOOL_ERROR_NO_PAGES. - * - * NOTE: if the MPOOL_FLAG_HEAVY_PACKING is set then this max-pages - * value will include the page with the mpool header structure in it. - * If the flag is _not_ set then the max-pages will not include this - * first page. - * - * RETURNS: - * - * Success - MPOOL_ERROR_NONE - * - * Failure - Mpool error code - * - * ARGUMENTS: - * - * mp_p <-> Pointer to the memory pool. - * - * max_pages -> Maximum number of pages used by the library. - */ -KS_DECLARE(int) mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages) -{ - if (mp_p == NULL) { - return MPOOL_ERROR_ARG_NULL; - } - if (mp_p->mp_magic != MPOOL_MAGIC) { - return MPOOL_ERROR_PNT; - } - if (mp_p->mp_magic2 != MPOOL_MAGIC) { - return MPOOL_ERROR_POOL_OVER; - } - - if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) { - mp_p->mp_max_pages = max_pages; - } - else { - /* - * If we are not heavy-packing the pool then we don't count the - * 1st page allocated which holds the mpool header structure. - */ - mp_p->mp_max_pages = max_pages + 1; - } - - return MPOOL_ERROR_NONE; -} - -/* - * const char *mpool_strerror - * - * DESCRIPTION: - * - * Return the corresponding string for the error number. - * - * RETURNS: - * - * Success - String equivalient of the error. - * - * Failure - String "invalid error code" - * - * ARGUMENTS: - * - * error -> Error number that we are converting. - */ -KS_DECLARE(const char *) mpool_strerror(const int error) -{ - switch (error) { - case MPOOL_ERROR_NONE: - return "no error"; - break; - case MPOOL_ERROR_ARG_NULL: - return "function argument is null"; - break; - case MPOOL_ERROR_ARG_INVALID: - return "function argument is invalid"; - break; - case MPOOL_ERROR_PNT: - return "invalid mpool pointer"; - break; - case MPOOL_ERROR_POOL_OVER: - return "mpool structure was overwritten"; - break; - case MPOOL_ERROR_PAGE_SIZE: - return "could not get system page-size"; - break; - case MPOOL_ERROR_OPEN_ZERO: - return "could not open /dev/zero"; - break; - case MPOOL_ERROR_NO_MEM: - return "no memory available"; - break; - case MPOOL_ERROR_MMAP: - return "problems with mmap"; - break; - case MPOOL_ERROR_SIZE: - return "error processing requested size"; - break; - case MPOOL_ERROR_TOO_BIG: - return "allocation exceeds pool max size"; - break; - case MPOOL_ERROR_MEM: - return "invalid memory address"; - break; - case MPOOL_ERROR_MEM_OVER: - return "memory lower bounds overwritten"; - break; - case MPOOL_ERROR_NOT_FOUND: - return "memory block not found in pool"; - break; - case MPOOL_ERROR_IS_FREE: - return "memory address has already been freed"; - break; - case MPOOL_ERROR_BLOCK_STAT: - return "invalid internal block status"; - break; - case MPOOL_ERROR_FREE_ADDR: - return "invalid internal free address"; - break; - case MPOOL_ERROR_NO_PAGES: - return "no available pages left in pool"; - break; - case MPOOL_ERROR_ALLOC: - return "system alloc function failed"; - break; - case MPOOL_ERROR_PNT_OVER: - return "user pointer admin space overwritten"; - break; - default: - break; - } - - return "invalid error code"; -} - - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/simclist.c b/libs/libks/src/simclist.c deleted file mode 100755 index 8333ab86d9..0000000000 --- a/libs/libks/src/simclist.c +++ /dev/null @@ -1,1540 +0,0 @@ -/* - * Copyright (c) 2007,2008,2009,2010,2011 Mij - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -/* - * SimCList library. See http://mij.oltrelinux.com/devel/simclist - */ - -/* SimCList implementation, version 1.6 */ - -#include -#include -#include /* for setting errno */ -#include -#ifndef _WIN32 -/* not in Windows! */ -# include -# include -#else -#include -#endif -#ifndef SIMCLIST_NO_DUMPRESTORE -/* includes for dump/restore */ -# include -# include /* for READ_ERRCHECK() and write() */ -# include /* for open() etc */ -# ifndef _WIN32 -# include /* for htons() on UNIX */ -# else -# include /* for htons() on Windows */ -# endif -#endif - -/* disable asserts */ -#ifndef SIMCLIST_DEBUG -#define NDEBUG -#endif - -#include - - -#include /* for open()'s access modes S_IRUSR etc */ -#include - -#if defined(_MSC_VER) || defined(__MINGW32__) -/* provide gettimeofday() missing in Windows */ -#ifdef _MSC_VER -#pragma comment(lib, "Winmm.lib") -#endif -int gettimeofday(struct timeval *tp, void *tzp) { - DWORD t; - - /* XSI says: "If tzp is not a null pointer, the behavior is unspecified" */ - assert(tzp == NULL); - - t = timeGetTime(); - tp->tv_sec = t / 1000; - tp->tv_usec = t % 1000; - return 0; -} -#endif - - -/* work around lack of inttypes.h support in broken Microsoft Visual Studio compilers */ -#if !defined(_WIN32) || !defined(_MSC_VER) -# include /* (u)int*_t */ -#else -# include -typedef UINT8 uint8_t; -typedef UINT16 uint16_t; -typedef ULONG32 uint32_t; -typedef UINT64 uint64_t; -typedef INT8 int8_t; -typedef INT16 int16_t; -typedef LONG32 int32_t; -typedef INT64 int64_t; -#endif - - -/* define some commodity macros for Dump/Restore functionality */ -#ifndef SIMCLIST_NO_DUMPRESTORE -/* write() decorated with error checking logic */ -#define WRITE_ERRCHECK(fd, msgbuf, msglen) do { \ - if (write(fd, msgbuf, msglen) < 0) return -1; \ - } while (0); -/* READ_ERRCHECK() decorated with error checking logic */ -#define READ_ERRCHECK(fd, msgbuf, msglen) do { \ - if (read(fd, msgbuf, msglen) != msglen) { \ - /*errno = EPROTO;*/ \ - return -1; \ - } \ - } while (0); - -/* convert 64bit integers from host to network format */ -#define hton64(x) ( \ - htons(1) == 1 ? \ - (uint64_t)x /* big endian */ \ - : /* little endian */ \ - ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \ - (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ - (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ - (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ - (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ - (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ - (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ - (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) \ - ) - -/* convert 64bit integers from network to host format */ -#define ntoh64(x) (hton64(x)) -#endif - -/* some OSes don't have EPROTO (eg OpenBSD) */ -#ifndef EPROTO -#define EPROTO EIO -#endif - -#ifdef SIMCLIST_WITH_THREADS -/* limit (approx) to the number of threads running - * for threaded operations. Only meant when - * SIMCLIST_WITH_THREADS is defined */ -#define SIMCLIST_MAXTHREADS 2 -#endif - -/* - * how many elems to keep as spare. During a deletion, an element - * can be saved in a "free-list", not free()d immediately. When - * latter insertions are performed, spare elems can be used instead - * of malloc()ing new elems. - * - * about this param, some values for appending - * 10 million elems into an empty list: - * (#, time[sec], gain[%], gain/no[%]) - * 0 2,164 0,00 0,00 <-- feature disabled - * 1 1,815 34,9 34,9 - * 2 1,446 71,8 35,9 <-- MAX gain/no - * 3 1,347 81,7 27,23 - * 5 1,213 95,1 19,02 - * 8 1,064 110,0 13,75 - * 10 1,015 114,9 11,49 <-- MAX gain w/ likely sol - * 15 1,019 114,5 7,63 - * 25 0,985 117,9 4,72 - * 50 1,088 107,6 2,15 - * 75 1,016 114,8 1,53 - * 100 0,988 117,6 1,18 - * 150 1,022 114,2 0,76 - * 200 0,939 122,5 0,61 <-- MIN time - */ -#ifndef SIMCLIST_MAX_SPARE_ELEMS -#define SIMCLIST_MAX_SPARE_ELEMS 5 -#endif - - -#ifdef SIMCLIST_WITH_THREADS -#include -#endif - -#include "simclist.h" - - -/* minumum number of elements for sorting with quicksort instead of insertion */ -#define SIMCLIST_MINQUICKSORTELS 24 - - -/* list dump declarations */ -#define SIMCLIST_DUMPFORMAT_VERSION 1 /* (short integer) version of fileformat managed by _dump* and _restore* functions */ - -#define SIMCLIST_DUMPFORMAT_HEADERLEN 30 /* length of the header */ - -/* header for a list dump */ -struct list_dump_header_s { - uint16_t ver; /* version */ - int32_t timestamp_sec; /* dump timestamp, seconds since UNIX Epoch */ - int32_t timestamp_usec; /* dump timestamp, microseconds since timestamp_sec */ - int32_t rndterm; /* random value terminator -- terminates the data sequence */ - - uint32_t totlistlen; /* sum of every element' size, bytes */ - uint32_t numels; /* number of elements */ - uint32_t elemlen; /* bytes length of an element, for constant-size lists, <= 0 otherwise */ - int32_t listhash; /* hash of the list at the time of dumping, or 0 if to be ignored */ -}; - - - -/* deletes tmp from list, with care wrt its position (head, tail, middle) */ -static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos); - -/* set default values for initialized lists */ -static int list_attributes_setdefaults(list_t *restrict l); - -#ifndef NDEBUG -/* check whether the list internal REPresentation is valid -- Costs O(n) */ -static int list_repOk(const list_t *restrict l); - -/* check whether the list attribute set is valid -- Costs O(1) */ -static int list_attrOk(const list_t *restrict l); -#endif - -/* do not inline, this is recursive */ -static void list_sort_quicksort(list_t *restrict l, int versus, - unsigned int first, struct list_entry_s *fel, - unsigned int last, struct list_entry_s *lel); - -static inline void list_sort_selectionsort(list_t *restrict l, int versus, - unsigned int first, struct list_entry_s *fel, - unsigned int last, struct list_entry_s *lel); - -static void *list_get_minmax(const list_t *restrict l, int versus); - -static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart); - -/* - * Random Number Generator - * - * The user is expected to seed the RNG (ie call srand()) if - * SIMCLIST_SYSTEM_RNG is defined. - * - * Otherwise, a self-contained RNG based on LCG is used; see - * http://en.wikipedia.org/wiki/Linear_congruential_generator . - * - * Facts pro local RNG: - * 1. no need for the user to call srand() on his own - * 2. very fast, possibly faster than OS - * 3. avoid interference with user's RNG - * - * Facts pro system RNG: - * 1. may be more accurate (irrelevant for SimCList randno purposes) - * 2. why reinvent the wheel - * - * Default to local RNG for user's ease of use. - */ - -#ifdef SIMCLIST_SYSTEM_RNG -/* keep track whether we initialized already (non-0) or not (0) */ -static unsigned random_seed = 0; - -/* use local RNG */ -static inline void seed_random(void) { - if (random_seed == 0) - random_seed = (unsigned)getpid() ^ (unsigned)time(NULL); -} - -static inline long get_random(void) { - random_seed = (1664525 * random_seed + 1013904223); - return random_seed; -} - -#else -/* use OS's random generator */ -# define seed_random() -# define get_random() (rand()) -#endif - - -/* list initialization */ -int list_init(list_t *restrict l) { - if (l == NULL) return -1; - - seed_random(); - - l->numels = 0; - - /* head/tail sentinels and mid pointer */ - l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); - l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); - l->head_sentinel->next = l->tail_sentinel; - l->tail_sentinel->prev = l->head_sentinel; - l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL; - l->head_sentinel->data = l->tail_sentinel->data = NULL; - - /* iteration attributes */ - l->iter_active = 0; - l->iter_pos = 0; - l->iter_curentry = NULL; - - /* free-list attributes */ - l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *)); - l->spareelsnum = 0; - -#ifdef SIMCLIST_WITH_THREADS - l->threadcount = 0; -#endif - - list_attributes_setdefaults(l); - - assert(list_repOk(l)); - assert(list_attrOk(l)); - - return 0; -} - -void list_destroy(list_t *restrict l) { - unsigned int i; - - list_clear(l); - for (i = 0; i < l->spareelsnum; i++) { - free(l->spareels[i]); - } - free(l->spareels); - free(l->head_sentinel); - free(l->tail_sentinel); -} - -int list_attributes_setdefaults(list_t *restrict l) { - l->attrs.comparator = NULL; - l->attrs.seeker = NULL; - - /* also free() element data when removing and element from the list */ - l->attrs.meter = NULL; - l->attrs.copy_data = 0; - - l->attrs.hasher = NULL; - - /* serializer/unserializer */ - l->attrs.serializer = NULL; - l->attrs.unserializer = NULL; - - assert(list_attrOk(l)); - - return 0; -} - -/* setting list properties */ -int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun) { - if (l == NULL) return -1; - - l->attrs.comparator = comparator_fun; - - assert(list_attrOk(l)); - - return 0; -} - -int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun) { - if (l == NULL) return -1; - - l->attrs.seeker = seeker_fun; - assert(list_attrOk(l)); - - return 0; -} - -int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data) { - if (l == NULL || (metric_fun == NULL && copy_data != 0)) return -1; - - l->attrs.meter = metric_fun; - l->attrs.copy_data = copy_data; - - assert(list_attrOk(l)); - - return 0; -} - -int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun) { - if (l == NULL) return -1; - - l->attrs.hasher = hash_computer_fun; - assert(list_attrOk(l)); - return 0; -} - -int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun) { - if (l == NULL) return -1; - - l->attrs.serializer = serializer_fun; - assert(list_attrOk(l)); - return 0; -} - -int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun) { - if (l == NULL) return -1; - - l->attrs.unserializer = unserializer_fun; - assert(list_attrOk(l)); - return 0; -} - -int list_append(list_t *restrict l, const void *data) { - return list_insert_at(l, data, l->numels); -} - -int list_prepend(list_t *restrict l, const void *data) { - return list_insert_at(l, data, 0); -} - -void *list_fetch(list_t *restrict l) { - return list_extract_at(l, 0); -} - -void *list_get_at(const list_t *restrict l, unsigned int pos) { - struct list_entry_s *tmp; - - tmp = list_findpos(l, pos); - - return (tmp != NULL ? tmp->data : NULL); -} - -void *list_get_max(const list_t *restrict l) { - return list_get_minmax(l, +1); -} - -void *list_get_min(const list_t *restrict l) { - return list_get_minmax(l, -1); -} - -/* REQUIRES {list->numels >= 1} - * return the min (versus < 0) or max value (v > 0) in l */ -static void *list_get_minmax(const list_t *restrict l, int versus) { - void *curminmax; - struct list_entry_s *s; - - if (l->attrs.comparator == NULL || l->numels == 0) - return NULL; - - curminmax = l->head_sentinel->next->data; - for (s = l->head_sentinel->next->next; s != l->tail_sentinel; s = s->next) { - if (l->attrs.comparator(curminmax, s->data) * versus > 0) - curminmax = s->data; - } - - return curminmax; -} - -/* set tmp to point to element at index posstart in l */ -static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) { - struct list_entry_s *ptr; - float x; - int i; - - /* accept 1 slot overflow for fetching head and tail sentinels */ - if (posstart < -1 || posstart > (int)l->numels) return NULL; - - x = (float)(posstart+1) / l->numels; - if (x <= 0.25) { - /* first quarter: get to posstart from head */ - for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++); - } else if (x < 0.5) { - /* second quarter: get to posstart from mid */ - for (i = (l->numels-1)/2, ptr = l->mid; i > posstart; ptr = ptr->prev, i--); - } else if (x <= 0.75) { - /* third quarter: get to posstart from mid */ - for (i = (l->numels-1)/2, ptr = l->mid; i < posstart; ptr = ptr->next, i++); - } else { - /* fourth quarter: get to posstart from tail */ - for (i = l->numels, ptr = l->tail_sentinel; i > posstart; ptr = ptr->prev, i--); - } - - return ptr; -} - -void *list_extract_at(list_t *restrict l, unsigned int pos) { - struct list_entry_s *tmp; - void *data; - - if (l->iter_active || pos >= l->numels) return NULL; - - tmp = list_findpos(l, pos); - data = tmp->data; - - tmp->data = NULL; /* save data from list_drop_elem() free() */ - list_drop_elem(l, tmp, pos); - l->numels--; - - assert(list_repOk(l)); - - return data; -} - -int list_insert_at(list_t *restrict l, const void *data, unsigned int pos) { - struct list_entry_s *lent, *succ, *prec; - - if (l->iter_active || pos > l->numels) return -1; - - /* this code optimizes malloc() with a free-list */ - if (l->spareelsnum > 0) { - lent = l->spareels[l->spareelsnum-1]; - l->spareelsnum--; - } else { - lent = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); - if (lent == NULL) - return -1; - } - - if (l->attrs.copy_data) { - /* make room for user' data (has to be copied) */ - size_t datalen = l->attrs.meter(data); - lent->data = (struct list_entry_s *)malloc(datalen); - memcpy(lent->data, data, datalen); - } else { - lent->data = (void*)data; - } - - /* actually append element */ - prec = list_findpos(l, pos-1); - succ = prec->next; - - prec->next = lent; - lent->prev = prec; - lent->next = succ; - succ->prev = lent; - - l->numels++; - - /* fix mid pointer */ - if (l->numels == 1) { /* first element, set pointer */ - l->mid = lent; - } else if (l->numels % 2) { /* now odd */ - if (pos >= (l->numels-1)/2) l->mid = l->mid->next; - } else { /* now even */ - if (pos <= (l->numels-1)/2) l->mid = l->mid->prev; - } - - assert(list_repOk(l)); - - return 1; -} - -int list_delete(list_t *restrict l, const void *data) { - int pos, r; - - pos = list_locate(l, data); - if (pos < 0) - return -1; - - r = list_delete_at(l, pos); - if (r < 0) - return -1; - - assert(list_repOk(l)); - - return 0; -} - -int list_delete_at(list_t *restrict l, unsigned int pos) { - struct list_entry_s *delendo; - - - if (l->iter_active || pos >= l->numels) return -1; - - delendo = list_findpos(l, pos); - - list_drop_elem(l, delendo, pos); - - l->numels--; - - - assert(list_repOk(l)); - - return 0; -} - -int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend) { - struct list_entry_s *lastvalid, *tmp, *tmp2; - unsigned int numdel, midposafter, i; - int movedx; - - if (l->iter_active || posend < posstart || posend >= l->numels) return -1; - - numdel = posend - posstart + 1; - if (numdel == l->numels) return list_clear(l); - - tmp = list_findpos(l, posstart); /* first el to be deleted */ - lastvalid = tmp->prev; /* last valid element */ - - midposafter = (l->numels-1-numdel)/2; - - midposafter = midposafter < posstart ? midposafter : midposafter+numdel; - movedx = midposafter - (l->numels-1)/2; - - if (movedx > 0) { /* move right */ - for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->next, i++); - } else { /* move left */ - movedx = -movedx; - for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->prev, i++); - } - - assert(posstart == 0 || lastvalid != l->head_sentinel); - i = posstart; - if (l->attrs.copy_data) { - /* also free element data */ - for (; i <= posend; i++) { - tmp2 = tmp; - tmp = tmp->next; - if (tmp2->data != NULL) free(tmp2->data); - if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { - l->spareels[l->spareelsnum++] = tmp2; - } else { - free(tmp2); - } - } - } else { - /* only free containers */ - for (; i <= posend; i++) { - tmp2 = tmp; - tmp = tmp->next; - if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { - l->spareels[l->spareelsnum++] = tmp2; - } else { - free(tmp2); - } - } - } - assert(i == posend+1 && (posend != l->numels || tmp == l->tail_sentinel)); - - lastvalid->next = tmp; - tmp->prev = lastvalid; - - l->numels -= posend - posstart + 1; - - assert(list_repOk(l)); - - return numdel; -} - -int list_clear(list_t *restrict l) { - struct list_entry_s *s; - unsigned int numels; - - /* will be returned */ - numels = l->numels; - - if (l->iter_active) return -1; - - if (l->attrs.copy_data) { /* also free user data */ - /* spare a loop conditional with two loops: spareing elems and freeing elems */ - for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) { - /* move elements as spares as long as there is room */ - if (s->data != NULL) free(s->data); - l->spareels[l->spareelsnum++] = s; - } - while (s != l->tail_sentinel) { - /* free the remaining elems */ - if (s->data != NULL) free(s->data); - s = s->next; - free(s->prev); - } - l->head_sentinel->next = l->tail_sentinel; - l->tail_sentinel->prev = l->head_sentinel; - } else { /* only free element containers */ - /* spare a loop conditional with two loops: spareing elems and freeing elems */ - for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) { - /* move elements as spares as long as there is room */ - l->spareels[l->spareelsnum++] = s; - } - while (s != l->tail_sentinel) { - /* free the remaining elems */ - s = s->next; - free(s->prev); - } - l->head_sentinel->next = l->tail_sentinel; - l->tail_sentinel->prev = l->head_sentinel; - } - l->numels = 0; - l->mid = NULL; - - assert(list_repOk(l)); - - return numels; -} - -unsigned int list_size(const list_t *restrict l) { - return l->numels; -} - -int list_empty(const list_t *restrict l) { - return (l->numels == 0); -} - -int list_locate(const list_t *restrict l, const void *data) { - struct list_entry_s *el; - int pos = 0; - - if (l->attrs.comparator != NULL) { - /* use comparator */ - for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) { - if (l->attrs.comparator(data, el->data) == 0) break; - } - } else { - /* compare references */ - for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) { - if (el->data == data) break; - } - } - if (el == l->tail_sentinel) return -1; - - return pos; -} - -void *list_seek(list_t *restrict l, const void *indicator) { - const struct list_entry_s *iter; - - if (l->attrs.seeker == NULL) return NULL; - - for (iter = l->head_sentinel->next; iter != l->tail_sentinel; iter = iter->next) { - if (l->attrs.seeker(iter->data, indicator) != 0) return iter->data; - } - - return NULL; -} - -int list_contains(const list_t *restrict l, const void *data) { - return (list_locate(l, data) >= 0); -} - -int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest) { - struct list_entry_s *el, *srcel; - unsigned int cnt; - int err; - - - if (l1 == NULL || l2 == NULL || dest == NULL || l1 == dest || l2 == dest) - return -1; - - list_init(dest); - - dest->numels = l1->numels + l2->numels; - if (dest->numels == 0) - return 0; - - /* copy list1 */ - srcel = l1->head_sentinel->next; - el = dest->head_sentinel; - while (srcel != l1->tail_sentinel) { - el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); - el->next->prev = el; - el = el->next; - el->data = srcel->data; - srcel = srcel->next; - } - dest->mid = el; /* approximate position (adjust later) */ - /* copy list 2 */ - srcel = l2->head_sentinel->next; - while (srcel != l2->tail_sentinel) { - el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); - el->next->prev = el; - el = el->next; - el->data = srcel->data; - srcel = srcel->next; - } - el->next = dest->tail_sentinel; - dest->tail_sentinel->prev = el; - - /* fix mid pointer */ - err = l2->numels - l1->numels; - if ((err+1)/2 > 0) { /* correct pos RIGHT (err-1)/2 moves */ - err = (err+1)/2; - for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->next; - } else if (err/2 < 0) { /* correct pos LEFT (err/2)-1 moves */ - err = -err/2; - for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->prev; - } - - assert(!(list_repOk(l1) && list_repOk(l2)) || list_repOk(dest)); - - return 0; -} - -int list_sort(list_t *restrict l, int versus) { - if (l->iter_active || l->attrs.comparator == NULL) /* cannot modify list in the middle of an iteration */ - return -1; - - if (l->numels <= 1) - return 0; - list_sort_quicksort(l, versus, 0, l->head_sentinel->next, l->numels-1, l->tail_sentinel->prev); - assert(list_repOk(l)); - return 0; -} - -#ifdef SIMCLIST_WITH_THREADS -struct list_sort_wrappedparams { - list_t *restrict l; - int versus; - unsigned int first, last; - struct list_entry_s *fel, *lel; -}; - -static void *list_sort_quicksort_threadwrapper(void *wrapped_params) { - struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)wrapped_params; - list_sort_quicksort(wp->l, wp->versus, wp->first, wp->fel, wp->last, wp->lel); - free(wp); - pthread_exit(NULL); - return NULL; -} -#endif - -static inline void list_sort_selectionsort(list_t *restrict l, int versus, - unsigned int first, struct list_entry_s *fel, - unsigned int last, struct list_entry_s *lel) { - struct list_entry_s *cursor, *toswap, *firstunsorted; - void *tmpdata; - - if (last <= first) /* <= 1-element lists are always sorted */ - return; - - for (firstunsorted = fel; firstunsorted != lel; firstunsorted = firstunsorted->next) { - /* find min or max in the remainder of the list */ - for (toswap = firstunsorted, cursor = firstunsorted->next; cursor != lel->next; cursor = cursor->next) - if (l->attrs.comparator(toswap->data, cursor->data) * -versus > 0) toswap = cursor; - if (toswap != firstunsorted) { /* swap firstunsorted with toswap */ - tmpdata = firstunsorted->data; - firstunsorted->data = toswap->data; - toswap->data = tmpdata; - } - } -} - -static void list_sort_quicksort(list_t *restrict l, int versus, - unsigned int first, struct list_entry_s *fel, - unsigned int last, struct list_entry_s *lel) { - unsigned int pivotid; - unsigned int i; - register struct list_entry_s *pivot; - struct list_entry_s *left, *right; - void *tmpdata; -#ifdef SIMCLIST_WITH_THREADS - pthread_t tid; - int traised; -#endif - - - if (last <= first) /* <= 1-element lists are always sorted */ - return; - - if (last - first+1 <= SIMCLIST_MINQUICKSORTELS) { - list_sort_selectionsort(l, versus, first, fel, last, lel); - return; - } - - /* base of iteration: one element list */ - if (! (last > first)) return; - - pivotid = (get_random() % (last - first + 1)); - /* pivotid = (last - first + 1) / 2; */ - - /* find pivot */ - if (pivotid < (last - first + 1)/2) { - for (i = 0, pivot = fel; i < pivotid; pivot = pivot->next, i++); - } else { - for (i = last - first, pivot = lel; i > pivotid; pivot = pivot->prev, i--); - } - - /* smaller PIVOT bigger */ - left = fel; - right = lel; - /* iterate --- left ---> PIV <--- right --- */ - while (left != pivot && right != pivot) { - for (; left != pivot && (l->attrs.comparator(left->data, pivot->data) * -versus <= 0); left = left->next); - /* left points to a smaller element, or to pivot */ - for (; right != pivot && (l->attrs.comparator(right->data, pivot->data) * -versus >= 0); right = right->prev); - /* right points to a bigger element, or to pivot */ - if (left != pivot && right != pivot) { - /* swap, then move iterators */ - tmpdata = left->data; - left->data = right->data; - right->data = tmpdata; - - left = left->next; - right = right->prev; - } - } - - /* now either left points to pivot (end run), or right */ - if (right == pivot) { /* left part longer */ - while (left != pivot) { - if (l->attrs.comparator(left->data, pivot->data) * -versus > 0) { - tmpdata = left->data; - left->data = pivot->prev->data; - pivot->prev->data = pivot->data; - pivot->data = tmpdata; - pivot = pivot->prev; - pivotid--; - if (pivot == left) break; - } else { - left = left->next; - } - } - } else { /* right part longer */ - while (right != pivot) { - if (l->attrs.comparator(right->data, pivot->data) * -versus < 0) { - /* move current right before pivot */ - tmpdata = right->data; - right->data = pivot->next->data; - pivot->next->data = pivot->data; - pivot->data = tmpdata; - pivot = pivot->next; - pivotid++; - if (pivot == right) break; - } else { - right = right->prev; - } - } - } - - /* sort sublists A and B : |---A---| pivot |---B---| */ - -#ifdef SIMCLIST_WITH_THREADS - traised = 0; - if (pivotid > 0) { - /* prepare wrapped args, then start thread */ - if (l->threadcount < SIMCLIST_MAXTHREADS-1) { - struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)malloc(sizeof(struct list_sort_wrappedparams)); - l->threadcount++; - traised = 1; - wp->l = l; - wp->versus = versus; - wp->first = first; - wp->fel = fel; - wp->last = first+pivotid-1; - wp->lel = pivot->prev; - if (pthread_create(&tid, NULL, list_sort_quicksort_threadwrapper, wp) != 0) { - free(wp); - traised = 0; - list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); - } - } else { - list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); - } - } - if (first + pivotid < last) list_sort_quicksort(l, versus, first+pivotid+1, pivot->next, last, lel); - if (traised) { - pthread_join(tid, (void **)NULL); - l->threadcount--; - } -#else - if (pivotid > 0) list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); - if (first + pivotid < last) list_sort_quicksort(l, versus, first+pivotid+1, pivot->next, last, lel); -#endif -} - -int list_iterator_start(list_t *restrict l) { - if (l->iter_active) return 0; - l->iter_pos = 0; - l->iter_active = 1; - l->iter_curentry = l->head_sentinel->next; - return 1; -} - -void *list_iterator_next(list_t *restrict l) { - void *toret; - - if (! l->iter_active) return NULL; - - toret = l->iter_curentry->data; - l->iter_curentry = l->iter_curentry->next; - l->iter_pos++; - - return toret; -} - -int list_iterator_hasnext(const list_t *restrict l) { - if (! l->iter_active) return 0; - return (l->iter_pos < l->numels); -} - -int list_iterator_stop(list_t *restrict l) { - if (! l->iter_active) return 0; - l->iter_pos = 0; - l->iter_active = 0; - return 1; -} - -int list_hash(const list_t *restrict l, list_hash_t *restrict hash) { - struct list_entry_s *x; - list_hash_t tmphash; - - assert(hash != NULL); - - tmphash = l->numels * 2 + 100; - if (l->attrs.hasher == NULL) { -#ifdef SIMCLIST_ALLOW_LOCATIONBASED_HASHES - /* ENABLE WITH CARE !! */ -#warning "Memlocation-based hash is consistent only for testing modification in the same program run." - int i; - - /* only use element references */ - for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { - for (i = 0; i < sizeof(x->data); i++) { - tmphash += (tmphash ^ (uintptr_t)x->data); - } - tmphash += tmphash % l->numels; - } -#else - return -1; -#endif - } else { - /* hash each element with the user-given function */ - for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { - tmphash += tmphash ^ l->attrs.hasher(x->data); - tmphash += tmphash % l->numels; - } - } - - *hash = tmphash; - - return 0; -} - -#ifndef SIMCLIST_NO_DUMPRESTORE -int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info) { - int32_t terminator_head, terminator_tail; - uint32_t elemlen; - off_t hop; - - - /* version */ - READ_ERRCHECK(fd, & info->version, sizeof(info->version)); - info->version = ntohs(info->version); - if (info->version > SIMCLIST_DUMPFORMAT_VERSION) { - errno = EILSEQ; - return -1; - } - - /* timestamp.tv_sec and timestamp.tv_usec */ - READ_ERRCHECK(fd, & info->timestamp.tv_sec, sizeof(info->timestamp.tv_sec)); - info->timestamp.tv_sec = ntohl(info->timestamp.tv_sec); - READ_ERRCHECK(fd, & info->timestamp.tv_usec, sizeof(info->timestamp.tv_usec)); - info->timestamp.tv_usec = ntohl(info->timestamp.tv_usec); - - /* list terminator (to check thereafter) */ - READ_ERRCHECK(fd, & terminator_head, sizeof(terminator_head)); - terminator_head = ntohl(terminator_head); - - /* list size */ - READ_ERRCHECK(fd, & info->list_size, sizeof(info->list_size)); - info->list_size = ntohl(info->list_size); - - /* number of elements */ - READ_ERRCHECK(fd, & info->list_numels, sizeof(info->list_numels)); - info->list_numels = ntohl(info->list_numels); - - /* length of each element (for checking for consistency) */ - READ_ERRCHECK(fd, & elemlen, sizeof(elemlen)); - elemlen = ntohl(elemlen); - - /* list hash */ - READ_ERRCHECK(fd, & info->list_hash, sizeof(info->list_hash)); - info->list_hash = ntohl(info->list_hash); - - /* check consistency */ - if (elemlen > 0) { - /* constant length, hop by size only */ - hop = info->list_size; - } else { - /* non-constant length, hop by size + all element length blocks */ - hop = info->list_size + elemlen*info->list_numels; - } - if (lseek(fd, hop, SEEK_CUR) == -1) { - return -1; - } - - /* read the trailing value and compare with terminator_head */ - READ_ERRCHECK(fd, & terminator_tail, sizeof(terminator_tail)); - terminator_tail = ntohl(terminator_tail); - - if (terminator_head == terminator_tail) - info->consistent = 1; - else - info->consistent = 0; - - return 0; -} - -int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info) { - int fd, ret; - - fd = open(filename, O_RDONLY, 0); - if (fd < 0) return -1; - - ret = list_dump_getinfo_filedescriptor(fd, info); - close(fd); - - return ret; -} - -int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len) { - struct list_entry_s *x; - void *ser_buf; - uint32_t bufsize; - struct timeval timeofday; - struct list_dump_header_s header; - - if (l->attrs.meter == NULL && l->attrs.serializer == NULL) { - errno = ENOTTY; - return -1; - } - - /**** DUMP FORMAT **** - - [ ver timestamp | totlen numels elemlen hash | DATA ] - - where DATA can be: - @ for constant-size list (element size is constant; elemlen > 0) - [ elem elem ... elem ] - @ for other lists (element size dictated by element_meter each time; elemlen <= 0) - [ size elem size elem ... size elem ] - - all integers are encoded in NETWORK BYTE FORMAT - *****/ - - - /* prepare HEADER */ - /* version */ - header.ver = htons( SIMCLIST_DUMPFORMAT_VERSION ); - - /* timestamp */ - gettimeofday(&timeofday, NULL); - header.timestamp_sec = htonl(timeofday.tv_sec); - header.timestamp_usec = htonl(timeofday.tv_usec); - - header.rndterm = htonl((int32_t)get_random()); - - /* total list size is postprocessed afterwards */ - - /* number of elements */ - header.numels = htonl(l->numels); - - /* include an hash, if possible */ - if (l->attrs.hasher != NULL) { - if (htonl(list_hash(l, & header.listhash)) != 0) { - /* could not compute list hash! */ - return -1; - } - } else { - header.listhash = htonl(0); - } - - header.totlistlen = header.elemlen = 0; - - /* leave room for the header at the beginning of the file */ - if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) { - /* errno set by lseek() */ - return -1; - } - - /* write CONTENT */ - if (l->numels > 0) { - /* SPECULATE that the list has constant element size */ - - if (l->attrs.serializer != NULL) { /* user user-specified serializer */ - /* get preliminary length of serialized element in header.elemlen */ - ser_buf = l->attrs.serializer(l->head_sentinel->next->data, & header.elemlen); - free(ser_buf); - /* request custom serialization of each element */ - for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { - ser_buf = l->attrs.serializer(x->data, &bufsize); - header.totlistlen += bufsize; - if (header.elemlen != 0) { /* continue on speculation */ - if (header.elemlen != bufsize) { - free(ser_buf); - /* constant element length speculation broken! */ - header.elemlen = 0; - header.totlistlen = 0; - x = l->head_sentinel; - if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) { - /* errno set by lseek() */ - return -1; - } - /* restart from the beginning */ - continue; - } - /* speculation confirmed */ - WRITE_ERRCHECK(fd, ser_buf, bufsize); - } else { /* speculation found broken */ - WRITE_ERRCHECK(fd, & bufsize, sizeof(size_t)); - WRITE_ERRCHECK(fd, ser_buf, bufsize); - } - free(ser_buf); - } - } else if (l->attrs.meter != NULL) { - header.elemlen = (uint32_t)l->attrs.meter(l->head_sentinel->next->data); - - /* serialize the element straight from its data */ - for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { - bufsize = l->attrs.meter(x->data); - header.totlistlen += bufsize; - if (header.elemlen != 0) { - if (header.elemlen != bufsize) { - /* constant element length speculation broken! */ - header.elemlen = 0; - header.totlistlen = 0; - x = l->head_sentinel; - /* restart from the beginning */ - continue; - } - WRITE_ERRCHECK(fd, x->data, bufsize); - } else { - WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t)); - WRITE_ERRCHECK(fd, x->data, bufsize); - } - } - } - /* adjust endianness */ - header.elemlen = htonl(header.elemlen); - header.totlistlen = htonl(header.totlistlen); - } - - /* write random terminator */ - WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); /* list terminator */ - - - /* write header */ - lseek(fd, 0, SEEK_SET); - - WRITE_ERRCHECK(fd, & header.ver, sizeof(header.ver)); /* version */ - WRITE_ERRCHECK(fd, & header.timestamp_sec, sizeof(header.timestamp_sec)); /* timestamp seconds */ - WRITE_ERRCHECK(fd, & header.timestamp_usec, sizeof(header.timestamp_usec)); /* timestamp microseconds */ - WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); /* random terminator */ - - WRITE_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen)); /* total length of elements */ - WRITE_ERRCHECK(fd, & header.numels, sizeof(header.numels)); /* number of elements */ - WRITE_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen)); /* size of each element, or 0 for independent */ - WRITE_ERRCHECK(fd, & header.listhash, sizeof(header.listhash)); /* list hash, or 0 for "ignore" */ - - - /* possibly store total written length in "len" */ - if (len != NULL) { - *len = sizeof(header) + ntohl(header.totlistlen); - } - - return 0; -} - -int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len) { - struct list_dump_header_s header; - unsigned long cnt; - void *buf; - uint32_t elsize, totreadlen, totmemorylen; - - memset(& header, 0, sizeof(header)); - - /* read header */ - - /* version */ - READ_ERRCHECK(fd, &header.ver, sizeof(header.ver)); - header.ver = ntohs(header.ver); - if (header.ver != SIMCLIST_DUMPFORMAT_VERSION) { - errno = EILSEQ; - return -1; - } - - /* timestamp */ - READ_ERRCHECK(fd, & header.timestamp_sec, sizeof(header.timestamp_sec)); - header.timestamp_sec = ntohl(header.timestamp_sec); - READ_ERRCHECK(fd, & header.timestamp_usec, sizeof(header.timestamp_usec)); - header.timestamp_usec = ntohl(header.timestamp_usec); - - /* list terminator */ - READ_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); - - header.rndterm = ntohl(header.rndterm); - - /* total list size */ - READ_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen)); - header.totlistlen = ntohl(header.totlistlen); - - /* number of elements */ - READ_ERRCHECK(fd, & header.numels, sizeof(header.numels)); - header.numels = ntohl(header.numels); - - /* length of every element, or '0' = variable */ - READ_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen)); - header.elemlen = ntohl(header.elemlen); - - /* list hash, or 0 = 'ignore' */ - READ_ERRCHECK(fd, & header.listhash, sizeof(header.listhash)); - header.listhash = ntohl(header.listhash); - - - /* read content */ - totreadlen = totmemorylen = 0; - if (header.elemlen > 0) { - /* elements have constant size = header.elemlen */ - if (l->attrs.unserializer != NULL) { - /* use unserializer */ - buf = malloc(header.elemlen); - for (cnt = 0; cnt < header.numels; cnt++) { - READ_ERRCHECK(fd, buf, header.elemlen); - list_append(l, l->attrs.unserializer(buf, & elsize)); - totmemorylen += elsize; - } - } else { - /* copy verbatim into memory */ - for (cnt = 0; cnt < header.numels; cnt++) { - buf = malloc(header.elemlen); - READ_ERRCHECK(fd, buf, header.elemlen); - list_append(l, buf); - } - totmemorylen = header.numels * header.elemlen; - } - totreadlen = header.numels * header.elemlen; - } else { - /* elements have variable size. Each element is preceded by its size */ - if (l->attrs.unserializer != NULL) { - /* use unserializer */ - for (cnt = 0; cnt < header.numels; cnt++) { - READ_ERRCHECK(fd, & elsize, sizeof(elsize)); - buf = malloc((size_t)elsize); - READ_ERRCHECK(fd, buf, elsize); - totreadlen += elsize; - list_append(l, l->attrs.unserializer(buf, & elsize)); - totmemorylen += elsize; - } - } else { - /* copy verbatim into memory */ - for (cnt = 0; cnt < header.numels; cnt++) { - READ_ERRCHECK(fd, & elsize, sizeof(elsize)); - buf = malloc(elsize); - READ_ERRCHECK(fd, buf, elsize); - totreadlen += elsize; - list_append(l, buf); - } - totmemorylen = totreadlen; - } - } - - READ_ERRCHECK(fd, &elsize, sizeof(elsize)); /* read list terminator */ - elsize = ntohl(elsize); - - /* possibly verify the list consistency */ - /* wrt hash */ - /* don't do that - if (header.listhash != 0 && header.listhash != list_hash(l)) { - errno = ECANCELED; - return -1; - } - */ - - /* wrt header */ - if (totreadlen != header.totlistlen && (int32_t)elsize == header.rndterm) { - errno = EPROTO; - return -1; - } - - /* wrt file */ - if (lseek(fd, 0, SEEK_CUR) != lseek(fd, 0, SEEK_END)) { - errno = EPROTO; - return -1; - } - - if (len != NULL) { - *len = totmemorylen; - } - - return 0; -} - -int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len) { - int fd, oflag, mode; - -#ifndef _WIN32 - oflag = O_RDWR | O_CREAT | O_TRUNC; - mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; -#else - oflag = _O_RDWR | _O_CREAT | _O_TRUNC; - mode = _S_IRUSR | _S_IWUSR | _S_IRGRP | _S_IROTH; -#endif - fd = open(filename, oflag, mode); - if (fd < 0) return -1; - - list_dump_filedescriptor(l, fd, len); - close(fd); - - return 0; -} - -int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len) { - int fd; - - fd = open(filename, O_RDONLY, 0); - if (fd < 0) return -1; - - list_restore_filedescriptor(l, fd, len); - close(fd); - - return 0; -} -#endif /* ifndef SIMCLIST_NO_DUMPRESTORE */ - - -static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos) { - if (tmp == NULL) return -1; - - /* fix mid pointer. This is wrt the PRE situation */ - if (l->numels % 2) { /* now odd */ - /* sort out the base case by hand */ - if (l->numels == 1) l->mid = NULL; - else if (pos >= l->numels/2) l->mid = l->mid->prev; - } else { /* now even */ - if (pos < l->numels/2) l->mid = l->mid->next; - } - - tmp->prev->next = tmp->next; - tmp->next->prev = tmp->prev; - - /* free what's to be freed */ - if (l->attrs.copy_data && tmp->data != NULL) - free(tmp->data); - - if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { - l->spareels[l->spareelsnum++] = tmp; - } else { - free(tmp); - } - - return 0; -} - -/* ready-made comparators and meters */ -#define SIMCLIST_NUMBER_COMPARATOR(type) int list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); } - -SIMCLIST_NUMBER_COMPARATOR(int8_t) -SIMCLIST_NUMBER_COMPARATOR(int16_t) -SIMCLIST_NUMBER_COMPARATOR(int32_t) -SIMCLIST_NUMBER_COMPARATOR(int64_t) - -SIMCLIST_NUMBER_COMPARATOR(uint8_t) -SIMCLIST_NUMBER_COMPARATOR(uint16_t) -SIMCLIST_NUMBER_COMPARATOR(uint32_t) -SIMCLIST_NUMBER_COMPARATOR(uint64_t) - -SIMCLIST_NUMBER_COMPARATOR(float) -SIMCLIST_NUMBER_COMPARATOR(double) - -int list_comparator_string(const void *a, const void *b) { return strcmp((const char *)b, (const char *)a); } - -/* ready-made metric functions */ -#define SIMCLIST_METER(type) size_t list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); } - -SIMCLIST_METER(int8_t) -SIMCLIST_METER(int16_t) -SIMCLIST_METER(int32_t) -SIMCLIST_METER(int64_t) - -SIMCLIST_METER(uint8_t) -SIMCLIST_METER(uint16_t) -SIMCLIST_METER(uint32_t) -SIMCLIST_METER(uint64_t) - -SIMCLIST_METER(float) -SIMCLIST_METER(double) - -size_t list_meter_string(const void *el) { return strlen((const char *)el) + 1; } - -/* ready-made hashing functions */ -#define SIMCLIST_HASHCOMPUTER(type) list_hash_t list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); } - -SIMCLIST_HASHCOMPUTER(int8_t) -SIMCLIST_HASHCOMPUTER(int16_t) -SIMCLIST_HASHCOMPUTER(int32_t) -SIMCLIST_HASHCOMPUTER(int64_t) - -SIMCLIST_HASHCOMPUTER(uint8_t) -SIMCLIST_HASHCOMPUTER(uint16_t) -SIMCLIST_HASHCOMPUTER(uint32_t) -SIMCLIST_HASHCOMPUTER(uint64_t) - -SIMCLIST_HASHCOMPUTER(float) -SIMCLIST_HASHCOMPUTER(double) - -list_hash_t list_hashcomputer_string(const void *el) { - size_t l; - list_hash_t hash = 123; - const char *str = (const char *)el; - char plus; - - for (l = 0; str[l] != '\0'; l++) { - if (l) plus = hash ^ str[l]; - else plus = hash ^ (str[l] - str[0]); - hash += (plus << (CHAR_BIT * (l % sizeof(list_hash_t)))); - } - - return hash; -} - - -#ifndef NDEBUG -static int list_repOk(const list_t *restrict l) { - int ok, i; - struct list_entry_s *s; - - ok = (l != NULL) && ( - /* head/tail checks */ - (l->head_sentinel != NULL && l->tail_sentinel != NULL) && - (l->head_sentinel != l->tail_sentinel) && (l->head_sentinel->prev == NULL && l->tail_sentinel->next == NULL) && - /* empty list */ - (l->numels > 0 || (l->mid == NULL && l->head_sentinel->next == l->tail_sentinel && l->tail_sentinel->prev == l->head_sentinel)) && - /* spare elements checks */ - l->spareelsnum <= SIMCLIST_MAX_SPARE_ELEMS - ); - - if (!ok) return 0; - - if (l->numels >= 1) { - /* correct referencing */ - for (i = -1, s = l->head_sentinel; i < (int)(l->numels-1)/2 && s->next != NULL; i++, s = s->next) { - if (s->next->prev != s) break; - } - ok = (i == (int)(l->numels-1)/2 && l->mid == s); - if (!ok) return 0; - for (; s->next != NULL; i++, s = s->next) { - if (s->next->prev != s) break; - } - ok = (i == (int)l->numels && s == l->tail_sentinel); - } - - return ok; -} - -static int list_attrOk(const list_t *restrict l) { - int ok; - - ok = (l->attrs.copy_data == 0 || l->attrs.meter != NULL); - return ok; -} - -#endif - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/table.c b/libs/libks/src/table.c deleted file mode 100644 index d948dc5885..0000000000 --- a/libs/libks/src/table.c +++ /dev/null @@ -1,4094 +0,0 @@ -/* - * Generic hash table handler... - * - * Copyright 2000 by Gray Watson. - * - * This file is part of the table package. - * - * Permission to use, copy, modify, and distribute this software for - * any purpose and without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies, and that the name of Gray Watson not be used in advertising - * or publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: table.c,v 1.19 2000/03/09 03:30:41 gray Exp $ - */ - -/* - * Handles basic hash-table manipulations. This is an implementation - * of open hashing with an array of buckets holding linked lists of - * elements. Each element has a key and a data. The user indexes on - * the key to find the data. See the typedefs in table_loc.h for more - * information. - */ - -#include -#include -#include -#include - -#if defined(unix) || defined(__APPLE__) - -#include - -#else - -#include -#include -#define NO_MMAP -#ifndef open -#define open _open -#endif -#ifndef fdopen -#define fdopen _fdopen -#endif -#endif - -#ifndef NO_MMAP - -#include -#include - -#ifndef MAP_FAILED -#define MAP_FAILED (caddr_t)0L -#endif - -#endif - -#define TABLE_MAIN - -#include "table.h" -#include "table_loc.h" - -#ifdef DMALLOC -#include "dmalloc.h" -#endif - -static char *rcs_id = - "$Id: table.c,v 1.19 2000/03/09 03:30:41 gray Exp $"; - -/* - * Version id for the library. You also need to add an entry to the - * NEWS and ChangeLog files. - */ -static char *version_id = "$TableVersion: 4.3.0 March 8, 2000 $"; - -/****************************** local functions ******************************/ - -/* - * static table_entry_t *first_entry - * - * DESCRIPTION: - * - * Return the first entry in the table. It will set the linear - * structure counter to the position of the first entry. - * - * RETURNS: - * - * Success: A pointer to the first entry in the table. - * - * Failure: NULL if there is no first entry. - * - * ARGUMENTS: - * - * table_p -> Table whose next entry we are finding. - * - * linear_p <-> Pointer to a linear structure which we will advance - * and then find the corresponding entry. - */ -static table_entry_t *first_entry(const table_t *table_p, - table_linear_t *linear_p) -{ - table_entry_t *entry_p; - unsigned int bucket_c = 0; - - /* look for the first non-empty bucket */ - for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) { - entry_p = table_p->ta_buckets[bucket_c]; - if (entry_p != NULL) { - if (linear_p != NULL) { - linear_p->tl_bucket_c = bucket_c; - linear_p->tl_entry_c = 0; - } - return TABLE_POINTER(table_p, table_entry_t *, entry_p); - } - } - - return NULL; -} - -/* - * static table_entry_t *next_entry - * - * DESCRIPTION: - * - * Return the next entry in the table which is past the position in - * our linear pointer. It will advance the linear structure counters. - * - * RETURNS: - * - * Success: A pointer to the next entry in the table. - * - * Failure: NULL. - * - * ARGUMENTS: - * - * table_p -> Table whose next entry we are finding. - * - * linear_p <-> Pointer to a linear structure which we will advance - * and then find the corresponding entry. - * - * error_p <- Pointer to an integer which when the routine returns - * will contain a table error code. - */ -static table_entry_t *next_entry(const table_t *table_p, - table_linear_t *linear_p, int *error_p) -{ - table_entry_t *entry_p; - int entry_c; - - /* can't next if we haven't first-ed */ - if (linear_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_LINEAR); - return NULL; - } - - if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) { - /* - * NOTE: this might happen if we delete an item which shortens the - * table bucket numbers. - */ - SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); - return NULL; - } - - linear_p->tl_entry_c++; - - /* find the entry which is the nth in the list */ - entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; - /* NOTE: we swap the order here to be more efficient */ - for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) { - /* did we reach the end of the list? */ - if (entry_p == NULL) { - break; - } - entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p; - } - - /* did we find an entry in the current bucket? */ - if (entry_p != NULL) { - SET_POINTER(error_p, TABLE_ERROR_NONE); - return TABLE_POINTER(table_p, table_entry_t *, entry_p); - } - - /* find the first entry in the next non-empty bucket */ - - linear_p->tl_entry_c = 0; - for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n; - linear_p->tl_bucket_c++) { - entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; - if (entry_p != NULL) { - SET_POINTER(error_p, TABLE_ERROR_NONE); - return TABLE_POINTER(table_p, table_entry_t *, entry_p); - } - } - - SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); - return NULL; -} - -/* - * static table_entry_t *this_entry - * - * DESCRIPTION: - * - * Return the entry pointer in the table which is currently being - * indicated by our linear pointer. - * - * RETURNS: - * - * Success: A pointer to the next entry in the table. - * - * Failure: NULL. - * - * ARGUMENTS: - * - * table_p -> Table whose next entry we are finding. - * - * linear_p -> Pointer to a linear structure which we will find the - * corresponding entry. - * - * error_p <- Pointer to an integer which when the routine returns - * will contain a table error code. - */ -static table_entry_t *this_entry(const table_t *table_p, - const table_linear_t *linear_p, - int *error_p) -{ - table_entry_t *entry_p; - int entry_c; - - /* can't next if we haven't first-ed */ - if (linear_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_LINEAR); - return NULL; - } - - if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) { - /* - * NOTE: this might happen if we delete an item which shortens the - * table bucket numbers. - */ - SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); - return NULL; - } - - /* find the entry which is the nth in the list */ - entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; - - /* NOTE: we swap the order here to be more efficient */ - for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) { - /* did we reach the end of the list? */ - if (entry_p == NULL) { - break; - } - entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p; - } - - /* did we find an entry in the current bucket? */ - if (entry_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); - return NULL; - } - else { - SET_POINTER(error_p, TABLE_ERROR_NONE); - return TABLE_POINTER(table_p, table_entry_t *, entry_p); - } -} - -/* - * static unsigned int hash - * - * DESCRIPTION: - * - * Hash a variable-length key into a 32-bit value. Every bit of the - * key affects every bit of the return value. Every 1-bit and 2-bit - * delta achieves avalanche. About (6 * len + 35) instructions. The - * best hash table sizes are powers of 2. There is no need to use mod - * (sooo slow!). If you need less than 32 bits, use a bitmask. For - * example, if you need only 10 bits, do h = (h & hashmask(10)); In - * which case, the hash table should have hashsize(10) elements. - * - * By Bob Jenkins, 1996. bob_jenkins@compuserve.com. You may use - * this code any way you wish, private, educational, or commercial. - * It's free. See - * http://ourworld.compuserve.com/homepages/bob_jenkins/evahash.htm - * Use for hash table lookup, or anything where one collision in 2^^32 - * is acceptable. Do NOT use for cryptographic purposes. - * - * RETURNS: - * - * Returns a 32-bit hash value. - * - * ARGUMENTS: - * - * key - Key (the unaligned variable-length array of bytes) that we - * are hashing. - * - * length - Length of the key in bytes. - * - * init_val - Initialization value of the hash if you need to hash a - * number of strings together. For instance, if you are hashing N - * strings (unsigned char **)keys, do it like this: - * - * for (i=0, h=0; i= 12; len -= 12) { - a += (key_p[0] - + ((unsigned int)key_p[1] << 8) - + ((unsigned int)key_p[2] << 16) - + ((unsigned int)key_p[3] << 24)); - b += (key_p[4] - + ((unsigned int)key_p[5] << 8) - + ((unsigned int)key_p[6] << 16) - + ((unsigned int)key_p[7] << 24)); - c += (key_p[8] - + ((unsigned int)key_p[9] << 8) - + ((unsigned int)key_p[10] << 16) - + ((unsigned int)key_p[11] << 24)); - HASH_MIX(a,b,c); - key_p += 12; - } - - c += length; - - /* all the case statements fall through to the next */ - switch(len) { - case 11: - c += ((unsigned int)key_p[10] << 24); - case 10: - c += ((unsigned int)key_p[9] << 16); - case 9: - c += ((unsigned int)key_p[8] << 8); - /* the first byte of c is reserved for the length */ - case 8: - b += ((unsigned int)key_p[7] << 24); - case 7: - b += ((unsigned int)key_p[6] << 16); - case 6: - b += ((unsigned int)key_p[5] << 8); - case 5: - b += key_p[4]; - case 4: - a += ((unsigned int)key_p[3] << 24); - case 3: - a += ((unsigned int)key_p[2] << 16); - case 2: - a += ((unsigned int)key_p[1] << 8); - case 1: - a += key_p[0]; - /* case 0: nothing left to add */ - } - HASH_MIX(a, b, c); - - return c; -} - -/* - * static int entry_size - * - * DESCRIPTION: - * - * Calculates the appropriate size of an entry to include the key and - * data sizes as well as any associated alignment to the data. - * - * RETURNS: - * - * The associated size of the entry. - * - * ARGUMENTS: - * - * table_p - Table associated with the entries whose size we are - * determining. - * - * key_size - Size of the entry key. - * - * data - Size of the entry data. - */ -static int entry_size(const table_t *table_p, const unsigned int key_size, - const unsigned int data_size) -{ - int size, left; - - /* initial size -- key is already aligned if right after struct */ - size = sizeof(struct table_shell_st) + key_size; - - /* if there is no alignment then it is easy */ - if (table_p->ta_data_align == 0) { - return size + data_size; - } - - /* add in our alignement */ - left = size & (table_p->ta_data_align - 1); - if (left > 0) { - size += table_p->ta_data_align - left; - } - - /* we add the data size here after the alignment */ - size += data_size; - - return size; -} - -/* - * static unsigned char *entry_data_buf - * - * DESCRIPTION: - * - * Companion to the ENTRY_DATA_BUF macro but this handles any - * associated alignment to the data in the entry. - * - * NOTE: we assume here that the data-alignment is > 0. - * - * RETURNS: - * - * Pointer to the data segment of the entry. - * - * ARGUMENTS: - * - * table_p - Table associated with the entry. - * - * entry_p - Entry whose data pointer we are determining. - */ -static unsigned char *entry_data_buf(const table_t *table_p, - const table_entry_t *entry_p) -{ - const unsigned char *buf_p; - unsigned int size, pad; - - buf_p = entry_p->te_key_buf + entry_p->te_key_size; - - /* we need the size of the space before the data */ - size = sizeof(struct table_shell_st) + entry_p->te_key_size; - - /* add in our alignment */ - pad = size & (table_p->ta_data_align - 1); - if (pad > 0) { - pad = table_p->ta_data_align - pad; - } - - return (unsigned char *)buf_p + pad; -} - -/******************************* sort routines *******************************/ - -/* - * static int local_compare - * - * DESCRIPTION: - * - * Compare two entries by calling user's compare program or by using - * memcmp. - * - * RETURNS: - * - * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. - * - * ARGUMENTS: - * - * p1 - First entry pointer to compare. - * - * p2 - Second entry pointer to compare. - * - * compare - User comparison function. Ignored. - * - * table_p - Associated table being ordered. Ignored. - * - * err_bp - Pointer to an integer which will be set with 1 if an error - * has occurred. It cannot be NULL. - */ -static int local_compare(const void *p1, const void *p2, - table_compare_t compare, const table_t *table_p, - int *err_bp) -{ - const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2; - int cmp; - unsigned int size; - - /* compare as many bytes as we can */ - size = (*ent1_p)->te_key_size; - if ((*ent2_p)->te_key_size < size) { - size = (*ent2_p)->te_key_size; - } - cmp = memcmp(ENTRY_KEY_BUF(*ent1_p), ENTRY_KEY_BUF(*ent2_p), size); - /* if common-size equal, then if next more bytes, it is larger */ - if (cmp == 0) { - cmp = (*ent1_p)->te_key_size - (*ent2_p)->te_key_size; - } - - *err_bp = 0; - return cmp; -} - -/* - * static int local_compare_pos - * - * DESCRIPTION: - * - * Compare two entries by calling user's compare program or by using - * memcmp. - * - * RETURNS: - * - * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. - * - * ARGUMENTS: - * - * p1 - First entry pointer to compare. - * - * p2 - Second entry pointer to compare. - * - * compare - User comparison function. Ignored. - * - * table_p - Associated table being ordered. - * - * err_bp - Pointer to an integer which will be set with 1 if an error - * has occurred. It cannot be NULL. - */ -static int local_compare_pos(const void *p1, const void *p2, - table_compare_t compare, - const table_t *table_p, int *err_bp) -{ - const table_linear_t *lin1_p = p1, *lin2_p = p2; - const table_entry_t *ent1_p, *ent2_p; - int cmp, ret; - unsigned int size; - - /* get entry pointers */ - ent1_p = this_entry(table_p, lin1_p, &ret); - ent2_p = this_entry(table_p, lin2_p, &ret); - if (ent1_p == NULL || ent2_p == NULL) { - *err_bp = 1; - return 0; - } - - /* compare as many bytes as we can */ - size = ent1_p->te_key_size; - if (ent2_p->te_key_size < size) { - size = ent2_p->te_key_size; - } - cmp = memcmp(ENTRY_KEY_BUF(ent1_p), ENTRY_KEY_BUF(ent2_p), size); - /* if common-size equal, then if next more bytes, it is larger */ - if (cmp == 0) { - cmp = ent1_p->te_key_size - ent2_p->te_key_size; - } - - *err_bp = 0; - return cmp; -} - -/* - * static int external_compare - * - * DESCRIPTION: - * - * Compare two entries by calling user's compare program or by using - * memcmp. - * - * RETURNS: - * - * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. - * - * ARGUMENTS: - * - * p1 - First entry pointer to compare. - * - * p2 - Second entry pointer to compare. - * - * user_compare - User comparison function. - * - * table_p - Associated table being ordered. - * - * err_bp - Pointer to an integer which will be set with 1 if an error - * has occurred. It cannot be NULL. - */ -static int external_compare(const void *p1, const void *p2, - table_compare_t user_compare, - const table_t *table_p, int *err_bp) -{ - const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2; - /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */ - *err_bp = 0; - return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size, - ENTRY_DATA_BUF(table_p, *ent1_p), - (*ent1_p)->te_data_size, - ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size, - ENTRY_DATA_BUF(table_p, *ent2_p), - (*ent2_p)->te_data_size); -} - -/* - * static int external_compare_pos - * - * DESCRIPTION: - * - * Compare two entries by calling user's compare program or by using - * memcmp. - * - * RETURNS: - * - * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. - * - * ARGUMENTS: - * - * p1 - First entry pointer to compare. - * - * p2 - Second entry pointer to compare. - * - * user_compare - User comparison function. - * - * table_p - Associated table being ordered. - * - * err_bp - Pointer to an integer which will be set with 1 if an error - * has occurred. It cannot be NULL. - */ -static int external_compare_pos(const void *p1, const void *p2, - table_compare_t user_compare, - const table_t *table_p, int *err_bp) -{ - const table_linear_t *lin1_p = p1, *lin2_p = p2; - const table_entry_t *ent1_p, *ent2_p; - int ret; - - /* get entry pointers */ - ent1_p = this_entry(table_p, lin1_p, &ret); - ent2_p = this_entry(table_p, lin2_p, &ret); - if (ent1_p == NULL || ent2_p == NULL) { - *err_bp = 1; - return 0; - } - - /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */ - *err_bp = 0; - return user_compare(ENTRY_KEY_BUF(ent1_p), (ent1_p)->te_key_size, - ENTRY_DATA_BUF(table_p, ent1_p), ent1_p->te_data_size, - ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size, - ENTRY_DATA_BUF(table_p, ent2_p), ent2_p->te_data_size); -} - -/* - * static int external_compare_align - * - * DESCRIPTION: - * - * Compare two entries by calling user's compare program or by using - * memcmp. Alignment information is necessary. - * - * RETURNS: - * - * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. - * - * ARGUMENTS: - * - * p1 - First entry pointer to compare. - * - * p2 - Second entry pointer to compare. - * - * user_compare - User comparison function. - * - * table_p - Associated table being ordered. - * - * err_bp - Pointer to an integer which will be set with 1 if an error - * has occurred. It cannot be NULL. - */ -static int external_compare_align(const void *p1, const void *p2, - table_compare_t user_compare, - const table_t *table_p, int *err_bp) -{ - const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2; - /* since we are aligned we have to use the entry_data_buf function */ - *err_bp = 0; - return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size, - entry_data_buf(table_p, *ent1_p), - (*ent1_p)->te_data_size, - ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size, - entry_data_buf(table_p, *ent2_p), - (*ent2_p)->te_data_size); -} - -/* - * static int external_compare_align_pos - * - * DESCRIPTION: - * - * Compare two entries by calling user's compare program or by using - * memcmp. Alignment information is necessary. - * - * RETURNS: - * - * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. - * - * ARGUMENTS: - * - * p1 - First entry pointer to compare. - * - * p2 - Second entry pointer to compare. - * - * user_compare - User comparison function. - * - * table_p - Associated table being ordered. - * - * err_bp - Pointer to an integer which will be set with 1 if an error - * has occurred. It cannot be NULL. - */ -static int external_compare_align_pos(const void *p1, const void *p2, - table_compare_t user_compare, - const table_t *table_p, int *err_bp) -{ - const table_linear_t *lin1_p = p1, *lin2_p = p2; - const table_entry_t *ent1_p, *ent2_p; - int ret; - - /* get entry pointers */ - ent1_p = this_entry(table_p, lin1_p, &ret); - ent2_p = this_entry(table_p, lin2_p, &ret); - if (ent1_p == NULL || ent2_p == NULL) { - *err_bp = 1; - return 0; - } - - /* since we are aligned we have to use the entry_data_buf function */ - *err_bp = 0; - return user_compare(ENTRY_KEY_BUF(ent1_p), ent1_p->te_key_size, - entry_data_buf(table_p, ent1_p), ent1_p->te_data_size, - ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size, - entry_data_buf(table_p, ent2_p), ent2_p->te_data_size); -} - -/* - * static void swap_bytes - * - * DESCRIPTION: - * - * Swap the values between two items of a specified size. - * - * RETURNS: - * - * None. - * - * ARGUMENTS: - * - * item1_p -> Pointer to the first item. - * - * item2_p -> Pointer to the first item. - * - * ele_size -> Size of the two items. - */ -static void swap_bytes(unsigned char *item1_p, unsigned char *item2_p, - int ele_size) -{ - unsigned char char_temp; - - for (; ele_size > 0; ele_size--) { - char_temp = *item1_p; - *item1_p = *item2_p; - *item2_p = char_temp; - item1_p++; - item2_p++; - } -} - -/* - * static void insert_sort - * - * DESCRIPTION: - * - * Do an insertion sort which is faster for small numbers of items and - * better if the items are already sorted. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * first_p <-> Start of the list that we are splitting. - * - * last_p <-> Last entry in the list that we are splitting. - * - * holder_p <-> Location of hold area we can store an entry. - * - * ele_size -> Size of the each element in the list. - * - * compare -> Our comparison function. - * - * user_compare -> User comparison function. Could be NULL if we are - * just using a local comparison function. - * - * table_p -> Associated table being sorted. - */ -static int insert_sort(unsigned char *first_p, unsigned char *last_p, - unsigned char *holder_p, - const unsigned int ele_size, compare_t compare, - table_compare_t user_compare, table_t *table_p) -{ - unsigned char *inner_p, *outer_p; - int ret, err_b; - - for (outer_p = first_p + ele_size; outer_p <= last_p; ) { - - /* look for the place to insert the entry */ - for (inner_p = outer_p - ele_size; - inner_p >= first_p; - inner_p -= ele_size) { - ret = compare(outer_p, inner_p, user_compare, table_p, &err_b); - if (err_b) { - return TABLE_ERROR_COMPARE; - } - if (ret >= 0) { - break; - } - } - inner_p += ele_size; - - /* do we need to insert the entry in? */ - if (outer_p != inner_p) { - /* - * Now we shift the entry down into its place in the already - * sorted list. - */ - memcpy(holder_p, outer_p, ele_size); - memmove(inner_p + ele_size, inner_p, outer_p - inner_p); - memcpy(inner_p, holder_p, ele_size); - } - - outer_p += ele_size; - } - - return TABLE_ERROR_NONE; -} - -/* - * static int split - * - * DESCRIPTION: - * - * This sorts an array of longs via the quick sort algorithm (it's - * pretty quick) - * - * RETURNS: - * - * None. - * - * ARGUMENTS: - * - * first_p -> Start of the list that we are splitting. - * - * last_p -> Last entry in the list that we are splitting. - * - * ele_size -> Size of the each element in the list. - * - * compare -> Our comparison function. - * - * user_compare -> User comparison function. Could be NULL if we are - * just using a local comparison function. - * - * table_p -> Associated table being sorted. - */ -static int split(unsigned char *first_p, unsigned char *last_p, - const unsigned int ele_size, compare_t compare, - table_compare_t user_compare, table_t *table_p) -{ - unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p; - unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS], *pivot; - unsigned int width, split_c = 0; - int size1, size2, min_qsort_size; - int ret, err_b; - - /* - * Allocate some space for our pivot value. We also use this as - * holder space for our insert sort. - */ - pivot = alloca(ele_size); - if (pivot == NULL) { - /* what else can we do? */ - abort(); - } - - min_qsort_size = MAX_QSORT_MANY * ele_size; - - while (1) { - - /* find the left, right, and mid point */ - left_p = first_p; - right_p = last_p; - /* is there a faster way to find this? */ - width = (last_p - first_p) / ele_size; - pivot_p = first_p + ele_size * (width >> 1); - - /* - * Find which of the left, middle, and right elements is the - * median (Knuth vol3 p123). - */ - ret = compare(first_p, pivot_p, user_compare, table_p, &err_b); - if (err_b) { - return TABLE_ERROR_COMPARE; - } - if (ret > 0) { - swap_bytes(first_p, pivot_p, ele_size); - } - ret = compare(pivot_p, last_p, user_compare, table_p, &err_b); - if (err_b) { - return TABLE_ERROR_COMPARE; - } - if (ret > 0) { - swap_bytes(pivot_p, last_p, ele_size); - ret = compare(first_p, pivot_p, user_compare, table_p, &err_b); - if (err_b) { - return TABLE_ERROR_COMPARE; - } - if (ret > 0) { - swap_bytes(first_p, pivot_p, ele_size); - } - } - - /* - * save our pivot so we don't have to worry about hitting and - * swapping it elsewhere while we iterate across the list below. - */ - memcpy(pivot, pivot_p, ele_size); - - do { - - /* shift the left side up until we reach the pivot value */ - while (1) { - ret = compare(left_p, pivot, user_compare, table_p, &err_b); - if (err_b) { - return TABLE_ERROR_COMPARE; - } - if (ret >= 0) { - break; - } - left_p += ele_size; - } - /* shift the right side down until we reach the pivot value */ - while (1) { - ret = compare(pivot, right_p, user_compare, table_p, &err_b); - if (err_b) { - return TABLE_ERROR_COMPARE; - } - if (ret >= 0) { - break; - } - right_p -= ele_size; - } - - /* if we met in the middle then we are done */ - if (left_p == right_p) { - left_p += ele_size; - right_p -= ele_size; - break; - } - else if (left_p < right_p) { - /* - * swap the left and right since they both were on the wrong - * size of the pivot and continue - */ - swap_bytes(left_p, right_p, ele_size); - left_p += ele_size; - right_p -= ele_size; - } - } while (left_p <= right_p); - - /* Rename variables to make more sense. This will get optimized out. */ - right_first_p = left_p; - left_last_p = right_p; - - /* determine the size of the left and right hand parts */ - size1 = left_last_p - first_p; - size2 = last_p - right_first_p; - - /* is the 1st half small enough to just insert-sort? */ - if (size1 < min_qsort_size) { - - /* use the pivot as our temporary space */ - ret = insert_sort(first_p, left_last_p, pivot, ele_size, compare, - user_compare, table_p); - if (ret != TABLE_ERROR_NONE) { - return ret; - } - - /* is the 2nd part small as well? */ - if (size2 < min_qsort_size) { - - /* use the pivot as our temporary space */ - ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare, - user_compare, table_p); - if (ret != TABLE_ERROR_NONE) { - return ret; - } - - /* pop a partition off our stack */ - if (split_c == 0) { - /* we are done */ - return TABLE_ERROR_NONE; - } - split_c--; - first_p = firsts[split_c]; - last_p = lasts[split_c]; - } - else { - /* we can just handle the right side immediately */ - first_p = right_first_p; - /* last_p = last_p */ - } - } - else if (size2 < min_qsort_size) { - - /* use the pivot as our temporary space */ - ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare, - user_compare, table_p); - if (ret != TABLE_ERROR_NONE) { - return ret; - } - - /* we can just handle the left side immediately */ - /* first_p = first_p */ - last_p = left_last_p; - } - else { - /* - * neither partition is small, we'll have to push the larger one - * of them on the stack - */ - if (split_c >= MAX_QSORT_SPLITS) { - /* sanity check here -- we should never get here */ - abort(); - } - if (size1 > size2) { - /* push the left partition on the stack */ - firsts[split_c] = first_p; - lasts[split_c] = left_last_p; - split_c++; - /* continue handling the right side */ - first_p = right_first_p; - /* last_p = last_p */ - } - else { - /* push the right partition on the stack */ - firsts[split_c] = right_first_p; - lasts[split_c] = last_p; - split_c++; - /* continue handling the left side */ - /* first_p = first_p */ - last_p = left_last_p; - } - } - } - - return TABLE_ERROR_NONE; -} - -/*************************** exported routines *******************************/ - -/* - * table_t *table_alloc - * - * DESCRIPTION: - * - * Allocate a new table structure. - * - * RETURNS: - * - * A pointer to the new table structure which must be passed to - * table_free to be deallocated. On error a NULL is returned. - * - * ARGUMENTS: - * - * bucket_n - Number of buckets for the hash table. Our current hash - * value works best with base two numbers. Set to 0 to take the - * library default of 1024. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ -table_t *table_alloc(const unsigned int bucket_n, int *error_p) -{ - table_t *table_p = NULL; - unsigned int buck_n; - - /* allocate a table structure */ - table_p = malloc(sizeof(table_t)); - if (table_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - return NULL; - } - - if (bucket_n > 0) { - buck_n = bucket_n; - } - else { - buck_n = DEFAULT_SIZE; - } - - /* allocate the buckets which are NULLed */ - table_p->ta_buckets = (table_entry_t **)calloc(buck_n, - sizeof(table_entry_t *)); - if (table_p->ta_buckets == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - free(table_p); - return NULL; - } - - /* initialize structure */ - table_p->ta_magic = TABLE_MAGIC; - table_p->ta_flags = 0; - table_p->ta_bucket_n = buck_n; - table_p->ta_entry_n = 0; - table_p->ta_data_align = 0; - table_p->ta_linear.tl_magic = 0; - table_p->ta_linear.tl_bucket_c = 0; - table_p->ta_linear.tl_entry_c = 0; - table_p->ta_mmap = NULL; - table_p->ta_file_size = 0; - table_p->ta_mem_pool = NULL; - table_p->ta_alloc_func = NULL; - table_p->ta_resize_func = NULL; - table_p->ta_free_func = NULL; - - SET_POINTER(error_p, TABLE_ERROR_NONE); - return table_p; -} - -/* - * table_t *table_alloc_in_pool - * - * DESCRIPTION: - * - * Allocate a new table structure in a memory pool or using - * alternative allocation and free functions. - * - * RETURNS: - * - * A pointer to the new table structure which must be passed to - * table_free to be deallocated. On error a NULL is returned. - * - * ARGUMENTS: - * - * bucket_n - Number of buckets for the hash table. Our current hash - * value works best with base two numbers. Set to 0 to take the - * library default of 1024. - * - * mem_pool <-> Memory pool to associate with the table. Can be NULL. - * - * alloc_func -> Allocate function we are overriding malloc() with. - * - * resize_func -> Resize function we are overriding the standard - * memory resize/realloc with. This can be NULL in which cause the - * library will allocate, copy, and free itself. - * - * free_func -> Free function we are overriding free() with. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ -table_t *table_alloc_in_pool(const unsigned int bucket_n, - void *mem_pool, - table_mem_alloc_t alloc_func, - table_mem_resize_t resize_func, - table_mem_free_t free_func, int *error_p) -{ - table_t *table_p = NULL; - unsigned int buck_n, size; - - /* make sure we have real functions, mem_pool and resize_func can be NULL */ - if (alloc_func == NULL || free_func == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ARG_NULL); - return NULL; - } - - /* allocate a table structure */ - table_p = alloc_func(mem_pool, sizeof(table_t)); - if (table_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - return NULL; - } - - if (bucket_n > 0) { - buck_n = bucket_n; - } - else { - buck_n = DEFAULT_SIZE; - } - - /* allocate the buckets which are NULLed */ - size = buck_n * sizeof(table_entry_t *); - table_p->ta_buckets = (table_entry_t **)alloc_func(mem_pool, size); - if (table_p->ta_buckets == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - (void)free_func(mem_pool, table_p, sizeof(table_t)); - return NULL; - } - /* - * We zero it ourselves to save the necessity of having a - * table_mem_calloc_t memory override function. - */ - memset(table_p->ta_buckets, 0, size); - - /* initialize structure */ - table_p->ta_magic = TABLE_MAGIC; - table_p->ta_flags = 0; - table_p->ta_bucket_n = buck_n; - table_p->ta_entry_n = 0; - table_p->ta_data_align = 0; - table_p->ta_linear.tl_magic = 0; - table_p->ta_linear.tl_bucket_c = 0; - table_p->ta_linear.tl_entry_c = 0; - table_p->ta_mmap = NULL; - table_p->ta_file_size = 0; - table_p->ta_mem_pool = mem_pool; - table_p->ta_alloc_func = alloc_func; - table_p->ta_resize_func = resize_func; - table_p->ta_free_func = free_func; - - SET_POINTER(error_p, TABLE_ERROR_NONE); - return table_p; -} - -/* - * int table_attr - * - * DESCRIPTION: - * - * Set the attributes for the table. The available attributes are - * specified at the top of table.h. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to a table structure which we will be altering. - * - * attr - Attribute(s) that we will be applying to the table. - */ -int table_attr(table_t *table_p, const int attr) -{ - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - - table_p->ta_flags = attr; - - return TABLE_ERROR_NONE; -} - -/* - * int table_set_data_alignment - * - * DESCRIPTION: - * - * Set the alignment for the data in the table. This is used when you - * want to store binary data types and refer to them directly out of - * the table storage. For instance if you are storing integers as - * data in the table and want to be able to retrieve the location of - * the interger and then increment it as (*loc_p)++. Otherwise you - * would have to memcpy it out to an integer, increment it, and memcpy - * it back. If you are storing character data, no alignment is - * necessary. - * - * For most data elements, sizeof(long) is recommended unless you use - * smaller data types exclusively. - * - * WARNING: If necessary, you must set the data alignment before any - * data gets put into the table. Otherwise a TABLE_ERROR_NOT_EMPTY - * error will be returned. - * - * NOTE: there is no way to set the key data alignment although it - * should automatically be long aligned. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to a table structure which we will be altering. - * - * alignment - Alignment requested for the data. Must be a power of - * 2. Set to 0 for none. - */ -int table_set_data_alignment(table_t *table_p, const int alignment) -{ - int val; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (table_p->ta_entry_n > 0) { - return TABLE_ERROR_NOT_EMPTY; - } - - /* defaults */ - if (alignment < 2) { - table_p->ta_data_align = 0; - } - else { - /* verify we have a base 2 number */ - for (val = 2; val < MAX_ALIGNMENT; val *= 2) { - if (val == alignment) { - break; - } - } - if (val >= MAX_ALIGNMENT) { - return TABLE_ERROR_ALIGNMENT; - } - table_p->ta_data_align = alignment; - } - - return TABLE_ERROR_NONE; -} - -/* - * int table_clear - * - * DESCRIPTION: - * - * Clear out and free all elements in a table structure. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer that we will be clearing. - */ -int table_clear(table_t *table_p) -{ - int final = TABLE_ERROR_NONE; - table_entry_t *entry_p, *next_p; - table_entry_t **bucket_p, **bounds_p; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - -#ifndef NO_MMAP - /* no mmap support so immediate error */ - if (table_p->ta_mmap != NULL) { - return TABLE_ERROR_MMAP_OP; - } -#endif - - /* free the table allocation and table structure */ - bounds_p = table_p->ta_buckets + table_p->ta_bucket_n; - for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) { - for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) { - /* record the next pointer before we free */ - next_p = entry_p->te_next_p; - if (table_p->ta_free_func == NULL) { - free(entry_p); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, - entry_size(table_p, - entry_p->te_key_size, - entry_p->te_data_size))) { - final = TABLE_ERROR_FREE; - } - } - - /* clear the bucket entry after we free its entries */ - *bucket_p = NULL; - } - - /* reset table state info */ - table_p->ta_entry_n = 0; - table_p->ta_linear.tl_magic = 0; - table_p->ta_linear.tl_bucket_c = 0; - table_p->ta_linear.tl_entry_c = 0; - - return final; -} - -/* - * int table_free - * - * DESCRIPTION: - * - * Deallocates a table structure. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer that we will be freeing. - */ -int table_free(table_t *table_p) -{ - int ret; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - -#ifndef NO_MMAP - /* no mmap support so immediate error */ - if (table_p->ta_mmap != NULL) { - return TABLE_ERROR_MMAP_OP; - } -#endif - - ret = table_clear(table_p); - - if (table_p->ta_buckets != NULL) { - if (table_p->ta_free_func == NULL) { - free(table_p->ta_buckets); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, - table_p->ta_buckets, - table_p->ta_bucket_n * - sizeof(table_entry_t *))) { - return TABLE_ERROR_FREE; - } - } - table_p->ta_magic = 0; - if (table_p->ta_free_func == NULL) { - free(table_p); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, table_p, - sizeof(table_t))) { - if (ret == TABLE_ERROR_NONE) { - ret = TABLE_ERROR_FREE; - } - } - - return ret; -} - -/* - * int table_insert_kd - * - * DESCRIPTION: - * - * Like table_insert except it passes back a pointer to the key and - * the data buffers after they have been inserted into the table - * structure. - * - * This routine adds a key/data pair both of which are made up of a - * buffer of bytes and an associated size. Both the key and the data - * will be copied into buffers allocated inside the table. If the key - * exists already, the associated data will be replaced if the - * overwrite flag is set, otherwise an error is returned. - * - * NOTE: be very careful changing the values since the table library - * provides the pointers to its memory. The key can _never_ be - * changed otherwise you will not find it again. The data can be - * changed but its length can never be altered unless you delete and - * re-insert it into the table. - * - * WARNING: The pointers to the key and data are not in any specific - * alignment. Accessing the key and/or data as an short, integer, or - * long pointer directly can cause problems. - * - * WARNING: Replacing a data cell (not inserting) will cause the table - * linked list to be temporarily invalid. Care must be taken with - * multiple threaded programs which are relying on the first/next - * linked list to be always valid. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer into which we will be inserting a - * new key/data pair. - * - * key_buf - Buffer of bytes of the key that we are inserting. If you - * are storing an (int) as the key (for example) then key_buf should - * be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are storing an (int) as the key (for example) then key_size should - * be sizeof(int). - * - * data_buf - Buffer of bytes of the data that we are inserting. If - * it is NULL then the library will allocate space for the data in the - * table without copying in any information. If data_buf is NULL and - * data_size is 0 then the library will associate a NULL data pointer - * with the key. If you are storing a (long) as the data (for - * example) then data_buf should be a (long *). - * - * data_size - Size of the data_buf buffer. If set to < 0 then the - * library will do a strlen of data_buf and add 1 for the '\0'. If - * you are storing an (long) as the key (for example) then key_size - * should be sizeof(long). - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the key storage that was allocated in the table. If you are - * storing an (int) as the key (for example) then key_buf_p should be - * (int **) i.e. the address of a (int *). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table. If you are - * storing an (long) as the data (for example) then data_buf_p should - * be (long **) i.e. the address of a (long *). - * - * overwrite - Flag which, if set to 1, will allow the overwriting of - * the data in the table with the new data if the key already exists - * in the table. - */ -int table_insert_kd(table_t *table_p, - const void *key_buf, const int key_size, - const void *data_buf, const int data_size, - void **key_buf_p, void **data_buf_p, - const char overwrite_b) -{ - int bucket; - unsigned int ksize, dsize, new_size, old_size, copy_size; - table_entry_t *entry_p, *last_p, *new_entry_p; - void *key_copy_p, *data_copy_p; - - /* check the arguments */ - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (key_buf == NULL) { - return TABLE_ERROR_ARG_NULL; - } - /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */ - if ((data_buf == NULL && data_size < 0) - || (data_buf != NULL && data_size == 0)) { - return TABLE_ERROR_SIZE; - } - -#ifndef NO_MMAP - /* no mmap support so immediate error */ - if (table_p->ta_mmap != NULL) { - return TABLE_ERROR_MMAP_OP; - } -#endif - - /* determine sizes of key and data */ - if (key_size < 0) { - ksize = strlen((char *)key_buf) + sizeof(char); - } - else { - ksize = key_size; - } - if (data_size < 0) { - dsize = strlen((char *)data_buf) + sizeof(char); - } - else { - dsize = data_size; - } - - /* get the bucket number via a hash function */ - bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; - - /* look for the entry in this bucket, only check keys of the same size */ - last_p = NULL; - for (entry_p = table_p->ta_buckets[bucket]; - entry_p != NULL; - last_p = entry_p, entry_p = entry_p->te_next_p) { - if (entry_p->te_key_size == ksize - && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) { - break; - } - } - - /* did we find it? then we are in replace mode. */ - if (entry_p != NULL) { - - /* can we not overwrite existing data? */ - if (! overwrite_b) { - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - return TABLE_ERROR_OVERWRITE; - } - - /* re-alloc entry's data if the new size != the old */ - if (dsize != entry_p->te_data_size) { - - /* - * First we delete it from the list to keep the list whole. - * This properly preserves the linked list in case we have a - * thread marching through the linked list while we are - * inserting. Maybe this is an unnecessary protection but it - * should not harm that much. - */ - if (last_p == NULL) { - table_p->ta_buckets[bucket] = entry_p->te_next_p; - } - else { - last_p->te_next_p = entry_p->te_next_p; - } - - /* - * Realloc the structure which may change its pointer. NOTE: - * this may change any previous data_key_p and data_copy_p - * pointers. - */ - new_size = entry_size(table_p, entry_p->te_key_size, dsize); - if (table_p->ta_resize_func == NULL) { - /* if the alloc function has not been overriden do realloc */ - if (table_p->ta_alloc_func == NULL) { - entry_p = (table_entry_t *)realloc(entry_p, new_size); - if (entry_p == NULL) { - return TABLE_ERROR_ALLOC; - } - } - else { - old_size = new_size - dsize + entry_p->te_data_size; - /* - * if the user did override alloc but not resize, assume - * that the user's allocation functions can't grok realloc - * and do it ourselves the hard way. - */ - new_entry_p = - (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, - new_size); - if (new_entry_p == NULL) { - return TABLE_ERROR_ALLOC; - } - if (new_size > old_size) { - copy_size = old_size; - } - else { - copy_size = new_size; - } - memcpy(new_entry_p, entry_p, copy_size); - if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, - old_size)) { - return TABLE_ERROR_FREE; - } - entry_p = new_entry_p; - } - } - else { - old_size = new_size - dsize + entry_p->te_data_size; - entry_p = (table_entry_t *) - table_p->ta_resize_func(table_p->ta_mem_pool, entry_p, - old_size, new_size); - if (entry_p == NULL) { - return TABLE_ERROR_ALLOC; - } - } - - /* add it back to the front of the list */ - entry_p->te_data_size = dsize; - entry_p->te_next_p = table_p->ta_buckets[bucket]; - table_p->ta_buckets[bucket] = entry_p; - } - - /* copy or replace data in storage */ - if (dsize > 0) { - if (table_p->ta_data_align == 0) { - data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - data_copy_p = entry_data_buf(table_p, entry_p); - } - if (data_buf != NULL) { - memcpy(data_copy_p, data_buf, dsize); - } - } - else { - data_copy_p = NULL; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(data_buf_p, data_copy_p); - - /* returning from the section where we were overwriting table data */ - return TABLE_ERROR_NONE; - } - - /* - * It is a new entry. - */ - - /* allocate a new entry */ - new_size = entry_size(table_p, ksize, dsize); - if (table_p->ta_alloc_func == NULL) { - entry_p = (table_entry_t *)malloc(new_size); - } - else { - entry_p = - (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, new_size); - } - if (entry_p == NULL) { - return TABLE_ERROR_ALLOC; - } - - /* copy key into storage */ - entry_p->te_key_size = ksize; - key_copy_p = ENTRY_KEY_BUF(entry_p); - memcpy(key_copy_p, key_buf, ksize); - - /* copy data in */ - entry_p->te_data_size = dsize; - if (dsize > 0) { - if (table_p->ta_data_align == 0) { - data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - data_copy_p = entry_data_buf(table_p, entry_p); - } - if (data_buf != NULL) { - memcpy(data_copy_p, data_buf, dsize); - } - } - else { - data_copy_p = NULL; - } - - SET_POINTER(key_buf_p, key_copy_p); - SET_POINTER(data_buf_p, data_copy_p); - - /* insert into list, no need to append */ - entry_p->te_next_p = table_p->ta_buckets[bucket]; - table_p->ta_buckets[bucket] = entry_p; - - table_p->ta_entry_n++; - - /* do we need auto-adjust? */ - if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST) - && SHOULD_TABLE_GROW(table_p)) { - return table_adjust(table_p, table_p->ta_entry_n); - } - - return TABLE_ERROR_NONE; -} - -/* - * int table_insert - * - * DESCRIPTION: - * - * Exactly the same as table_insert_kd except it does not pass back a - * pointer to the key after they have been inserted into the table - * structure. This is still here for backwards compatibility. - * - * See table_insert_kd for more information. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer into which we will be inserting a - * new key/data pair. - * - * key_buf - Buffer of bytes of the key that we are inserting. If you - * are storing an (int) as the key (for example) then key_buf should - * be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are storing an (int) as the key (for example) then key_size should - * be sizeof(int). - * - * data_buf - Buffer of bytes of the data that we are inserting. If - * it is NULL then the library will allocate space for the data in the - * table without copying in any information. If data_buf is NULL and - * data_size is 0 then the library will associate a NULL data pointer - * with the key. If you are storing a (long) as the data (for - * example) then data_buf should be a (long *). - * - * data_size - Size of the data_buf buffer. If set to < 0 then the - * library will do a strlen of data_buf and add 1 for the '\0'. If - * you are storing an (long) as the key (for example) then key_size - * should be sizeof(long). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table. If you are - * storing an (long) as the data (for example) then data_buf_p should - * be (long **) i.e. the address of a (long *). - * - * overwrite - Flag which, if set to 1, will allow the overwriting of - * the data in the table with the new data if the key already exists - * in the table. - */ -int table_insert(table_t *table_p, - const void *key_buf, const int key_size, - const void *data_buf, const int data_size, - void **data_buf_p, const char overwrite_b) -{ - return table_insert_kd(table_p, key_buf, key_size, data_buf, data_size, - NULL, data_buf_p, overwrite_b); -} - -/* - * int table_retrieve - * - * DESCRIPTION: - * - * This routine looks up a key made up of a buffer of bytes and an - * associated size in the table. If found then it returns the - * associated data information. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer into which we will be searching - * for the key. - * - * key_buf - Buffer of bytes of the key that we are searching for. If - * you are looking for an (int) as the key (for example) then key_buf - * should be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are looking for an (int) as the key (for example) then key_size - * should be sizeof(int). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table and that is - * associated with the key. If a (long) was stored as the data (for - * example) then data_buf_p should be (long **) i.e. the address of a - * (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data stored in the table that is associated with - * the key. - */ -int table_retrieve(table_t *table_p, - const void *key_buf, const int key_size, - void **data_buf_p, int *data_size_p) -{ - int bucket; - unsigned int ksize; - table_entry_t *entry_p, **buckets; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (key_buf == NULL) { - return TABLE_ERROR_ARG_NULL; - } - - /* find key size */ - if (key_size < 0) { - ksize = strlen((char *)key_buf) + sizeof(char); - } - else { - ksize = key_size; - } - - /* get the bucket number via a has function */ - bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; - - /* look for the entry in this bucket, only check keys of the same size */ - buckets = table_p->ta_buckets; - for (entry_p = buckets[bucket]; - entry_p != NULL; - entry_p = entry_p->te_next_p) { - entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p); - if (entry_p->te_key_size == ksize - && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) { - break; - } - } - - /* not found? */ - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * int table_delete - * - * DESCRIPTION: - * - * This routine looks up a key made up of a buffer of bytes and an - * associated size in the table. If found then it will be removed - * from the table. The associated data can be passed back to the user - * if requested. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * NOTE: this could be an allocation error if the library is to return - * the data to the user. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we will be deleteing - * the key. - * - * key_buf - Buffer of bytes of the key that we are searching for to - * delete. If you are deleting an (int) key (for example) then - * key_buf should be a (int *). - * - * key_size - Size of the key_buf buffer. If set to < 0 then the - * library will do a strlen of key_buf and add 1 for the '\0'. If you - * are deleting an (int) key (for example) then key_size should be - * sizeof(int). - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table and that was - * associated with the key. If a (long) was stored as the data (for - * example) then data_buf_p should be (long **) i.e. the address of a - * (long *). If a pointer is passed in, the caller is responsible for - * freeing it after use. If data_buf_p is NULL then the library will - * free up the data allocation itself. - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that was stored in the table and that was - * associated with the key. - */ -int table_delete(table_t *table_p, - const void *key_buf, const int key_size, - void **data_buf_p, int *data_size_p) -{ - int bucket; - unsigned int ksize; - unsigned char *data_copy_p; - table_entry_t *entry_p, *last_p; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (key_buf == NULL) { - return TABLE_ERROR_ARG_NULL; - } - -#ifndef NO_MMAP - /* no mmap support so immediate error */ - if (table_p->ta_mmap != NULL) { - return TABLE_ERROR_MMAP_OP; - } -#endif - - /* get the key size */ - if (key_size < 0) { - ksize = strlen((char *)key_buf) + sizeof(char); - } - else { - ksize = key_size; - } - - /* find our bucket */ - bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; - - /* look for the entry in this bucket, only check keys of the same size */ - for (last_p = NULL, entry_p = table_p->ta_buckets[bucket]; - entry_p != NULL; - last_p = entry_p, entry_p = entry_p->te_next_p) { - if (entry_p->te_key_size == ksize - && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) { - break; - } - } - - /* did we find it? */ - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - /* - * NOTE: we may want to adjust the linear counters here if the entry - * we are deleting is the one we are pointing on or is ahead of the - * one in the bucket list - */ - - /* remove entry from the linked list */ - if (last_p == NULL) { - table_p->ta_buckets[bucket] = entry_p->te_next_p; - } - else { - last_p->te_next_p = entry_p->te_next_p; - } - - /* free entry */ - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - /* - * if we were storing it compacted, we now need to malloc some - * space if the user wants the value after the delete. - */ - if (table_p->ta_alloc_func == NULL) { - *data_buf_p = malloc(entry_p->te_data_size); - } - else { - *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool, - entry_p->te_data_size); - } - if (*data_buf_p == NULL) { - return TABLE_ERROR_ALLOC; - } - if (table_p->ta_data_align == 0) { - data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - data_copy_p = entry_data_buf(table_p, entry_p); - } - memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size); - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - if (table_p->ta_free_func == NULL) { - free(entry_p); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, - entry_size(table_p, - entry_p->te_key_size, - entry_p->te_data_size))) { - return TABLE_ERROR_FREE; - } - - table_p->ta_entry_n--; - - /* do we need auto-adjust down? */ - if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST) - && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN) - && SHOULD_TABLE_SHRINK(table_p)) { - return table_adjust(table_p, table_p->ta_entry_n); - } - - return TABLE_ERROR_NONE; -} - -/* - * int table_delete_first - * - * DESCRIPTION: - * - * This is like the table_delete routines except it deletes the first - * key/data pair in the table instead of an entry corresponding to a - * particular key. The associated key and data information can be - * passed back to the user if requested. This routines is handy to - * clear out a table. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * NOTE: this could be an allocation error if the library is to return - * the data to the user. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we will be deleteing - * the first key. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the first key that was allocated in the table. - * If an (int) was stored as the first key (for example) then - * key_buf_p should be (int **) i.e. the address of a (int *). If a - * pointer is passed in, the caller is responsible for freeing it - * after use. If key_buf_p is NULL then the library will free up the - * key allocation itself. - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that was stored in the table and that was - * associated with the key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that was allocated in the table and that was - * associated with the key. If a (long) was stored as the data (for - * example) then data_buf_p should be (long **) i.e. the address of a - * (long *). If a pointer is passed in, the caller is responsible for - * freeing it after use. If data_buf_p is NULL then the library will - * free up the data allocation itself. - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that was stored in the table and that was - * associated with the key. - */ -int table_delete_first(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - unsigned char *data_copy_p; - table_entry_t *entry_p; - table_linear_t linear; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - -#ifndef NO_MMAP - /* no mmap support so immediate error */ - if (table_p->ta_mmap != NULL) { - return TABLE_ERROR_MMAP_OP; - } -#endif - - /* take the first entry */ - entry_p = first_entry(table_p, &linear); - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - /* - * NOTE: we may want to adjust the linear counters here if the entry - * we are deleting is the one we are pointing on or is ahead of the - * one in the bucket list - */ - - /* remove entry from the linked list */ - table_p->ta_buckets[linear.tl_bucket_c] = entry_p->te_next_p; - - /* free entry */ - if (key_buf_p != NULL) { - if (entry_p->te_key_size == 0) { - *key_buf_p = NULL; - } - else { - /* - * if we were storing it compacted, we now need to malloc some - * space if the user wants the value after the delete. - */ - if (table_p->ta_alloc_func == NULL) { - *key_buf_p = malloc(entry_p->te_key_size); - } - else { - *key_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool, - entry_p->te_key_size); - } - if (*key_buf_p == NULL) { - return TABLE_ERROR_ALLOC; - } - memcpy(*key_buf_p, ENTRY_KEY_BUF(entry_p), entry_p->te_key_size); - } - } - SET_POINTER(key_size_p, entry_p->te_key_size); - - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - /* - * if we were storing it compacted, we now need to malloc some - * space if the user wants the value after the delete. - */ - if (table_p->ta_alloc_func == NULL) { - *data_buf_p = malloc(entry_p->te_data_size); - } - else { - *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool, - entry_p->te_data_size); - } - if (*data_buf_p == NULL) { - return TABLE_ERROR_ALLOC; - } - if (table_p->ta_data_align == 0) { - data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - data_copy_p = entry_data_buf(table_p, entry_p); - } - memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size); - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - if (table_p->ta_free_func == NULL) { - free(entry_p); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, - entry_size(table_p, - entry_p->te_key_size, - entry_p->te_data_size))) { - return TABLE_ERROR_FREE; - } - - table_p->ta_entry_n--; - - /* do we need auto-adjust down? */ - if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST) - && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN) - && SHOULD_TABLE_SHRINK(table_p)) { - return table_adjust(table_p, table_p->ta_entry_n); - } - - return TABLE_ERROR_NONE; -} - -/* - * int table_info - * - * DESCRIPTION: - * - * Get some information about a table_p structure. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting - * information. - * - * num_buckets_p - Pointer to an integer which, if not NULL, will - * contain the number of buckets in the table. - * - * num_entries_p - Pointer to an integer which, if not NULL, will - * contain the number of entries stored in the table. - */ -int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p) -{ - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - - SET_POINTER(num_buckets_p, table_p->ta_bucket_n); - SET_POINTER(num_entries_p, table_p->ta_entry_n); - - return TABLE_ERROR_NONE; -} - -/* - * int table_adjust - * - * DESCRIPTION: - * - * Set the number of buckets in a table to a certain value. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer of which we are adjusting. - * - * bucket_n - Number buckets to adjust the table to. Set to 0 to - * adjust the table to its number of entries. - */ -int table_adjust(table_t *table_p, const int bucket_n) -{ - table_entry_t *entry_p, *next_p; - table_entry_t **buckets, **bucket_p, **bounds_p; - int bucket; - unsigned int buck_n, bucket_size; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - -#ifndef NO_MMAP - /* no mmap support so immediate error */ - if (table_p->ta_mmap != NULL) { - return TABLE_ERROR_MMAP_OP; - } -#endif - - /* - * NOTE: we walk through the entries and rehash them. If we stored - * the hash value as a full int in the table-entry, all we would - * have to do is remod it. - */ - - /* normalize to the number of entries */ - if (bucket_n == 0) { - buck_n = table_p->ta_entry_n; - } - else { - buck_n = bucket_n; - } - - /* we must have at least 1 bucket */ - if (buck_n == 0) { - buck_n = 1; - } - - (void)printf("growing table to %d\n", buck_n); - - /* make sure we have something to do */ - if (buck_n == table_p->ta_bucket_n) { - return TABLE_ERROR_NONE; - } - - /* allocate a new bucket list */ - bucket_size = buck_n * sizeof(table_entry_t *); - if (table_p->ta_alloc_func == NULL) { - buckets = (table_entry_t **)malloc(bucket_size); - } - else { - buckets = - (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool, - bucket_size); - } - if (buckets == NULL) { - return TABLE_ERROR_ALLOC; - } - /* - * We zero it ourselves to save the necessity of having a - * table_mem_calloc_t memory override function. - */ - memset(buckets, 0, bucket_size); - - /* - * run through each of the items in the current table and rehash - * them into the newest bucket sizes - */ - bounds_p = table_p->ta_buckets + table_p->ta_bucket_n; - for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) { - for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) { - - /* hash the old data into the new table size */ - bucket = hash(ENTRY_KEY_BUF(entry_p), entry_p->te_key_size, 0) % buck_n; - - /* record the next one now since we overwrite next below */ - next_p = entry_p->te_next_p; - - /* insert into new list, no need to append */ - entry_p->te_next_p = buckets[bucket]; - buckets[bucket] = entry_p; - - /* - * NOTE: we may want to adjust the bucket_c linear entry here to - * keep it current - */ - } - /* remove the old table pointers as we go by */ - *bucket_p = NULL; - } - - /* replace the table buckets with the new ones */ - if (table_p->ta_free_func == NULL) { - free(table_p->ta_buckets); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, - table_p->ta_buckets, - table_p->ta_bucket_n * - sizeof(table_entry_t *))) { - return TABLE_ERROR_FREE; - } - table_p->ta_buckets = buckets; - table_p->ta_bucket_n = buck_n; - - return TABLE_ERROR_NONE; -} - -/* - * int table_type_size - * - * DESCRIPTION: - * - * Return the size of the internal table type. - * - * RETURNS: - * - * The size of the table_t type. - * - * ARGUMENTS: - * - * None. - */ -int table_type_size(void) -{ - return sizeof(table_t); -} - -/************************* linear access routines ****************************/ - -/* - * int table_first - * - * DESCRIPTION: - * - * Find first element in a table and pass back information about the - * key/data pair. If any of the key/data pointers are NULL then they - * are ignored. - * - * NOTE: This function is not reentrant. More than one thread cannot - * be doing a first and next on the same table at the same time. Use - * the table_first_r version below for this. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * first element. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the first key that is allocated in the table. If - * an (int) is stored as the first key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the first key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the first key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the first key. - */ -int table_first(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - - /* initialize our linear magic number */ - table_p->ta_linear.tl_magic = LINEAR_MAGIC; - - entry_p = first_entry(table_p, &table_p->ta_linear); - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * int table_next - * - * DESCRIPTION: - * - * Find the next element in a table and pass back information about - * the key/data pair. If any of the key/data pointers are NULL then - * they are ignored. - * - * NOTE: This function is not reentrant. More than one thread cannot - * be doing a first and next on the same table at the same time. Use - * the table_next_r version below for this. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * next element. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the next key that is allocated in the table. If - * an (int) is stored as the next key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the next key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the next key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the next key. - */ -int table_next(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p; - int error; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) { - return TABLE_ERROR_LINEAR; - } - - /* move to the next entry */ - entry_p = next_entry(table_p, &table_p->ta_linear, &error); - if (entry_p == NULL) { - return error; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * int table_this - * - * DESCRIPTION: - * - * Find the current element in a table and pass back information about - * the key/data pair. If any of the key/data pointers are NULL then - * they are ignored. - * - * NOTE: This function is not reentrant. Use the table_current_r - * version below. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * current element. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the current key that is allocated in the table. - * If an (int) is stored as the current key (for example) then - * key_buf_p should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the current key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the current key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the current key. - */ -int table_this(table_t *table_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p = NULL; - int entry_c; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) { - return TABLE_ERROR_LINEAR; - } - - /* if we removed an item that shorted the bucket list, we may get this */ - if (table_p->ta_linear.tl_bucket_c >= table_p->ta_bucket_n) { - /* - * NOTE: this might happen if we delete an item which shortens the - * table bucket numbers. - */ - return TABLE_ERROR_NOT_FOUND; - } - - /* find the entry which is the nth in the list */ - entry_p = table_p->ta_buckets[table_p->ta_linear.tl_bucket_c]; - /* NOTE: we swap the order here to be more efficient */ - for (entry_c = table_p->ta_linear.tl_entry_c; entry_c > 0; entry_c--) { - /* did we reach the end of the list? */ - if (entry_p == NULL) { - break; - } - entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p; - } - - /* is this a NOT_FOUND or a LINEAR error */ - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * int table_first_r - * - * DESCRIPTION: - * - * Reetrant version of the table_first routine above. Find first - * element in a table and pass back information about the key/data - * pair. If any of the key/data pointers are NULL then they are - * ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * first element. - * - * linear_p - Pointer to a table linear structure which is initialized - * here. The same pointer should then be passed to table_next_r - * below. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the first key that is allocated in the table. If - * an (int) is stored as the first key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the first key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the first key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the first key. - */ -int table_first_r(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (linear_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - - /* initialize our linear magic number */ - linear_p->tl_magic = LINEAR_MAGIC; - - entry_p = first_entry(table_p, linear_p); - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * int table_next_r - * - * DESCRIPTION: - * - * Reetrant version of the table_next routine above. Find next - * element in a table and pass back information about the key/data - * pair. If any of the key/data pointers are NULL then they are - * ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * next element. - * - * linear_p - Pointer to a table linear structure which is incremented - * here. The same pointer must have been passed to table_first_r - * first so that it can be initialized. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the next key that is allocated in the table. If - * an (int) is stored as the next key (for example) then key_buf_p - * should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL will be set - * to the size of the key that is stored in the table and that is - * associated with the next key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the next key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the next key. - */ -int table_next_r(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p; - int error; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (linear_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (linear_p->tl_magic != LINEAR_MAGIC) { - return TABLE_ERROR_LINEAR; - } - - /* move to the next entry */ - entry_p = next_entry(table_p, linear_p, &error); - if (entry_p == NULL) { - return error; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * int table_this_r - * - * DESCRIPTION: - * - * Reetrant version of the table_this routine above. Find current - * element in a table and pass back information about the key/data - * pair. If any of the key/data pointers are NULL then they are - * ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * current element. - * - * linear_p - Pointer to a table linear structure which is accessed - * here. The same pointer must have been passed to table_first_r - * first so that it can be initialized. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of the current key that is allocated in the table. - * If an (int) is stored as the current key (for example) then - * key_buf_p should be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table and that is - * associated with the current key. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage that is allocated in the table and that is - * associated with the current key. If a (long) is stored as the data - * (for example) then data_buf_p should be (long **) i.e. the address - * of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table and that is - * associated with the current key. - */ -int table_this_r(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p; - int entry_c; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (linear_p->tl_magic != LINEAR_MAGIC) { - return TABLE_ERROR_LINEAR; - } - - /* if we removed an item that shorted the bucket list, we may get this */ - if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) { - /* - * NOTE: this might happen if we delete an item which shortens the - * table bucket numbers. - */ - return TABLE_ERROR_NOT_FOUND; - } - - /* find the entry which is the nth in the list */ - for (entry_c = linear_p->tl_entry_c, - entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; - entry_p != NULL && entry_c > 0; - entry_c--, entry_p = TABLE_POINTER(table_p, table_entry_t *, - entry_p)->te_next_p) { - } - - if (entry_p == NULL) { - return TABLE_ERROR_NOT_FOUND; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/******************************* mmap routines *******************************/ - -/* - * table_t *table_mmap - * - * DESCRIPTION: - * - * Mmap a table from a file that had been written to disk earlier via - * table_write. - * - * RETURNS: - * - * A pointer to the new table structure which must be passed to - * table_munmap to be deallocated. On error a NULL is returned. - * - * ARGUMENTS: - * - * path - Table file to mmap in. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ -table_t *table_mmap(const char *path, int *error_p) -{ -#ifdef NO_MMAP - - /* no mmap support so immediate error */ - SET_POINTER(error_p, TABLE_ERROR_MMAP_NONE); - return NULL; - -#else - - table_t *table_p; - struct stat sbuf; - int fd, state; - - table_p = (table_t *)malloc(sizeof(table_t)); - if (table_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - return NULL; - } - - /* open the mmap file */ - fd = open(path, O_RDONLY, 0); - if (fd < 0) { - free(table_p); - SET_POINTER(error_p, TABLE_ERROR_OPEN); - return NULL; - } - - /* get the file size */ - if (fstat(fd, &sbuf) != 0) { - free(table_p); - SET_POINTER(error_p, TABLE_ERROR_OPEN); - return NULL; - } - - /* mmap the space and close the file */ -#ifdef __alpha - state = (MAP_SHARED | MAP_FILE | MAP_VARIABLE); -#else - state = MAP_SHARED; -#endif - - table_p->ta_mmap = (table_t *)mmap((caddr_t)0, sbuf.st_size, PROT_READ, - state, fd, 0); - (void)close(fd); - - if (table_p->ta_mmap == (table_t *)MAP_FAILED) { - SET_POINTER(error_p, TABLE_ERROR_MMAP); - return NULL; - } - - /* is the mmap file contain bad info or maybe another system type? */ - if (table_p->ta_mmap->ta_magic != TABLE_MAGIC) { - SET_POINTER(error_p, TABLE_ERROR_PNT); - return NULL; - } - - /* sanity check on the file size */ - if (table_p->ta_mmap->ta_file_size != sbuf.st_size) { - SET_POINTER(error_p, TABLE_ERROR_SIZE); - return NULL; - } - - /* copy the fields out of the mmap file into our memory version */ - table_p->ta_magic = TABLE_MAGIC; - table_p->ta_flags = table_p->ta_mmap->ta_flags; - table_p->ta_bucket_n = table_p->ta_mmap->ta_bucket_n; - table_p->ta_entry_n = table_p->ta_mmap->ta_entry_n; - table_p->ta_data_align = table_p->ta_mmap->ta_data_align; - table_p->ta_buckets = TABLE_POINTER(table_p, table_entry_t **, - table_p->ta_mmap->ta_buckets); - table_p->ta_linear.tl_magic = 0; - table_p->ta_linear.tl_bucket_c = 0; - table_p->ta_linear.tl_entry_c = 0; - /* mmap is already set */ - table_p->ta_file_size = table_p->ta_mmap->ta_file_size; - - SET_POINTER(error_p, TABLE_ERROR_NONE); - return table_p; - -#endif -} - -/* - * int table_munmap - * - * DESCRIPTION: - * - * Unmmap a table that was previously mmapped using table_mmap. - * - * RETURNS: - * - * Returns table error codes. - * - * ARGUMENTS: - * - * table_p - Mmaped table pointer to unmap. - */ -int table_munmap(table_t *table_p) -{ -#ifdef NO_MMAP - - /* no mmap support so immediate error */ - return TABLE_ERROR_MMAP_NONE; - -#else - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (table_p->ta_mmap == NULL) { - return TABLE_ERROR_PNT; - } - - (void)munmap((caddr_t)table_p->ta_mmap, table_p->ta_file_size); - table_p->ta_magic = 0; - free(table_p); - return TABLE_ERROR_NONE; - -#endif -} - -/******************************* file routines *******************************/ - -/* - * int table_read - * - * DESCRIPTION: - * - * Read in a table from a file that had been written to disk earlier - * via table_write. - * - * RETURNS: - * - * Success - Pointer to the new table structure which must be passed - * to table_free to be deallocated. - * - * Failure - NULL - * - * ARGUMENTS: - * - * path - Table file to read in. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ -table_t *table_read(const char *path, int *error_p) -{ - unsigned int size; - int fd, ent_size; - FILE *infile; - table_entry_t entry, **bucket_p, *entry_p = NULL, *last_p; - unsigned long pos; - table_t *table_p; - - /* open the file */ - fd = open(path, O_RDONLY, 0); - if (fd < 0) { - SET_POINTER(error_p, TABLE_ERROR_OPEN); - return NULL; - } - - /* allocate a table structure */ - table_p = malloc(sizeof(table_t)); - if (table_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - return NULL; - } - - /* now open the fd to get buffered i/o */ - infile = fdopen(fd, "r"); - if (infile == NULL) { - SET_POINTER(error_p, TABLE_ERROR_OPEN); - return NULL; - } - - /* read the main table struct */ - if (fread(table_p, sizeof(table_t), 1, infile) != 1) { - SET_POINTER(error_p, TABLE_ERROR_READ); - free(table_p); - return NULL; - } - table_p->ta_file_size = 0; - - /* is the mmap file contain bad info or maybe another system type? */ - if (table_p->ta_magic != TABLE_MAGIC) { - SET_POINTER(error_p, TABLE_ERROR_PNT); - return NULL; - } - - /* allocate the buckets */ - table_p->ta_buckets = (table_entry_t **)calloc(table_p->ta_bucket_n, - sizeof(table_entry_t *)); - if (table_p->ta_buckets == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - free(table_p); - return NULL; - } - - if (fread(table_p->ta_buckets, sizeof(table_entry_t *), table_p->ta_bucket_n, - infile) != (size_t)table_p->ta_bucket_n) { - SET_POINTER(error_p, TABLE_ERROR_READ); - free(table_p->ta_buckets); - free(table_p); - return NULL; - } - - /* read in the entries */ - for (bucket_p = table_p->ta_buckets; - bucket_p < table_p->ta_buckets + table_p->ta_bucket_n; - bucket_p++) { - - /* skip null buckets */ - if (*bucket_p == NULL) { - continue; - } - - /* run through the entry list */ - last_p = NULL; - for (pos = *(unsigned long *)bucket_p;; - pos = (unsigned long)entry_p->te_next_p) { - - /* read in the entry */ - if (fseek(infile, pos, SEEK_SET) != 0) { - SET_POINTER(error_p, TABLE_ERROR_SEEK); - free(table_p->ta_buckets); - free(table_p); - if (entry_p != NULL) { - free(entry_p); - } - /* the other table elements will not be freed */ - return NULL; - } - if (fread(&entry, sizeof(struct table_shell_st), 1, infile) != 1) { - SET_POINTER(error_p, TABLE_ERROR_READ); - free(table_p->ta_buckets); - free(table_p); - if (entry_p != NULL) { - free(entry_p); - } - /* the other table elements will not be freed */ - return NULL; - } - - /* make a new entry */ - ent_size = entry_size(table_p, entry.te_key_size, entry.te_data_size); - entry_p = (table_entry_t *)malloc(ent_size); - if (entry_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - free(table_p->ta_buckets); - free(table_p); - /* the other table elements will not be freed */ - return NULL; - } - entry_p->te_key_size = entry.te_key_size; - entry_p->te_data_size = entry.te_data_size; - entry_p->te_next_p = entry.te_next_p; - - if (last_p == NULL) { - *bucket_p = entry_p; - } - else { - last_p->te_next_p = entry_p; - } - - /* determine how much more we have to read */ - size = ent_size - sizeof(struct table_shell_st); - if (fread(ENTRY_KEY_BUF(entry_p), sizeof(char), size, infile) != size) { - SET_POINTER(error_p, TABLE_ERROR_READ); - free(table_p->ta_buckets); - free(table_p); - free(entry_p); - /* the other table elements will not be freed */ - return NULL; - } - - /* we are done if the next pointer is null */ - if (entry_p->te_next_p == (unsigned long)0) { - break; - } - last_p = entry_p; - } - } - - (void)fclose(infile); - - SET_POINTER(error_p, TABLE_ERROR_NONE); - return table_p; -} - -/* - * int table_write - * - * DESCRIPTION: - * - * Write a table from memory to file. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to the table that we are writing to the file. - * - * path - Table file to write out to. - * - * mode - Mode of the file. This argument is passed on to open when - * the file is created. - */ -int table_write(const table_t *table_p, const char *path, const int mode) -{ - int fd, rem, ent_size; - unsigned int bucket_c, bucket_size; - unsigned long size; - table_entry_t *entry_p, **buckets, **bucket_p, *next_p; - table_t main_tab; - FILE *outfile; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - - fd = open(path, O_WRONLY | O_CREAT, mode); - if (fd < 0) { - return TABLE_ERROR_OPEN; - } - - outfile = fdopen(fd, "w"); - if (outfile == NULL) { - return TABLE_ERROR_OPEN; - } - - /* allocate a block of sizes for each bucket */ - bucket_size = sizeof(table_entry_t *) * table_p->ta_bucket_n; - if (table_p->ta_alloc_func == NULL) { - buckets = (table_entry_t **)malloc(bucket_size); - } - else { - buckets = - (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool, - bucket_size); - } - if (buckets == NULL) { - return TABLE_ERROR_ALLOC; - } - - /* make a copy of the main struct */ - main_tab = *table_p; - - /* start counting the bytes */ - size = 0; - size += sizeof(table_t); - - /* buckets go right after main struct */ - main_tab.ta_buckets = (table_entry_t **)size; - size += sizeof(table_entry_t *) * table_p->ta_bucket_n; - - /* run through and count the buckets */ - for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) { - bucket_p = table_p->ta_buckets + bucket_c; - if (*bucket_p == NULL) { - buckets[bucket_c] = NULL; - continue; - } - buckets[bucket_c] = (table_entry_t *)size; - for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) { - size += entry_size(table_p, entry_p->te_key_size, entry_p->te_data_size); - /* - * We now have to round the file to the nearest long so the - * mmaping of the longs in the entry structs will work. - */ - rem = size & (sizeof(long) - 1); - if (rem > 0) { - size += sizeof(long) - rem; - } - } - } - /* add a \0 at the end to fill the last section */ - size++; - - /* set the main fields */ - main_tab.ta_linear.tl_magic = 0; - main_tab.ta_linear.tl_bucket_c = 0; - main_tab.ta_linear.tl_entry_c = 0; - main_tab.ta_mmap = NULL; - main_tab.ta_file_size = size; - - /* - * Now we can start the writing because we got the bucket offsets. - */ - - /* write the main table struct */ - size = 0; - if (fwrite(&main_tab, sizeof(table_t), 1, outfile) != 1) { - if (table_p->ta_free_func == NULL) { - free(buckets); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size); - } - return TABLE_ERROR_WRITE; - } - size += sizeof(table_t); - if (fwrite(buckets, sizeof(table_entry_t *), table_p->ta_bucket_n, - outfile) != (size_t)table_p->ta_bucket_n) { - if (table_p->ta_free_func == NULL) { - free(buckets); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size); - } - return TABLE_ERROR_WRITE; - } - size += sizeof(table_entry_t *) * table_p->ta_bucket_n; - - /* write out the entries */ - for (bucket_p = table_p->ta_buckets; - bucket_p < table_p->ta_buckets + table_p->ta_bucket_n; - bucket_p++) { - for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) { - - ent_size = entry_size(table_p, entry_p->te_key_size, - entry_p->te_data_size); - size += ent_size; - /* round to nearest long here so we can write copy */ - rem = size & (sizeof(long) - 1); - if (rem > 0) { - size += sizeof(long) - rem; - } - next_p = entry_p->te_next_p; - if (next_p != NULL) { - entry_p->te_next_p = (table_entry_t *)size; - } - - /* now write to disk */ - if (fwrite(entry_p, ent_size, 1, outfile) != 1) { - if (table_p->ta_free_func == NULL) { - free(buckets); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, - bucket_size); - } - return TABLE_ERROR_WRITE; - } - - /* restore the next pointer */ - if (next_p != NULL) { - entry_p->te_next_p = next_p; - } - - /* now write the padding information */ - if (rem > 0) { - rem = sizeof(long) - rem; - /* - * NOTE: this won't leave fseek'd space at the end but we - * don't care there because there is no accessed memory - * afterwards. We write 1 \0 at the end to make sure. - */ - if (fseek(outfile, rem, SEEK_CUR) != 0) { - if (table_p->ta_free_func == NULL) { - free(buckets); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, - bucket_size); - } - return TABLE_ERROR_SEEK; - } - } - } - } - /* - * Write a \0 at the end of the file to make sure that the last - * fseek filled with nulls. - */ - (void)fputc('\0', outfile); - - (void)fclose(outfile); - if (table_p->ta_free_func == NULL) { - free(buckets); - } - else if (! table_p->ta_free_func(table_p->ta_mem_pool, buckets, - bucket_size)) { - return TABLE_ERROR_FREE; - } - - return TABLE_ERROR_NONE; -} - -/******************************** table order ********************************/ - -/* - * table_entry_t *table_order - * - * DESCRIPTION: - * - * Order a table by building an array of table entry pointers and then - * sorting this array using the qsort function. To retrieve the - * sorted entries, you can then use the table_entry routine to access - * each entry in order. - * - * NOTE: This routine is thread safe and makes use of an internal - * status qsort function. - * - * RETURNS: - * - * Success - An allocated list of table-linear structures which must - * be freed by table_order_free later. - * - * Failure - NULL - * - * ARGUMENTS: - * - * table_p - Pointer to the table that we are ordering. - * - * compare - Comparison function defined by the user. Its definition - * is at the top of the table.h file. If this is NULL then it will - * order the table my memcmp-ing the keys. - * - * num_entries_p - Pointer to an integer which, if not NULL, will - * contain the number of entries in the returned entry pointer array. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ -table_entry_t **table_order(table_t *table_p, table_compare_t compare, - int *num_entries_p, int *error_p) -{ - table_entry_t *entry_p, **entries, **entries_p; - table_linear_t linear; - compare_t comp_func; - unsigned int entries_size; - int ret; - - if (table_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ARG_NULL); - return NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - SET_POINTER(error_p, TABLE_ERROR_PNT); - return NULL; - } - - /* there must be at least 1 element in the table for this to work */ - if (table_p->ta_entry_n == 0) { - SET_POINTER(error_p, TABLE_ERROR_EMPTY); - return NULL; - } - - entries_size = table_p->ta_entry_n * sizeof(table_entry_t *); - if (table_p->ta_alloc_func == NULL) { - entries = (table_entry_t **)malloc(entries_size); - } - else { - entries = - (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool, - entries_size); - } - if (entries == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - return NULL; - } - - /* get a pointer to all entries */ - entry_p = first_entry(table_p, &linear); - if (entry_p == NULL) { - if (table_p->ta_free_func == NULL) { - free(entries); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size); - } - SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); - return NULL; - } - - /* add all of the entries to the array */ - for (entries_p = entries; - entry_p != NULL; - entry_p = next_entry(table_p, &linear, &ret)) { - *entries_p++ = entry_p; - } - - if (ret != TABLE_ERROR_NOT_FOUND) { - if (table_p->ta_free_func == NULL) { - free(entries); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size); - } - SET_POINTER(error_p, ret); - return NULL; - } - - if (compare == NULL) { - /* this is regardless of the alignment */ - comp_func = local_compare; - } - else if (table_p->ta_data_align == 0) { - comp_func = external_compare; - } - else { - comp_func = external_compare_align; - } - - /* now qsort the entire entries array from first to last element */ - ret = split((unsigned char *)entries, - (unsigned char *)(entries + table_p->ta_entry_n - 1), - sizeof(table_entry_t *), comp_func, compare, table_p); - if (ret != TABLE_ERROR_NONE) { - if (table_p->ta_free_func == NULL) { - free(entries); - } - else { - (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size); - } - SET_POINTER(error_p, ret); - return NULL; - } - - SET_POINTER(num_entries_p, table_p->ta_entry_n); - - SET_POINTER(error_p, TABLE_ERROR_NONE); - return entries; -} - -/* - * int table_order_free - * - * DESCRIPTION: - * - * Free the pointer returned by the table_order or table_order_pos - * routines. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to the table. - * - * table_entries - Allocated list of entry pointers returned by - * table_order. - * - * entry_n - Number of entries in the array as passed back by - * table_order or table_order_pos in num_entries_p. - */ -int table_order_free(table_t *table_p, table_entry_t **table_entries, - const int entry_n) -{ - int ret, final = TABLE_ERROR_NONE; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - - if (table_p->ta_free_func == NULL) { - free(table_entries); - } - else { - ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries, - sizeof(table_entry_t *) * entry_n); - if (ret != 1) { - final = TABLE_ERROR_FREE; - } - } - - return final; -} - -/* - * int table_entry - * - * DESCRIPTION: - * - * Get information about an element. The element is one from the - * array returned by the table_order function. If any of the key/data - * pointers are NULL then they are ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * element. - * - * entry_p - Pointer to a table entry from the array returned by the - * table_order function. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of this entry that is allocated in the table. If an - * (int) is stored as this entry (for example) then key_buf_p should - * be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage of this entry that is allocated in the table. - * If a (long) is stored as this entry data (for example) then - * data_buf_p should be (long **) i.e. the address of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table. - */ -int table_entry(table_t *table_p, table_entry_t *entry_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (entry_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - - SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); - SET_POINTER(key_size_p, entry_p->te_key_size); - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - SET_POINTER(data_size_p, entry_p->te_data_size); - - return TABLE_ERROR_NONE; -} - -/* - * table_linear_t *table_order_pos - * - * DESCRIPTION: - * - * Order a table by building an array of table linear structures and - * then sorting this array using the qsort function. To retrieve the - * sorted entries, you can then use the table_entry_pos routine to - * access each entry in order. - * - * NOTE: This routine is thread safe and makes use of an internal - * status qsort function. - * - * RETURNS: - * - * Success - An allocated list of table-linear structures which must - * be freed by table_order_pos_free later. - * - * Failure - NULL - * - * ARGUMENTS: - * - * table_p - Pointer to the table that we are ordering. - * - * compare - Comparison function defined by the user. Its definition - * is at the top of the table.h file. If this is NULL then it will - * order the table my memcmp-ing the keys. - * - * num_entries_p - Pointer to an integer which, if not NULL, will - * contain the number of entries in the returned entry pointer array. - * - * error_p - Pointer to an integer which, if not NULL, will contain a - * table error code. - */ -table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare, - int *num_entries_p, int *error_p) -{ - table_entry_t *entry_p; - table_linear_t linear, *linears, *linears_p; - compare_t comp_func; - int ret; - - if (table_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ARG_NULL); - return NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - SET_POINTER(error_p, TABLE_ERROR_PNT); - return NULL; - } - - /* there must be at least 1 element in the table for this to work */ - if (table_p->ta_entry_n == 0) { - SET_POINTER(error_p, TABLE_ERROR_EMPTY); - return NULL; - } - - if (table_p->ta_alloc_func == NULL) { - linears = (table_linear_t *)malloc(table_p->ta_entry_n * - sizeof(table_linear_t)); - } - else { - linears = - (table_linear_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, - table_p->ta_entry_n * - sizeof(table_linear_t)); - } - if (linears == NULL) { - SET_POINTER(error_p, TABLE_ERROR_ALLOC); - return NULL; - } - - /* get a pointer to all entries */ - entry_p = first_entry(table_p, &linear); - if (entry_p == NULL) { - SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); - return NULL; - } - - /* add all of the entries to the array */ - for (linears_p = linears; - entry_p != NULL; - entry_p = next_entry(table_p, &linear, &ret)) { - *linears_p++ = linear; - } - - if (ret != TABLE_ERROR_NOT_FOUND) { - SET_POINTER(error_p, ret); - return NULL; - } - - if (compare == NULL) { - /* this is regardless of the alignment */ - comp_func = local_compare_pos; - } - else if (table_p->ta_data_align == 0) { - comp_func = external_compare_pos; - } - else { - comp_func = external_compare_align_pos; - } - - /* now qsort the entire entries array from first to last element */ - split((unsigned char *)linears, - (unsigned char *)(linears + table_p->ta_entry_n - 1), - sizeof(table_linear_t), comp_func, compare, table_p); - - if (num_entries_p != NULL) { - *num_entries_p = table_p->ta_entry_n; - } - - SET_POINTER(error_p, TABLE_ERROR_NONE); - return linears; -} - -/* - * int table_order_pos_free - * - * DESCRIPTION: - * - * Free the pointer returned by the table_order or table_order_pos - * routines. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Pointer to the table. - * - * table_entries - Allocated list of entry pointers returned by - * table_order_pos. - * - * entry_n - Number of entries in the array as passed back by - * table_order or table_order_pos in num_entries_p. - */ -int table_order_pos_free(table_t *table_p, table_linear_t *table_entries, - const int entry_n) -{ - int ret, final = TABLE_ERROR_NONE; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - - if (table_p->ta_free_func == NULL) { - free(table_entries); - } - else { - ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries, - sizeof(table_linear_t) * entry_n); - if (ret != 1) { - final = TABLE_ERROR_FREE; - } - } - - return final; -} - -/* - * int table_entry_pos - * - * DESCRIPTION: - * - * Get information about an element. The element is one from the - * array returned by the table_order function. If any of the key/data - * pointers are NULL then they are ignored. - * - * RETURNS: - * - * Success - TABLE_ERROR_NONE - * - * Failure - Table error code. - * - * ARGUMENTS: - * - * table_p - Table structure pointer from which we are getting the - * element. - * - * linear_p - Pointer to a table linear structure from the array - * returned by the table_order function. - * - * key_buf_p - Pointer which, if not NULL, will be set to the address - * of the storage of this entry that is allocated in the table. If an - * (int) is stored as this entry (for example) then key_buf_p should - * be (int **) i.e. the address of a (int *). - * - * key_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the key that is stored in the table. - * - * data_buf_p - Pointer which, if not NULL, will be set to the address - * of the data storage of this entry that is allocated in the table. - * If a (long) is stored as this entry data (for example) then - * data_buf_p should be (long **) i.e. the address of a (long *). - * - * data_size_p - Pointer to an integer which, if not NULL, will be set - * to the size of the data that is stored in the table. - */ -int table_entry_pos(table_t *table_p, table_linear_t *linear_p, - void **key_buf_p, int *key_size_p, - void **data_buf_p, int *data_size_p) -{ - table_entry_t *entry_p; - int ret; - - if (table_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - if (table_p->ta_magic != TABLE_MAGIC) { - return TABLE_ERROR_PNT; - } - if (linear_p == NULL) { - return TABLE_ERROR_ARG_NULL; - } - - /* find the associated entry */ - entry_p = this_entry(table_p, linear_p, &ret); - if (entry_p == NULL) { - return ret; - } - - if (key_buf_p != NULL) { - *key_buf_p = ENTRY_KEY_BUF(entry_p); - } - if (key_size_p != NULL) { - *key_size_p = entry_p->te_key_size; - } - if (data_buf_p != NULL) { - if (entry_p->te_data_size == 0) { - *data_buf_p = NULL; - } - else { - if (table_p->ta_data_align == 0) { - *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); - } - else { - *data_buf_p = entry_data_buf(table_p, entry_p); - } - } - } - if (data_size_p != NULL) { - *data_size_p = entry_p->te_data_size; - } - - return TABLE_ERROR_NONE; -} - -/* - * const char *table_strerror - * - * DESCRIPTION: - * - * Return the corresponding string for the error number. - * - * RETURNS: - * - * Success - String equivalient of the error. - * - * Failure - String "invalid error code" - * - * ARGUMENTS: - * - * error - Error number that we are converting. - */ -const char *table_strerror(const int error) -{ - error_str_t *err_p; - - for (err_p = errors; err_p->es_error != 0; err_p++) { - if (err_p->es_error == error) { - return err_p->es_string; - } - } - - return INVALID_ERROR; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/table_util.c b/libs/libks/src/table_util.c deleted file mode 100644 index 8b8c20f0b7..0000000000 --- a/libs/libks/src/table_util.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Hash table utility program. - * - * Copyright 2000 by Gray Watson - * - * This file is part of the table package. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose and without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, - * and that the name of Gray Watson not be used in advertising or - * publicity pertaining to distribution of the document or software - * without specific, written prior permission. - * - * Gray Watson makes no representations about the suitability of the - * software described herein for any purpose. It is provided "as is" - * without express or implied warranty. - * - * The author may be reached via http://256.com/gray/ - * - * $Id: table_util.c,v 1.5 2000/03/09 03:30:42 gray Exp $ - */ - -#include -#include -#include - -#include "table.h" - -static char *rcs_id = - "$Id: table_util.c,v 1.5 2000/03/09 03:30:42 gray Exp $"; - -#define WRITE_MODE 0640 /* mode to write out table */ -#define SPECIAL_CHARS "e\033^^\"\"''\\\\n\nr\rt\tb\bf\fa\007" - -/* - * expand_chars - * - * DESCRIPTION: - * - * Copies a buffer into a output buffer while translates - * non-printables into %03o octal values. If it can, it will also - * translate certain \ characters (\r, \n, etc.) into \\%c. The - * routine is useful for printing out binary values. - * - * NOTE: It does _not_ add a \0 at the end of the output buffer. - * - * RETURNS: - * - * Returns the number of characters added to the output buffer. - * - * ARGUMENTS: - * - * buf - the buffer to convert. - * - * buf_size - size of the buffer. If < 0 then it will expand till it - * sees a \0 character. - * - * out - destination buffer for the convertion. - * - * out_size - size of the output buffer. - */ -int expand_chars(const void *buf, const int buf_size, - char *out, const int out_size) -{ - int buf_c; - const unsigned char *buf_p, *spec_p; - char *max_p, *out_p = out; - - /* setup our max pointer */ - max_p = out + out_size; - - /* run through the input buffer, counting the characters as we go */ - for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) { - - /* did we reach the end of the buffer? */ - if (buf_size < 0) { - if (*buf_p == '\0') { - break; - } - } - else { - if (buf_c >= buf_size) { - break; - } - } - - /* search for special characters */ - for (spec_p = (unsigned char *)SPECIAL_CHARS + 1; - *(spec_p - 1) != '\0'; - spec_p += 2) { - if (*spec_p == *buf_p) { - break; - } - } - - /* did we find one? */ - if (*(spec_p - 1) != '\0') { - if (out_p + 2 >= max_p) { - break; - } - (void)sprintf(out_p, "\\%c", *(spec_p - 1)); - out_p += 2; - continue; - } - - /* print out any 7-bit printable characters */ - if (*buf_p < 128 && isprint(*buf_p)) { - if (out_p + 1 >= max_p) { - break; - } - *out_p = *(char *)buf_p; - out_p += 1; - } - else { - if (out_p + 4 >= max_p) { - break; - } - (void)sprintf(out_p, "\\%03o", *buf_p); - out_p += 4; - } - } - - return out_p - out; -} - -/* - * dump_table - * - * DESCRIPTION: - * - * Dump a table file to the screen. - * - * RETURNS: - * - * None. - * - * ARGUMENTS: - * - * tab_p - a table pointer that we are dumping. - */ -static void dump_table(table_t *tab_p) -{ - char buf[10240]; - void *key_p, *data_p; - int ret, key_size, data_size, len, entry_c; - - for (ret = table_first(tab_p, (void **)&key_p, &key_size, - (void **)&data_p, &data_size), entry_c = 0; - ret == TABLE_ERROR_NONE; - ret = table_next(tab_p, (void **)&key_p, &key_size, - (void **)&data_p, &data_size), entry_c++) { - /* expand the key */ - len = expand_chars(key_p, key_size, buf, sizeof(buf)); - (void)printf("%d: key '%.*s' (%d), ", entry_c, len, buf, len); - /* now dump the data */ - len = expand_chars(data_p, data_size, buf, sizeof(buf)); - (void)printf("data '%.*s' (%d)\n", len, buf, len); - } -} - -/* - * usage - * - * DESCRIPTION: - * - * Print the usage message to stderr. - * - * RETURNS: - * - * None. - * - * ARGUMENTS: - * - * tab_p - a table pointer that we are dumping. - */ -static void usage(void) -{ - (void)fprintf(stderr, - "Usage: table_util\n" - " [-b number] or --buckets num buckets to adjust table\n" - " [-o file] or --out-file output filename\n" - " [-v] or --verbose verbose messages\n" - " file input table filename\n"); - exit(1); -} - -int main(int argc, char **argv) -{ - table_t *tab_p; - char do_write = 0, verbose = 0; - char *out_file = NULL, *in_file; - int ret, entry_n, bucket_n, num_buckets = 0; - - /* process the args */ - for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { - - switch (*(*argv + 1)) { - - case 'b': - argc--, argv++; - if (argc == 0) { - usage(); - } - num_buckets = atoi(*argv); - break; - - case 'o': - argc--, argv++; - if (argc == 0) { - usage(); - } - out_file = *argv; - break; - - case 'v': - verbose = 1; - break; - - default: - usage(); - break; - } - } - - if (argc != 1) { - usage(); - } - - /* take the last argument as the input file */ - in_file = *argv; - - /* read in the table from disk */ - tab_p = table_read(in_file, &ret); - if (tab_p == NULL) { - (void)fprintf(stderr, "table_util: unable to table_read from '%s': %s\n", - in_file, table_strerror(ret)); - exit(1); - } - - /* get info about the table */ - ret = table_info(tab_p, &bucket_n, &entry_n); - if (ret != TABLE_ERROR_NONE) { - (void)fprintf(stderr, - "table_util: unable to get info on table in '%s': %s\n", - in_file, table_strerror(ret)); - exit(1); - } - - (void)printf("Read table of %d buckets and %d entries from '%s'\n", - bucket_n, entry_n, in_file); - - if (verbose) { - dump_table(tab_p); - } - - if (num_buckets > 0) { - /* adjust the table's buckets */ - ret = table_adjust(tab_p, num_buckets); - if (ret != TABLE_ERROR_NONE) { - (void)fprintf(stderr, - "table_util: unable to adjust table to %d buckets: %s\n", - num_buckets, table_strerror(ret)); - exit(1); - } - do_write = 1; - } - - /* did we modify the table at all */ - if (do_write) { - if (out_file == NULL) { - out_file = in_file; - } - - /* write out our table */ - ret = table_write(tab_p, out_file, WRITE_MODE); - if (ret != TABLE_ERROR_NONE) { - (void)fprintf(stderr, "table_util: unable to write table to '%s': %s\n", - out_file, table_strerror(ret)); - exit(1); - } - - (void)printf("Wrote table to '%s'\n", out_file); - } - - /* free the table */ - ret = table_free(tab_p); - if (ret != TABLE_ERROR_NONE) { - (void)fprintf(stderr, "table_util: unable to free table: %s\n", - table_strerror(ret)); - /* NOTE: not a critical error */ - } - - exit(0); -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: - */ diff --git a/libs/libks/src/win/mman.c b/libs/libks/src/win/mman.c deleted file mode 100644 index b154317e98..0000000000 --- a/libs/libks/src/win/mman.c +++ /dev/null @@ -1,180 +0,0 @@ - -#include -#include -#include - -#include "mman.h" - -#ifndef FILE_MAP_EXECUTE -#define FILE_MAP_EXECUTE 0x0020 -#endif /* FILE_MAP_EXECUTE */ - -static int __map_mman_error(const DWORD err, const int deferr) -{ - if (err == 0) - return 0; - //TODO: implement - return err; -} - -static DWORD __map_mmap_prot_page(const int prot) -{ - DWORD protect = 0; - - if (prot == PROT_NONE) - return protect; - - if ((prot & PROT_EXEC) != 0) - { - protect = ((prot & PROT_WRITE) != 0) ? - PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; - } - else - { - protect = ((prot & PROT_WRITE) != 0) ? - PAGE_READWRITE : PAGE_READONLY; - } - - return protect; -} - -static DWORD __map_mmap_prot_file(const int prot) -{ - DWORD desiredAccess = 0; - - if (prot == PROT_NONE) - return desiredAccess; - - if ((prot & PROT_READ) != 0) - desiredAccess |= FILE_MAP_READ; - if ((prot & PROT_WRITE) != 0) - desiredAccess |= FILE_MAP_WRITE; - if ((prot & PROT_EXEC) != 0) - desiredAccess |= FILE_MAP_EXECUTE; - - return desiredAccess; -} - -void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) -{ - HANDLE fm, h; - - void * map = MAP_FAILED; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4293) -#endif - - const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ? - (DWORD)off : (DWORD)(off & 0xFFFFFFFFL); - const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ? - (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL); - const DWORD protect = __map_mmap_prot_page(prot); - const DWORD desiredAccess = __map_mmap_prot_file(prot); - - const off_t maxSize = off + (off_t)len; - - const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ? - (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL); - const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ? - (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL); - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - errno = 0; - - if (len == 0 - /* Unsupported flag combinations */ - || (flags & MAP_FIXED) != 0 - /* Usupported protection combinations */ - || prot == PROT_EXEC) - { - errno = EINVAL; - return MAP_FAILED; - } - - h = ((flags & MAP_ANONYMOUS) == 0) ? - (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE; - - if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE) - { - errno = EBADF; - return MAP_FAILED; - } - - fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL); - - if (fm == NULL) - { - errno = __map_mman_error(GetLastError(), EPERM); - return MAP_FAILED; - } - - map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len); - - CloseHandle(fm); - - if (map == NULL) - { - errno = __map_mman_error(GetLastError(), EPERM); - return MAP_FAILED; - } - - return map; -} - -int munmap(void *addr, size_t len) -{ - if (UnmapViewOfFile(addr)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int _mprotect(void *addr, size_t len, int prot) -{ - DWORD newProtect = __map_mmap_prot_page(prot); - DWORD oldProtect = 0; - - if (VirtualProtect(addr, len, newProtect, &oldProtect)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int msync(void *addr, size_t len, int flags) -{ - if (FlushViewOfFile(addr, len)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int mlock(const void *addr, size_t len) -{ - if (VirtualLock((LPVOID)addr, len)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int munlock(const void *addr, size_t len) -{ - if (VirtualUnlock((LPVOID)addr, len)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} diff --git a/libs/libks/src/win/sys/mman.h b/libs/libks/src/win/sys/mman.h deleted file mode 100644 index 7c1197b819..0000000000 --- a/libs/libks/src/win/sys/mman.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * sys/mman.h - * mman-win32 - */ - -#ifndef _SYS_MMAN_H_ -#define _SYS_MMAN_H_ - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -/* All the headers include this file. */ -#ifndef _MSC_VER -#include <_mingw.h> -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 - -#define MAP_FILE 0 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_TYPE 0xf -#define MAP_FIXED 0x10 -#define MAP_ANONYMOUS 0x20 -#define MAP_ANON MAP_ANONYMOUS - -#define MAP_FAILED ((void *)-1) - -/* Flags for msync. */ -#define MS_ASYNC 1 -#define MS_SYNC 2 -#define MS_INVALIDATE 4 - -void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); -int munmap(void *addr, size_t len); -int _mprotect(void *addr, size_t len, int prot); -int msync(void *addr, size_t len, int flags); -int mlock(const void *addr, size_t len); -int munlock(const void *addr, size_t len); - -#ifdef __cplusplus -}; -#endif - -#endif /* _SYS_MMAN_H_ */ diff --git a/libs/libks/test/testpools.c b/libs/libks/test/testpools.c deleted file mode 100644 index 48580a0525..0000000000 --- a/libs/libks/test/testpools.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include "mpool.h" -#include - -int main(int argc, char **argv) -{ - mpool_t *pool; - int err = 0; - char *str = NULL; - int x = 0; - int bytes = 1024; - - if (argc > 1) { - int tmp = atoi(argv[1]); - - if (tmp > 0) { - bytes = tmp; - } else { - fprintf(stderr, "INVALID\n"); - exit(255); - } - } - - pool = mpool_open(MPOOL_FLAG_ANONYMOUS, 0, NULL, &err); - - if (!pool || err != MPOOL_ERROR_NONE) { - fprintf(stderr, "ERR: %d [%s]\n", err, mpool_strerror(err)); - exit(255); - } - - str = mpool_alloc(pool, bytes, &err); - memset(str+x, '.', bytes -1); - *(str+(bytes-1)) = '\0'; - - printf("%s\n", str); - - //mpool_clear(pool); - err = mpool_close(pool); - - if (err != MPOOL_ERROR_NONE) { - fprintf(stderr, "ERR: [%s]\n", mpool_strerror(err)); - exit(255); - } - - exit(0); -} diff --git a/libs/libks/test/testpools/testpools.vcxproj b/libs/libks/test/testpools/testpools.vcxproj deleted file mode 100644 index 0313278219..0000000000 --- a/libs/libks/test/testpools/testpools.vcxproj +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F} - Win32Proj - testpools - 8.1 - - - - Application - true - v140 - Unicode - - - Application - false - v140 - true - Unicode - - - Application - true - v140 - Unicode - - - Application - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(ProjectDir)..\..\src\include - - - Console - true - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(ProjectDir)..\..\src\include - - - Console - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(ProjectDir)..\..\src\include - - - Console - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(ProjectDir)..\..\src\include - - - Console - true - true - true - - - - - - - - {70d178d8-1100-4152-86c0-809a91cff832} - - - - - - \ No newline at end of file diff --git a/libs/libks/test/testpools/testpools.vcxproj.filters b/libs/libks/test/testpools/testpools.vcxproj.filters deleted file mode 100644 index 85777cf3ad..0000000000 --- a/libs/libks/test/testpools/testpools.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file