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 <mij@bitchx.it>
-License: ISC
-
Files: libs/libtpl-1.5/src/tpl.[ch]
Copyright: 2005-2010, Troy D. Hanson
License: BSD-2-clause
+++ /dev/null
-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
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ImportGroup Label="PropertySheets" />
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup />
- <ItemDefinitionGroup>
- <ClCompile>
- <PreprocessorDefinitions>SIMCLIST_NO_DUMPRESTORE;_CRT_SECURE_NO_WARNINGS;KS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>$(ProjectDir)\src\include;$(ProjectDir)\src\win\sys;$(ProjectDir)\src\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <DisableSpecificWarnings>4574;4100;4127;4668;4255;4706;4710;4820</DisableSpecificWarnings>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemGroup />
-</Project>
\ No newline at end of file
+++ /dev/null
-
-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
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{70D178D8-1100-4152-86C0-809A91CFF832}</ProjectGuid>
- <Keyword>Win32Proj</Keyword>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="Shared">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="libks.props" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="libks.props" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="libks.props" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="libks.props" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <LinkIncremental>true</LinkIncremental>
- <IntDir>$(Platform)\$(Configuration)\</IntDir>
- <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <LinkIncremental>true</LinkIncremental>
- <IntDir>$(Platform)\$(Configuration)\</IntDir>
- <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <WarningLevel>EnableAllWarnings</WarningLevel>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <TargetMachine>MachineX86</TargetMachine>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <WarningLevel>EnableAllWarnings</WarningLevel>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <TargetMachine>MachineX86</TargetMachine>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <SubSystem>Windows</SubSystem>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <WarningLevel>EnableAllWarnings</WarningLevel>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBKS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <WarningLevel>EnableAllWarnings</WarningLevel>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="src\ks.c" />
- <ClCompile Include="src\ks_buffer.c" />
- <ClCompile Include="src\ks_config.c" />
- <ClCompile Include="src\ks_json.c" />
- <ClCompile Include="src\ks_threadmutex.c" />
- <ClCompile Include="src\mpool.c" />
- <ClCompile Include="src\simclist.c" />
- <ClCompile Include="src\table.c" />
- <ClCompile Include="src\table_util.c" />
- <ClCompile Include="src\win\mman.c" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\include\cc.h" />
- <ClInclude Include="src\include\ks.h" />
- <ClInclude Include="src\include\ks_buffer.h" />
- <ClInclude Include="src\include\ks_config.h" />
- <ClInclude Include="src\include\ks_json.h" />
- <ClInclude Include="src\include\ks_platform.h" />
- <ClInclude Include="src\include\ks_threadmutex.h" />
- <ClInclude Include="src\include\ks_types.h" />
- <ClInclude Include="src\include\mpool.h" />
- <ClInclude Include="src\include\mpool_loc.h" />
- <ClInclude Include="src\include\simclist.h" />
- <ClInclude Include="src\include\table.h" />
- <ClInclude Include="src\include\table_loc.h" />
- <ClInclude Include="src\win\mman.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="src\ks.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\ks_buffer.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\ks_config.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\ks_json.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\ks_threadmutex.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\mpool.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\simclist.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\table.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\table_util.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\win\mman.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\include\cc.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks_buffer.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks_config.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks_json.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks_threadmutex.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\mpool.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\mpool_loc.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\simclist.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\table.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\table_loc.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\win\mman.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks_types.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\include\ks_platform.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
-</Project>
\ No newline at end of file
+++ /dev/null
-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";
-
+++ /dev/null
-/*
- * 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 <stdarg.h>
-#include <ks_types.h>
-
-#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 <ks_threadmutex.h>
-#include <ks_buffer.h>
-
-#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:
- */
+++ /dev/null
-/*
- * 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:
- */
+++ /dev/null
-/*
- * 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
- *
- * <pre>
- *
- * EXAMPLE
- *
- * [category1]
- * var1 => val1
- * var2 => val2
- * \# lines that begin with \# are comments
- * \#var3 => val3
- * </pre>
- * @{
- */
-
-#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:
- */
+++ /dev/null
-/*
- 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
+++ /dev/null
-/*
- * 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 <stdarg.h>
-
-#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 <time.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef WIN32
-#include <sys/types.h>
-#include <sys/select.h>
-#include <netinet/tcp.h>
-#include <sys/signal.h>
-#include <unistd.h>
-#include <ctype.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#include <assert.h>
-
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-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 <stdint.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <stdarg.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#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:
- */
+++ /dev/null
-/*
- * 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:
- */
+++ /dev/null
-/*
- * 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 <stdarg.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* defined(__cplusplus) */
-
-#include <ks_platform.h>
-
-#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:
- */
-
+++ /dev/null
-/*
- * 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 <sys/types.h>
-
-/*
- * 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:
- */
+++ /dev/null
-/*
- * 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:
- */
+++ /dev/null
-/*
- * Copyright (c) 2007,2008 Mij <mij@bitchx.it>
- *
- * 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 <inttypes.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#ifndef SIMCLIST_NO_DUMPRESTORE
-# ifndef _WIN32
-# include <sys/time.h> /* list_dump_info_t's struct timeval */
-# else
-# include <time.h>
-# 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:
- */
+++ /dev/null
-/*
- * 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:
- */
+++ /dev/null
-/*
- * 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:
- */
-
+++ /dev/null
-/*
- * 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 <ks.h>
-#ifndef WIN32
-#define closesocket(x) shutdown(x, 2); close(x)
-#include <fcntl.h>
-#include <errno.h>
-#else
-#pragma warning (disable:6386)
-/* These warnings need to be ignored warning in sdk header */
-#include <Ws2tcpip.h>
-#include <windows.h>
-#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 <poll.h>
-#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;
-}
-
+++ /dev/null
-/*
- * 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:
- */
+++ /dev/null
-/*
- * 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:
- */
+++ /dev/null
-/*
- 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 <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-#include <float.h>
-#include <limits.h>
-#include <ctype.h>
-#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;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
- cJSON_free(entries);
- return 0;
- }
-
- /* Compose the output array. */
- *out='[';
- ptr=out+1;*ptr=0;
- for (i=0;i<numentries;i++)
- {
- strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
- if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
- cJSON_free(entries[i]);
- }
- cJSON_free(entries);
- *ptr++=']';*ptr++=0;
- return out;
-}
-
-/* Build an object from the text. */
-static const char *parse_object(cJSON *item,const char *value)
-{
- cJSON *child;
- if (*value!='{') {ep=value;return 0;} /* not an object! */
-
- item->type=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;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
- cJSON_free(names);cJSON_free(entries);
- return 0;
- }
-
- /* Compose the output: */
- *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
- for (i=0;i<numentries;i++)
- {
- if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
- strcpy(ptr,names[i]);ptr+=strlen(names[i]);
- *ptr++=':';if (fmt) *ptr++='\t';
- strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
- if (i!=numentries-1) *ptr++=',';
- if (fmt) *ptr++='\n';*ptr=0;
- cJSON_free(names[i]);cJSON_free(entries[i]);
- }
-
- cJSON_free(names);cJSON_free(entries);
- if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
- *ptr++='}';*ptr++=0;
- return out;
-}
-
-/* Get Array size/item / object item. */
-KS_DECLARE(int) cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;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 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=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 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=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 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=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 && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+++ /dev/null
-/*
- * 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 <process.h>
-
-#define KS_THREAD_CALLING_CONVENTION __stdcall
-
-struct ks_mutex {
- CRITICAL_SECTION mutex;
-};
-
-#else
-
-#include <pthread.h>
-
-#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:
- */
+++ /dev/null
-/*
- * 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 <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef _MSC_VER
-#include <io.h>
-#ifndef open
-#define open _open
-#endif
-#ifndef close
-#define close _close
-#endif
-#else
-#include <unistd.h>
-#endif
-#include <sys/mman.h>
-
-#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 <Windows.h>
-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:
- */
+++ /dev/null
-/*
- * Copyright (c) 2007,2008,2009,2010,2011 Mij <mij@bitchx.it>
- *
- * 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 <stdlib.h>
-#include <string.h>
-#include <errno.h> /* for setting errno */
-#include <sys/types.h>
-#ifndef _WIN32
-/* not in Windows! */
-# include <unistd.h>
-# include <stdint.h>
-#else
-#include <Windows.h>
-#endif
-#ifndef SIMCLIST_NO_DUMPRESTORE
-/* includes for dump/restore */
-# include <time.h>
-# include <sys/uio.h> /* for READ_ERRCHECK() and write() */
-# include <fcntl.h> /* for open() etc */
-# ifndef _WIN32
-# include <arpa/inet.h> /* for htons() on UNIX */
-# else
-# include <winsock2.h> /* for htons() on Windows */
-# endif
-#endif
-
-/* disable asserts */
-#ifndef SIMCLIST_DEBUG
-#define NDEBUG
-#endif
-
-#include <assert.h>
-
-
-#include <sys/stat.h> /* for open()'s access modes S_IRUSR etc */
-#include <limits.h>
-
-#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 <inttypes.h> /* (u)int*_t */
-#else
-# include <basetsd.h>
-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 <pthread.h>
-#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:
- */
+++ /dev/null
-/*
- * 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 <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(unix) || defined(__APPLE__)
-
-#include <unistd.h>
-
-#else
-
-#include <io.h>
-#include <malloc.h>
-#define NO_MMAP
-#ifndef open
-#define open _open
-#endif
-#ifndef fdopen
-#define fdopen _fdopen
-#endif
-#endif
-
-#ifndef NO_MMAP
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#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<N; ++i) h = hash( keys[i], len[i], h);
- */
-static unsigned int hash(const unsigned char *key,
- const unsigned int length,
- const unsigned int init_val)
-{
- const unsigned char *key_p = key;
- unsigned int a, b, c, len;
-
- /* set up the internal state */
- a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- b = 0x9e3779b9;
- c = init_val; /* the previous hash value */
-
- /* handle most of the key */
- for (len = length; len >= 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:
- */
+++ /dev/null
-/*
- * 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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#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:
- */
+++ /dev/null
-
-#include <windows.h>
-#include <errno.h>
-#include <io.h>
-
-#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;
-}
+++ /dev/null
-/*
- * 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 <sys/types.h>
-
-#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_ */
+++ /dev/null
-#include <stdlib.h>
-#include <stdio.h>
-#include "mpool.h"
-#include <string.h>
-
-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);
-}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{766F7FF4-CF39-4CDF-ABDC-4E9C88568F1F}</ProjectGuid>
- <Keyword>Win32Proj</Keyword>
- <RootNamespace>testpools</RootNamespace>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="Shared">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <LinkIncremental>true</LinkIncremental>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <LinkIncremental>true</LinkIncremental>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <LinkIncremental>false</LinkIncremental>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <LinkIncremental>false</LinkIncremental>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\include</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\include</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\include</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalIncludeDirectories>$(ProjectDir)..\..\src\include</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\testpools.c" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\libks.vcxproj">
- <Project>{70d178d8-1100-4152-86c0-809a91cff832}</Project>
- </ProjectReference>
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\testpools.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
-</Project>
\ No newline at end of file