├── .buzzy ├── links.yaml └── package.yaml ├── .gitignore ├── .travis.yml ├── .travis ├── install └── test ├── CMakeLists.txt ├── COPYING ├── INSTALL ├── README.markdown ├── cmake ├── FindCTargets.cmake ├── FindParseArguments.cmake └── FindPrereqs.cmake ├── docs ├── .gitattributes ├── CMakeLists.txt └── old │ ├── CMakeLists.txt │ ├── _static │ ├── .keep │ ├── docco-sphinx.css │ └── pygments.css │ ├── _templates │ └── .keep │ ├── allocation.rst │ ├── array.rst │ ├── attributes.rst │ ├── basic-types.rst │ ├── bitset.rst │ ├── buffer.rst │ ├── byte-order.rst │ ├── cli.rst │ ├── conf.py │ ├── config.rst │ ├── dllist.rst │ ├── ds.rst │ ├── errors.rst │ ├── files.rst │ ├── gc.rst │ ├── hash-table.rst │ ├── hash-values.rst │ ├── index.rst │ ├── int128.rst │ ├── managed-buffer.rst │ ├── mempool.rst │ ├── net-addresses.rst │ ├── process.rst │ ├── ring-buffer.rst │ ├── slice.rst │ ├── stream.rst │ ├── subprocess.rst │ ├── threads.rst │ ├── timestamps.rst │ ├── unique-ids.rst │ ├── versions.rst │ └── visibility.rst ├── extras └── hashstring.py ├── include ├── CMakeLists.txt └── libcork │ ├── cli.h │ ├── cli │ └── commands.h │ ├── config.h │ ├── config │ ├── arch.h │ ├── bsd.h │ ├── config.h │ ├── gcc.h │ ├── linux.h │ ├── macosx.h │ └── version.h.in │ ├── core.h │ ├── core │ ├── allocator.h │ ├── api.h │ ├── attributes.h │ ├── byte-order.h │ ├── callbacks.h │ ├── error.h │ ├── gc.h │ ├── hash.h │ ├── id.h │ ├── mempool.h │ ├── net-addresses.h │ ├── timestamp.h │ ├── types.h │ └── u128.h │ ├── ds.h │ ├── ds │ ├── array.h │ ├── bitset.h │ ├── buffer.h │ ├── dllist.h │ ├── hash-table.h │ ├── managed-buffer.h │ ├── ring-buffer.h │ ├── slice.h │ └── stream.h │ ├── helpers │ ├── errors.h │ ├── gc.h │ └── posix.h │ ├── os.h │ ├── os │ ├── files.h │ ├── process.h │ └── subprocess.h │ ├── threads.h │ └── threads │ ├── atomics.h │ └── basics.h ├── make-dist.sh ├── run.sh ├── share ├── CMakeLists.txt └── valgrind │ └── libcork.supp ├── src ├── APPNAME.pc.in ├── CMakeLists.txt ├── cork-hash │ └── cork-hash.c ├── cork-initializer │ ├── init1.c │ ├── init2.c │ └── main.c ├── cork-test │ └── cork-test.c ├── libcork.pc.in └── libcork │ ├── cli │ └── commands.c │ ├── core │ ├── allocator.c │ ├── error.c │ ├── gc.c │ ├── hash.c │ ├── ip-address.c │ ├── mempool.c │ ├── timestamp.c │ ├── u128.c │ └── version.c │ ├── ds │ ├── array.c │ ├── bitset.c │ ├── buffer.c │ ├── dllist.c │ ├── file-stream.c │ ├── hash-table.c │ ├── managed-buffer.c │ ├── ring-buffer.c │ └── slice.c │ ├── posix │ ├── directory-walker.c │ ├── env.c │ ├── exec.c │ ├── files.c │ ├── process.c │ └── subprocess.c │ └── pthreads │ └── thread.c ├── tests ├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── COPYING.cram.txt ├── ccram ├── cork-hash.t ├── cork-initializer.t ├── cork-test │ ├── cleanup.t │ ├── directory-watcher.t │ ├── help1-c1-s1.t │ ├── help1-c1-s2.t │ ├── help1-c1.t │ ├── help1-c2.t │ ├── help1-root.t │ ├── help2-c1-s1.t │ ├── help2-c1-s2.t │ ├── help2-c1.t │ ├── help2-c2.t │ ├── help2-root.t │ ├── help3-c1-s1.t │ ├── help3-c1-s2.t │ ├── help3-c1.t │ ├── help3-c2.t │ ├── help3-root.t │ ├── no-command-c1.t │ ├── no-command-root.t │ ├── run-c1-s1-f-t.t │ ├── run-c1-s1-f.t │ ├── run-c1-s1-t.t │ ├── run-c1-s1-test.t │ ├── run-c1-s1.t │ ├── run-c1-s2-f.t │ ├── run-c1-s2-file.t │ ├── run-c1-s2.t │ ├── run-c2.t │ ├── run-find-01.t │ ├── run-find-all-01.t │ ├── run-mkdir-01.t │ ├── run-paths-01.t │ ├── run-pwd-01.t │ ├── run-rm-01.t │ ├── run-sub-01.t │ ├── run-sub-02.t │ ├── run-sub-03.t │ ├── run-sub-04.t │ ├── run-sub-05.t │ └── run-sub-06.t ├── cram.py ├── helpers.h ├── test-array.c ├── test-bitset.c ├── test-buffer.c ├── test-core.c ├── test-dllist.c ├── test-files.c ├── test-gc.c ├── test-hash-table.c ├── test-input.txt ├── test-managed-buffer.c ├── test-mempool.c ├── test-ring-buffer.c ├── test-slice.c ├── test-subprocess.c ├── test-threads.c └── tile-test └── version.sh /.buzzy/links.yaml: -------------------------------------------------------------------------------- 1 | - git://github.com/redjack/buzzy-core.git 2 | - git://github.com/redjack/check.git 3 | -------------------------------------------------------------------------------- /.buzzy/package.yaml: -------------------------------------------------------------------------------- 1 | name: libcork 2 | build_dependencies: 3 | - pkg-config 4 | - check >= 0.9.4 5 | license: BSD 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /.build/ 3 | 4 | RELEASE-VERSION 5 | 6 | /libcork*.tar.gz 7 | /libcork*.tar.bz2 8 | 9 | *.[oa] 10 | *.os 11 | *.so 12 | *.dylib 13 | 14 | !.travis.yml 15 | !.travis/ 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - clang 4 | - gcc 5 | env: 6 | - ARCH=i386 ENABLE_SHARED_EXECUTABLES=YES 7 | - ARCH=amd64 ENABLE_SHARED_EXECUTABLES=YES 8 | - ARCH=i386 ENABLE_SHARED_EXECUTABLES=NO 9 | - ARCH=amd64 ENABLE_SHARED_EXECUTABLES=NO 10 | os: 11 | - linux 12 | - osx 13 | install: .travis/install 14 | script: .travis/test 15 | 16 | # In addition to pull requests, always build these branches 17 | branches: 18 | only: 19 | - master 20 | - develop 21 | -------------------------------------------------------------------------------- /.travis/install: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ "$TRAVIS_OS_NAME" = linux ]; then 6 | sudo apt-get update -qq 7 | 8 | if [ "$ARCH" = i386 ]; then 9 | sudo apt-get install gcc-multilib 10 | fi 11 | 12 | sudo apt-get install check:$ARCH 13 | else 14 | brew install --universal check 15 | fi 16 | -------------------------------------------------------------------------------- /.travis/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | mkdir .build 6 | cd .build 7 | 8 | if [ "$TRAVIS_OS_NAME" = linux ]; then 9 | if [ "$ARCH" = i386 ]; then 10 | ARCH_FLAGS="-m32" 11 | else 12 | ARCH_FLAGS="" 13 | fi 14 | elif [ "$TRAVIS_OS_NAME" = osx ]; then 15 | if [ "$ARCH" = i386 ]; then 16 | ARCH_FLAGS="-arch i386" 17 | else 18 | ARCH_FLAGS="-arch x86_64" 19 | fi 20 | fi 21 | 22 | cmake .. \ 23 | -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 24 | -DCMAKE_C_FLAGS_RELWITHDEBINFO="-g -O3 $ARCH_FLAGS" \ 25 | -DENABLE_SHARED_EXECUTABLES="${ENABLE_SHARED_EXECUTABLES}" 26 | make 27 | make test 28 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2015, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | cmake_minimum_required(VERSION 2.6) 10 | set(PROJECT_NAME libcork) 11 | set(RELEASE_DATE 2015-09-03) 12 | project(${PROJECT_NAME}) 13 | enable_testing() 14 | 15 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 16 | find_package(ParseArguments) 17 | find_package(Prereqs) 18 | find_package(CTargets) 19 | 20 | #----------------------------------------------------------------------- 21 | # Retrieve the current version number 22 | 23 | execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/version.sh 24 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 25 | RESULT_VARIABLE VERSION_RESULT 26 | OUTPUT_VARIABLE VERSION 27 | OUTPUT_STRIP_TRAILING_WHITESPACE) 28 | if(VERSION_RESULT) 29 | message(FATAL_ERROR 30 | "Cannot determine version number: " ${VERSION_RESULT}) 31 | endif(VERSION_RESULT) 32 | # This causes an annoying extra prompt in ccmake. 33 | # message("Current version: " ${VERSION}) 34 | 35 | string(REGEX REPLACE "-dev.*" "-dev" BASE_VERSION "${VERSION}") 36 | 37 | if(BASE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-dev)?$") 38 | set(VERSION_MAJOR "${CMAKE_MATCH_1}") 39 | set(VERSION_MINOR "${CMAKE_MATCH_2}") 40 | set(VERSION_PATCH "${CMAKE_MATCH_3}") 41 | else(BASE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-dev)?$") 42 | message(FATAL_ERROR "Invalid version number: ${VERSION}") 43 | endif(BASE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-dev)?$") 44 | 45 | execute_process( 46 | COMMAND git rev-parse HEAD 47 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 48 | RESULT_VARIABLE GIT_SHA1_RESULT 49 | OUTPUT_VARIABLE GIT_SHA1 50 | OUTPUT_STRIP_TRAILING_WHITESPACE 51 | ) 52 | if(GIT_SHA1_RESULT) 53 | message(FATAL_ERROR 54 | "Cannot determine git commit: " ${GIT_SHA1_RESULT}) 55 | endif(GIT_SHA1_RESULT) 56 | 57 | #----------------------------------------------------------------------- 58 | # Check for building on Tilera 59 | # If the Tilera environment is installed, then $TILERA_ROOT is defined 60 | # as the path to the active MDE. 61 | 62 | if(DEFINED ENV{TILERA_ROOT}) 63 | set(TILERA TRUE) 64 | set(TILERA_ROOT $ENV{TILERA_ROOT}) 65 | message("-- Configuring for Tilera MDE ${TILERA_ROOT}") 66 | set(ENV{PKG_CONFIG_PATH} 67 | "${TILERA_ROOT}/tile/usr/lib/pkgconfig:${TILERA_ROOT}/tile/usr/local/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}" 68 | ) 69 | set(CMAKE_SYSTEM_NAME "Tilera") 70 | set(CMAKE_SYSTEM_PROCESSOR "tilegx") 71 | set(CMAKE_C_COMPILER "${TILERA_ROOT}/bin/tile-gcc") 72 | set(CMAKE_LINKER "${TILERA_ROOT}/bin/tile-ld") 73 | set(TILERA_MONITOR "${TILERA_ROOT}/bin/tile-monitor") 74 | #add_definitions(-std=gnu99) 75 | set(CMAKE_FIND_ROOT_PATH "${TILERA_ROOT}/tile") 76 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) 77 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 78 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 79 | endif() 80 | 81 | #----------------------------------------------------------------------- 82 | # Set some options 83 | 84 | if(APPLE) 85 | if (NOT CMAKE_INSTALL_NAME_DIR) 86 | set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib") 87 | endif (NOT CMAKE_INSTALL_NAME_DIR) 88 | endif(APPLE) 89 | 90 | if(NOT CMAKE_BUILD_TYPE) 91 | set(CMAKE_BUILD_TYPE Release CACHE STRING 92 | "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." 93 | FORCE) 94 | endif(NOT CMAKE_BUILD_TYPE) 95 | 96 | set(ENABLE_SHARED YES CACHE BOOL "Whether to build a shared library") 97 | set(ENABLE_SHARED_EXECUTABLES NO CACHE BOOL 98 | "Whether to link executables using shared libraries") 99 | set(ENABLE_STATIC YES CACHE BOOL "Whether to build a static library") 100 | 101 | set(CMAKE_INSTALL_LIBDIR lib CACHE STRING 102 | "The base name of the installation directory for libraries") 103 | 104 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") 105 | add_definitions(-Wall -Werror) 106 | elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") 107 | add_definitions(-Wall -Werror) 108 | elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel") 109 | add_definitions(-Wall -Werror) 110 | endif(CMAKE_C_COMPILER_ID STREQUAL "GNU") 111 | 112 | include(GNUInstallDirs) 113 | 114 | #----------------------------------------------------------------------- 115 | # Check for prerequisite libraries 116 | 117 | find_package(Threads) 118 | set(THREADS_LDFLAGS "${CMAKE_THREAD_LIBS_INIT}") 119 | set(THREADS_STATIC_LDFLAGS "${CMAKE_THREAD_LIBS_INIT}") 120 | 121 | #----------------------------------------------------------------------- 122 | # Include our subdirectories 123 | 124 | add_subdirectory(include) 125 | add_subdirectory(share) 126 | add_subdirectory(src) 127 | add_subdirectory(tests) 128 | add_subdirectory(docs/old) 129 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright © 2011-2012, RedJack, LLC. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | • Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | • Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | • Neither the name of RedJack Software, LLC nor the names of its 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation instructions 2 | ========================= 3 | 4 | The libcork library is written in ANSI C. It uses cmake as its build 5 | manager. 6 | 7 | 8 | Prerequisite libraries 9 | ---------------------- 10 | 11 | To build libcork, you need the following libraries installed on your 12 | system: 13 | 14 | * pkg-config 15 | * check (http://check.sourceforge.net) 16 | 17 | 18 | Building from source 19 | -------------------- 20 | 21 | The libcork library uses cmake as its build manager. In most cases, you 22 | should be able to build the source code using the following: 23 | 24 | $ mkdir build 25 | $ cd build 26 | $ cmake .. -DCMAKE_INSTALL_PREFIX=$PREFIX 27 | $ make 28 | $ make test 29 | $ make install 30 | 31 | You might have to run the last command using sudo, if you need 32 | administrative privileges to write to the $PREFIX directory. 33 | 34 | 35 | Shared and static libraries 36 | --------------------------- 37 | 38 | You can use the `ENABLE_SHARED` and `ENABLE_STATIC` cmake options to control 39 | whether or not to install shared and static versions of libcork, respectively. 40 | By default, both are installed. 41 | 42 | You can use the `ENABLE_SHARED_EXECUTABLE` cmake option to control whether the 43 | programs that we install link with libcork's shared library or static library. 44 | (Note that this can override the value of `ENABLE_SHARED`; if you ask for the 45 | programs to link with the shared library, then we have to install that shared 46 | library for the programs to work properly.) By default, we link with libcork 47 | statically. 48 | 49 | So, as an example, if you wanted to only build and install the shared library, 50 | and to have our programs link with that shared library, you'd replace the cmake 51 | command with the following: 52 | 53 | $ cmake .. \ 54 | -DCMAKE_INSTALL_PREFIX=$PREFIX \ 55 | -DENABLE_SHARED=YES \ 56 | -DENABLE_STATIC=NO \ 57 | -DENABLE_SHARED_EXECUTABLES=YES 58 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # libcork 2 | 3 | [![Build Status](https://img.shields.io/travis/redjack/libcork/develop.svg)](https://travis-ci.org/redjack/libcork) 4 | 5 | So what is libcork, exactly? It's a “simple, easily embeddable, 6 | cross-platform C library”. It falls roughly into the same category as 7 | [glib](http://library.gnome.org/devel/glib/) or 8 | [APR](http://apr.apache.org/) in the C world; the STL, 9 | [POCO](http://pocoproject.org/), or [QtCore](http://qt.nokia.com/) 10 | in the C++ world; or the standard libraries of any decent dynamic 11 | language. 12 | 13 | So if libcork has all of these comparables, why a new library? Well, 14 | none of the C++ options are really applicable here. And none of the C 15 | options work, because one of the main goals is to have the library be 16 | highly modular, and useful in resource-constrained systems. Once we 17 | describe some of the design decisions that we've made in libcork, you'll 18 | hopefully see how this fits into an interesting niche of its own. 19 | 20 | ## Using libcork 21 | 22 | There are two primary ways to use libcork in your own software project: 23 | as a _shared library_, or _embedded_. 24 | 25 | When you use libcork as a shared library, you install it just like you 26 | would any other C library. We happen to use CMake as our build system, 27 | so you follow the usual CMake recipe to install the library. (See the 28 | [INSTALL](INSTALL) file for details.) All of the libcork code is 29 | contained within a single shared library (called libcork.so, 30 | libcork.dylib, or cork.dll, depending on the system). We also install a 31 | pkg-config file that makes it easy to add the appropriate compiler flags 32 | in your own build scripts. So, you use pkg-config to find libcork's 33 | include and library files, link with libcork, and you're good to go. 34 | 35 | The alternative is to embed libcork into your own software project's 36 | directory structure. In this case, your build scripts compile the 37 | libcork source along with the rest of your code. This has some 38 | advantages for resource-constrained systems, since (assuming your 39 | compiler and linker are any good), you only include the libcork routines 40 | that you actually use. And if your toolchain supports link-time 41 | optimization, the libcork routines can be optimized into the rest of 42 | your code. 43 | 44 | Which should you use? That's really up to you. Linking against the 45 | shared library adds a runtime dependency, but gives you the usual 46 | benefits of shared libraries: the library in memory is shared across 47 | each program that uses it; you can install a single bug-fix update and 48 | all libcork programs automatically take advantage of the new release; 49 | etc. The embedding option is great if you really need to make your 50 | library as small as possible, or if you don't want to add that runtime 51 | dependency. 52 | 53 | ## Design decisions 54 | 55 | Note that having libcork be **easily** embeddable has some ramifications 56 | on the library's design. In particular, we don't want to make any 57 | assumptions about which build system you're embedding libcork into. We 58 | happen to use CMake, but you might be using autotools, waf, scons, or 59 | any number of others. Most cross-platform libraries follow the 60 | autotools model of performing some checks at compile time (maybe during 61 | a separate “configure” phase, maybe not) to choose the right API 62 | implementation for the current platform. Since we can't assume a build 63 | system, we have to take a different approach, and do as many checks as 64 | we can using the C preprocessor. Any check that we can't make in the 65 | preprocessor has to be driven by a C preprocessor macro definition, 66 | which you (the libcork user) are responsible for checking for and 67 | defining. So we need to have as few of those as possible. 68 | -------------------------------------------------------------------------------- /cmake/FindParseArguments.cmake: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2015, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | 10 | # CMake 2.8.4 and higher gives us cmake_parse_arguments out of the box. For 11 | # earlier versions (RHEL5!) we have to define it ourselves. (The definition 12 | # comes from .) 13 | 14 | if (CMAKE_VERSION VERSION_LESS "2.8.4") 15 | 16 | MACRO(CMAKE_PARSE_ARGUMENTS prefix arg_names option_names) 17 | SET(DEFAULT_ARGS) 18 | FOREACH(arg_name ${arg_names}) 19 | SET(${prefix}_${arg_name}) 20 | ENDFOREACH(arg_name) 21 | FOREACH(option ${option_names}) 22 | SET(${prefix}_${option} FALSE) 23 | ENDFOREACH(option) 24 | 25 | SET(current_arg_name DEFAULT_ARGS) 26 | SET(current_arg_list) 27 | FOREACH(arg ${ARGN}) 28 | SET(larg_names ${arg_names}) 29 | LIST(FIND larg_names "${arg}" is_arg_name) 30 | IF (is_arg_name GREATER -1) 31 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 32 | SET(current_arg_name ${arg}) 33 | SET(current_arg_list) 34 | ELSE (is_arg_name GREATER -1) 35 | SET(loption_names ${option_names}) 36 | LIST(FIND loption_names "${arg}" is_option) 37 | IF (is_option GREATER -1) 38 | SET(${prefix}_${arg} TRUE) 39 | ELSE (is_option GREATER -1) 40 | SET(current_arg_list ${current_arg_list} ${arg}) 41 | ENDIF (is_option GREATER -1) 42 | ENDIF (is_arg_name GREATER -1) 43 | ENDFOREACH(arg) 44 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 45 | ENDMACRO(CMAKE_PARSE_ARGUMENTS) 46 | 47 | else (CMAKE_VERSION VERSION_LESS "2.8.4") 48 | 49 | include(CMakeParseArguments) 50 | 51 | endif (CMAKE_VERSION VERSION_LESS "2.8.4") 52 | -------------------------------------------------------------------------------- /cmake/FindPrereqs.cmake: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2015, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | 10 | #----------------------------------------------------------------------- 11 | # Configuration options that control all of the below 12 | 13 | set(PKG_CONFIG_PATH CACHE STRING "pkg-config search path") 14 | if (PKG_CONFIG_PATH) 15 | set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:$ENV{PKG_CONFIG_PATH}") 16 | endif (PKG_CONFIG_PATH) 17 | 18 | 19 | #----------------------------------------------------------------------- 20 | # pkg-config prerequisites 21 | 22 | find_package(PkgConfig) 23 | 24 | function(pkgconfig_prereq DEP) 25 | set(options OPTIONAL) 26 | set(one_args) 27 | set(multi_args) 28 | cmake_parse_arguments(_ "${options}" "${one_args}" "${multi_args}" ${ARGN}) 29 | 30 | string(REGEX REPLACE "[<>=].*" "" SHORT_NAME "${DEP}") 31 | string(REPLACE "-" "_" SHORT_NAME "${SHORT_NAME}") 32 | string(TOUPPER ${SHORT_NAME} UPPER_SHORT_NAME) 33 | string(TOLOWER ${SHORT_NAME} LOWER_SHORT_NAME) 34 | 35 | set(USE_CUSTOM_${UPPER_SHORT_NAME} NO CACHE BOOL 36 | "Whether you want to provide custom details for ${LOWER_SHORT_NAME}") 37 | 38 | if (NOT USE_CUSTOM_${UPPER_SHORT_NAME}) 39 | set(PKG_CHECK_ARGS) 40 | if (NOT __OPTIONAL) 41 | list(APPEND PKG_CHECK_ARGS REQUIRED) 42 | endif (NOT __OPTIONAL) 43 | list(APPEND PKG_CHECK_ARGS ${DEP}) 44 | 45 | pkg_check_modules(${UPPER_SHORT_NAME} ${PKG_CHECK_ARGS}) 46 | endif (NOT USE_CUSTOM_${UPPER_SHORT_NAME}) 47 | 48 | include_directories(${${UPPER_SHORT_NAME}_INCLUDE_DIRS}) 49 | link_directories(${${UPPER_SHORT_NAME}_LIBRARY_DIRS}) 50 | endfunction(pkgconfig_prereq) 51 | 52 | 53 | #----------------------------------------------------------------------- 54 | # find_library prerequisites 55 | 56 | function(library_prereq LIB_NAME) 57 | set(options OPTIONAL) 58 | set(one_args) 59 | set(multi_args) 60 | cmake_parse_arguments(_ "${options}" "${one_args}" "${multi_args}" ${ARGN}) 61 | 62 | string(REPLACE "-" "_" SHORT_NAME "${LIB_NAME}") 63 | string(TOUPPER ${SHORT_NAME} UPPER_SHORT_NAME) 64 | string(TOLOWER ${SHORT_NAME} LOWER_SHORT_NAME) 65 | 66 | set(USE_CUSTOM_${UPPER_SHORT_NAME} NO CACHE BOOL 67 | "Whether you want to provide custom details for ${LOWER_SHORT_NAME}") 68 | 69 | if (USE_CUSTOM_${UPPER_SHORT_NAME}) 70 | include_directories(${${UPPER_SHORT_NAME}_INCLUDE_DIRS}) 71 | link_directories(${${UPPER_SHORT_NAME}_LIBRARY_DIRS}) 72 | else (USE_CUSTOM_${UPPER_SHORT_NAME}) 73 | find_library(${UPPER_SHORT_NAME}_LIBRARIES ${LIB_NAME}) 74 | endif (USE_CUSTOM_${UPPER_SHORT_NAME}) 75 | 76 | endfunction(library_prereq) 77 | -------------------------------------------------------------------------------- /docs/.gitattributes: -------------------------------------------------------------------------------- 1 | *.graffle -diff -whitespace 2 | /*.[1-9] -diff -whitespace 3 | -------------------------------------------------------------------------------- /docs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2014, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | # Fill in this with the text that you want to include in the header and footer 10 | # of each man page. 11 | 12 | set(MAN_HEADER "${PROJECT_NAME} documentation") 13 | set(MAN_FOOTER "${PROJECT_NAME}") 14 | 15 | # Fill this in with any man pages that should be built from a pandoc source 16 | # file. For a man page called foo.5, there should be a pandoc source file 17 | # called foo.5.pandoc. 18 | 19 | set(MAN_PAGES 20 | ) 21 | 22 | #----------------------------------------------------------------------- 23 | # Everything below is boilerplate! 24 | 25 | find_program( 26 | PANDOC_EXECUTABLE 27 | NAMES pandoc 28 | HINTS ENV PANDOC_DIR 29 | PATH_SUFFIXES bin 30 | DOC "Pandoc man page generator" 31 | ) 32 | 33 | set(GENERATE_DOC TRUE CACHE BOOL 34 | "Whether to rebuild documentation") 35 | 36 | if (NOT PANDOC_EXECUTABLE) 37 | message(WARNING "Unable to find pandoc documentation generator") 38 | set(GENERATE_DOC FALSE) 39 | endif (NOT PANDOC_EXECUTABLE) 40 | 41 | 42 | # Link man pages go in docs/links 43 | 44 | macro(install_links section) 45 | file(GLOB links "links/*.${section}") 46 | if (links) 47 | install( 48 | FILES ${links} 49 | DESTINATION "share/man/man${section}" 50 | ) 51 | endif (links) 52 | endmacro(install_links section) 53 | 54 | install_links(1) # commands 55 | install_links(3) # library API 56 | install_links(4) # special files and drivers 57 | install_links(5) # file formats and conventions 58 | install_links(7) # miscellaneous 59 | install_links(8) # system commands 60 | 61 | 62 | # Man pages with actual content go in docs 63 | 64 | set(ALL_MANS) 65 | 66 | macro(pandocify name) 67 | set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}.pandoc") 68 | set(dest "${CMAKE_CURRENT_SOURCE_DIR}/${name}") 69 | get_filename_component(section "${name}" EXT) 70 | string(REPLACE "." "" section "${section}") 71 | 72 | # Only compile the markdown source into groff man pages if requested. 73 | if (GENERATE_DOC) 74 | add_custom_command( 75 | OUTPUT ${dest} 76 | COMMAND ${PANDOC_EXECUTABLE} 77 | -f markdown -t man -s --smart 78 | -V header="${MAN_HEADER}" 79 | -V footer="${MAN_FOOTER}" 80 | -V date=${RELEASE_DATE} 81 | -o ${dest} ${src} 82 | MAIN_DEPENDENCY ${src} 83 | COMMENT "Building ${name}" 84 | ) 85 | list(APPEND ALL_MANS ${dest}) 86 | endif (GENERATE_DOC) 87 | 88 | # We should always have an already-compiled copy of each man page in the 89 | # source tree, which we can install even if we didn't build fresh new 90 | # copies. 91 | install( 92 | FILES ${dest} 93 | DESTINATION "share/man/man${section}" 94 | ) 95 | endmacro(pandocify) 96 | 97 | foreach(MAN_PAGE ${MAN_PAGES}) 98 | pandocify(${MAN_PAGE}) 99 | endforeach(MAN_PAGE) 100 | 101 | add_custom_target(doc ALL DEPENDS ${ALL_MANS}) 102 | -------------------------------------------------------------------------------- /docs/old/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2014, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | find_program( 10 | SPHINX_EXECUTABLE 11 | NAMES sphinx-build 12 | HINTS ENV SPHINX_DIR 13 | PATH_SUFFIXES bin 14 | DOC "Sphinx documentation generator" 15 | ) 16 | 17 | set(GENERATE_DOC TRUE) 18 | 19 | if (TILERA) 20 | message(STATUS "Note: We don't build documentation on the Tilera platform") 21 | set(GENERATE_DOC FALSE) 22 | endif (TILERA) 23 | 24 | if (NOT SPHINX_EXECUTABLE) 25 | message(WARNING "Unable to find Sphinx documentation generator") 26 | set(GENERATE_DOC FALSE) 27 | endif (NOT SPHINX_EXECUTABLE) 28 | 29 | set(INTERSPHINX_OVERRIDES "") 30 | 31 | macro(find_prereq_doc LIB_NAME) 32 | execute_process( 33 | COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=sphinxdir ${LIB_NAME} 34 | OUTPUT_VARIABLE LIB_SPHINX_DIR 35 | OUTPUT_STRIP_TRAILING_WHITESPACE 36 | ) 37 | 38 | if (LIB_SPHINX_DIR) 39 | message(STATUS "Using ${LIB_NAME} docs in ${LIB_SPHINX_DIR}") 40 | set( 41 | INTERSPHINX_OVERRIDES 42 | "${INTERSPHINX_OVERRIDES}\nintersphinx_mapping['${LIB_NAME}'] = ('${LIB_SPHINX_DIR}', None)" 43 | ) 44 | endif (LIB_SPHINX_DIR) 45 | endmacro(find_prereq_doc) 46 | 47 | if (GENERATE_DOC) 48 | set(SPHINX_SRC_CONF_FILE "${CMAKE_CURRENT_SOURCE_DIR}/conf.py") 49 | set(SPHINX_CONF_FILE "${CMAKE_CURRENT_BINARY_DIR}/conf.py") 50 | set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees") 51 | set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html") 52 | 53 | # If your Sphinx documentation references the Sphinx documentation of 54 | # any of your prerequisite libraries, add some calls to 55 | # find_prereq_doc here: 56 | # 57 | # find_prereq_doc(libcork) 58 | 59 | set( 60 | VERSION_FOR_CONF_PY 61 | "\nrelease=\"${VERSION}\"\nversion=\"${BASE_VERSION}\"" 62 | ) 63 | configure_file(${SPHINX_SRC_CONF_FILE} ${SPHINX_CONF_FILE} @ONLY) 64 | file(COPY _static DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 65 | file(COPY _templates DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 66 | 67 | add_custom_target(old-doc ALL 68 | ${SPHINX_EXECUTABLE} 69 | -b html 70 | -d "${SPHINX_CACHE_DIR}" 71 | -c "${CMAKE_CURRENT_BINARY_DIR}" 72 | "${CMAKE_CURRENT_SOURCE_DIR}" 73 | "${SPHINX_HTML_DIR}" 74 | COMMENT "Building HTML documentation with Sphinx" 75 | ) 76 | 77 | list(APPEND CLEAN_FILES "${SPHINX_CACHE_DIR}" "${SPHINX_HTML_DIR}") 78 | set_directory_properties( 79 | PROPERTIES 80 | ADDITIONAL_MAKE_CLEAN_FILES "${CLEAN_FILES}" 81 | ) 82 | 83 | install( 84 | DIRECTORY "${SPHINX_HTML_DIR}" 85 | DESTINATION "share/doc/${PROJECT_NAME}" 86 | ) 87 | endif (GENERATE_DOC) 88 | -------------------------------------------------------------------------------- /docs/old/_static/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadowsocks/libcork/0231641bca541e80e82519b7a2933cfed02023c9/docs/old/_static/.keep -------------------------------------------------------------------------------- /docs/old/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight .c { color: #408080; font-style: italic } /* Comment */ 3 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 4 | .highlight .k { color: #954121 } /* Keyword */ 5 | .highlight .o { color: #666666 } /* Operator */ 6 | .highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #BC7A00 } /* Comment.Preproc */ 8 | .highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ 10 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 11 | .highlight .ge { font-style: italic } /* Generic.Emph */ 12 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 13 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 14 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 15 | .highlight .go { color: #808080 } /* Generic.Output */ 16 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 17 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 18 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 19 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */ 20 | .highlight .kc { color: #954121 } /* Keyword.Constant */ 21 | .highlight .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ 22 | .highlight .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ 23 | .highlight .kp { color: #954121 } /* Keyword.Pseudo */ 24 | .highlight .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ 25 | .highlight .kt { color: #B00040 } /* Keyword.Type */ 26 | .highlight .m { color: #666666 } /* Literal.Number */ 27 | .highlight .s { color: #219161 } /* Literal.String */ 28 | .highlight .na { color: #7D9029 } /* Name.Attribute */ 29 | .highlight .nb { color: #954121 } /* Name.Builtin */ 30 | .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 31 | .highlight .no { color: #880000 } /* Name.Constant */ 32 | .highlight .nd { color: #AA22FF } /* Name.Decorator */ 33 | .highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ 34 | .highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 35 | .highlight .nf { color: #0000FF } /* Name.Function */ 36 | .highlight .nl { color: #A0A000 } /* Name.Label */ 37 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 38 | .highlight .nt { color: #954121; font-weight: bold } /* Name.Tag */ 39 | .highlight .nv { color: #19469D } /* Name.Variable */ 40 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #666666 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #219161 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #219161 } /* Literal.String.Char */ 48 | .highlight .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #219161 } /* Literal.String.Double */ 50 | .highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 51 | .highlight .sh { color: #219161 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #954121 } /* Literal.String.Other */ 54 | .highlight .sr { color: #BB6688 } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #219161 } /* Literal.String.Single */ 56 | .highlight .ss { color: #19469D } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #954121 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #19469D } /* Name.Variable.Class */ 59 | .highlight .vg { color: #19469D } /* Name.Variable.Global */ 60 | .highlight .vi { color: #19469D } /* Name.Variable.Instance */ 61 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ 62 | -------------------------------------------------------------------------------- /docs/old/_templates/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shadowsocks/libcork/0231641bca541e80e82519b7a2933cfed02023c9/docs/old/_templates/.keep -------------------------------------------------------------------------------- /docs/old/attributes.rst: -------------------------------------------------------------------------------- 1 | .. _attributes: 2 | 3 | ******************* 4 | Compiler attributes 5 | ******************* 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | The macros in this section define compiler-agnostic versions of several 14 | common compiler attributes. 15 | 16 | 17 | .. function:: CORK_LIKELY(expression) 18 | CORK_UNLIKELY(expression) 19 | 20 | Indicate that the given Boolean *expression* is likely to be ``true`` 21 | or ``false``, respectively. The compiler can sometimes use this 22 | information to generate more efficient code. 23 | 24 | 25 | .. macro:: CORK_ATTR_CONST 26 | 27 | Declare a “constant” function. The return value of a constant 28 | function can only depend on its parameters. This is slightly more 29 | strict than a “pure” function (declared by 30 | :c:macro:`CORK_ATTR_PURE`); a constant function is not allowed to 31 | read from global variables, whereas a pure function is. 32 | 33 | .. note:: Note that the compiler won't verify that your function 34 | meets the requirements of a constant function. Instead, this 35 | attribute notifies the compiler of your intentions, which allows 36 | the compiler to assume more about your function when optimizing 37 | code that calls it. 38 | 39 | :: 40 | 41 | int square(int x) CORK_ATTR_CONST; 42 | 43 | 44 | .. macro:: CORK_ATTR_MALLOC 45 | 46 | Declare a function that returns a newly allocated pointer. The 47 | compiler can use this information to generate more accurate aliasing 48 | information, since it can infer that the result of the function 49 | cannot alias any other existing pointer. 50 | 51 | :: 52 | 53 | void *custom_malloc(size_t size) CORK_ATTR_MALLOC; 54 | 55 | 56 | .. macro:: CORK_ATTR_NOINLINE 57 | 58 | Declare that a function shouldn't be eligible for inlining. 59 | 60 | 61 | .. macro:: CORK_ATTR_PRINTF(format_index, args_index) 62 | 63 | Declare a function that takes in ``printf``\ -like parameters. 64 | *format_index* is the index (starting from 1) of the parameter that 65 | contains the ``printf`` format string. *args_index* is the index of 66 | the first parameter that contains the data to format. 67 | 68 | 69 | .. macro:: CORK_ATTR_PURE 70 | 71 | Declare a “pure” function. The return value of a pure function can 72 | only depend on its parameters, and on global variables. 73 | 74 | :: 75 | 76 | static int _next_id; 77 | int get_next_id(void) CORK_ATTR_PURE; 78 | 79 | 80 | .. macro:: CORK_ATTR_SENTINEL 81 | 82 | Declare a var-arg function whose last parameter must be a ``NULL`` 83 | sentinel value. When the compiler supports this attribute, it will 84 | check the actual parameters whenever this function is called, and 85 | ensure that the last parameter is a ``NULL``. 86 | 87 | 88 | .. macro:: CORK_ATTR_UNUSED 89 | 90 | Declare a entity that might not be used. This lets you keep 91 | ``-Wall`` activated in several cases where you're obligated to define 92 | something that you don't intend to use. 93 | 94 | :: 95 | 96 | CORK_ATTR_UNUSED static void 97 | unused_function(void) 98 | { 99 | CORK_ATTR_UNUSED int unused_value; 100 | } 101 | 102 | 103 | .. macro:: CORK_INITIALIZER(func_name) 104 | 105 | Declare a ``static`` function that will be automatically called at program 106 | startup. If there are multiple initializer functions linked into a program, 107 | there is no guarantee about the order in which the functions will be called. 108 | 109 | :: 110 | 111 | #include 112 | #include 113 | 114 | static cork_array(int) array; 115 | 116 | CORK_INITIALIZER(init_array) 117 | { 118 | cork_array_init(&array); 119 | } 120 | -------------------------------------------------------------------------------- /docs/old/basic-types.rst: -------------------------------------------------------------------------------- 1 | .. _basic-types: 2 | 3 | *********** 4 | Basic types 5 | *********** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | The types in this section ensure that the C99 integer types are 14 | available, regardless of platform. We also define some preprocessor 15 | macros that give the size of the non-fixed-size standard types. In 16 | addition, libcork defines some useful low-level types: 17 | 18 | .. toctree:: 19 | :maxdepth: 1 20 | 21 | int128 22 | net-addresses 23 | timestamps 24 | hash-values 25 | unique-ids 26 | 27 | Integral types 28 | ============== 29 | 30 | .. type:: bool 31 | 32 | A boolean. Where possible, we simply include ```` to get 33 | this type. It might be ``typedef``\ ed to ``int``\ . We also make 34 | sure that the following constants are defined: 35 | 36 | .. var:: bool false 37 | bool true 38 | 39 | .. type:: int8_t 40 | uint8_t 41 | int16_t 42 | uint16_t 43 | int32_t 44 | uint32_t 45 | int64_t 46 | uint64_t 47 | 48 | Signed and unsigned, fixed-size integral types. 49 | 50 | .. type:: intptr_t 51 | uintptr_t 52 | 53 | Signed and unsigned integers that are guaranteed to be big enough to 54 | hold a type-cast ``void *``\ . 55 | 56 | .. type:: size_t 57 | 58 | An unsigned integer big enough to hold the size of a memory object, 59 | or a maximal array index. 60 | 61 | .. type:: ptrdiff_t 62 | 63 | A signed integer big enough to hold the difference between two 64 | pointers. 65 | 66 | Size macros 67 | =========== 68 | 69 | .. macro:: CORK_SIZEOF_SHORT 70 | CORK_SIZEOF_INT 71 | CORK_SIZEOF_LONG 72 | CORK_SIZEOF_POINTER 73 | 74 | The size (in bytes) of the ``short``, ``int``, ``long``, and ``void 75 | *`` types, respectively. 76 | 77 | 78 | .. _embedded-struct: 79 | 80 | Embedded ``struct``\ s 81 | ====================== 82 | 83 | Quite often a callback function or API will take in a pointer to a 84 | particular ``struct``, with the expectation that you can embed that 85 | ``struct`` into some other type for extension purposes. Kind of a 86 | bastardized subclassing mechanism for C code. The doubly-linked list 87 | module is a perfect example; you're meant to embed 88 | :c:type:`cork_dllist_item` within the linked list element type. You can 89 | use the following macro to obtain the pointer to the containing 90 | (“subclass”) ``struct``, when given a pointer to the contained 91 | (“superclass”) ``struct``: 92 | 93 | .. function:: struct_type \*cork_container_of(field_type \*field, TYPE struct_type, FIELD field_name) 94 | 95 | The *struct_type* parameter must be the name of a ``struct`` type, 96 | *field_name* must be the name of some field within that 97 | ``struct``, and *field* must be a pointer to an instance of that 98 | field. The macro returns a pointer to the containing ``struct``. 99 | So, given the following definitions:: 100 | 101 | struct superclass { 102 | int a; 103 | }; 104 | 105 | struct subclass { 106 | int b; 107 | struct superclass parent; 108 | }; 109 | 110 | struct subclass instance; 111 | 112 | then the following identity holds:: 113 | 114 | cork_container_of(&instance.parent, struct subclass, parent) == &instance 115 | 116 | .. note:: When the superclass ``struct`` appears as the first element 117 | of the subclass ``struct``, you can obtain the same effect using a 118 | simple type-cast. However, the ``cork_container_of`` macro is 119 | more robust, since it also works when the superclass ``struct`` 120 | appears later on in the subclass ``struct``. 121 | -------------------------------------------------------------------------------- /docs/old/bitset.rst: -------------------------------------------------------------------------------- 1 | .. _bits: 2 | 3 | ******** 4 | Bit sets 5 | ******** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | This sections defines a type for storing an array of bits. This data structure 14 | is most often used to implement a set of integers. It is particularly good when 15 | you expect your sets to be *dense*. You should not use a bitset if the number 16 | of possibly elements is outrageously large, however, since that would cause your 17 | bitset to exhaust the available memory. 18 | 19 | .. type:: struct cork_bitset 20 | 21 | An array of bits. You should not allocate any instances of this type 22 | yourself; use :c:func:`cork_bitset_new` instead. 23 | 24 | .. member:: size_t bit_count 25 | 26 | The number of bits that are included in this array. (Each bit can be on 27 | or off; this does not give you the number of bits that are *on*, it gives 28 | you the number of bits in total, on or off.) 29 | 30 | 31 | .. function:: void cork_bitset_init(struct cork_bitset \*set) 32 | 33 | Initialize a new bitset instance that you've allocated yourself 34 | (usually on the stack). All bits will be initialized to ``0``. 35 | 36 | .. function:: struct cork_bitset \*cork_bitset_new(size_t bit_count) 37 | 38 | Create a new bitset with enough space to store the given number of bits. 39 | All bits will be initialized to ``0``. 40 | 41 | .. function:: void cork_bitset_done(struct cork_bitset \*set) 42 | 43 | Finalize a bitset, freeing any set content that it contains. This 44 | function should only be used for bitsets that you allocated yourself, 45 | and initialized using :c:func:`cork_bitset_init()`. You must **not** use 46 | this function to free a bitset allocated using :c:func:`cork_bitset_new()`. 47 | 48 | .. function:: void cork_bitset_free(struct cork_bitset \*set) 49 | 50 | Finalize and deallocate a bitset, freeing any set content that it 51 | contains. This function should only be used for bitsets allocated 52 | using :c:func:`cork_bitset_new()`. You must **not** use this 53 | function to free a bitset initialized using :c:func:`cork_bitset_init()`. 54 | 55 | .. function:: bool cork_bitset_get(struct cork_bitset \*set, size_t index) 56 | 57 | Return whether the given bit is on or off in *set*. It is your 58 | responsibility to ensure that *index* is within the valid range for *set*. 59 | 60 | .. function:: void cork_bitset_set(struct cork_bitset \*set, size_t index, bool value) 61 | 62 | Turn the given bit on or off in *set*. It is your responsibility to ensure 63 | that *index* is within the valid range for *set*. 64 | 65 | .. function:: void cork_bitset_clear(struct cork_bitset \*set) 66 | 67 | Turn off of the bits in *set*. 68 | -------------------------------------------------------------------------------- /docs/old/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import sys, os 4 | 5 | extensions = ['sphinx.ext.mathjax'] 6 | source_suffix = '.rst' 7 | master_doc = 'index' 8 | project_name = u'libcork' 9 | project_slug = u'libcork' 10 | company = u'RedJack, LLC' 11 | copyright_years = u'2011-2012' 12 | 13 | default_role = 'c:func' 14 | primary_domain = 'c' 15 | 16 | rst_epilog = """ 17 | .. |project_name| replace:: """ + project_name + """ 18 | """ 19 | 20 | # Intersphinx stuff 21 | 22 | # If your documentation uses intersphinx to link to other Sphinx 23 | # documentation sets, uncomment and fill in the following. 24 | # 25 | #intersphinx_mapping = { 26 | # 'libcork': ('http://libcork.readthedocs.org/en/latest/', None), 27 | #} 28 | 29 | # Our CMake build scripts will insert overrides below if the prereq 30 | # libraries have installed their Sphinx documentation locally. DO NOT 31 | # uncomment out the last line of this block; we need it commented so 32 | # that this conf.py file still works if CMake doesn't do its 33 | # substitution thing. 34 | # @INTERSPHINX_OVERRIDES@ 35 | 36 | #---------------------------------------------------------------------- 37 | # Everything below here shouldn't need to be changed. 38 | 39 | release = None 40 | version = None 41 | 42 | # Give CMake a chance to insert a version number 43 | # @VERSION_FOR_CONF_PY@ 44 | 45 | # Otherwise grab version from git 46 | if version is None: 47 | import re 48 | import subprocess 49 | release = str(subprocess.check_output(["git", "describe"]).rstrip()) 50 | version = re.sub(r"-dev.*$", "-dev", release) 51 | 52 | # Project details 53 | 54 | project = project_name 55 | copyright = copyright_years+u', '+company 56 | templates_path = ['_templates'] 57 | exclude_patterns = ['_build'] 58 | pygments_style = 'sphinx' 59 | 60 | html_theme = 'default' 61 | html_style = 'docco-sphinx.css' 62 | html_static_path = ['_static'] 63 | htmlhelp_basename = project_slug+'-doc' 64 | 65 | 66 | latex_documents = [ 67 | ('index', project_slug+'.tex', project_name+u' Documentation', 68 | company, 'manual'), 69 | ] 70 | 71 | man_pages = [ 72 | ('index', 'libcork', u'libcork documentation', 73 | [u'RedJack, LLC'], 1) 74 | ] 75 | 76 | texinfo_documents = [ 77 | ('index', 'libcork', u'libcork documentation', 78 | u'RedJack, LLC', 'libcork', 'One line description of project.', 79 | 'Miscellaneous'), 80 | ] 81 | -------------------------------------------------------------------------------- /docs/old/ds.rst: -------------------------------------------------------------------------------- 1 | .. _ds: 2 | 3 | *************** 4 | Data structures 5 | *************** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | libcork includes implementations of a number of useful data structures. 14 | 15 | .. toctree:: 16 | :maxdepth: 1 17 | 18 | array 19 | bitset 20 | slice 21 | managed-buffer 22 | buffer 23 | stream 24 | dllist 25 | hash-table 26 | ring-buffer 27 | -------------------------------------------------------------------------------- /docs/old/hash-values.rst: -------------------------------------------------------------------------------- 1 | .. _hash-values: 2 | 3 | *********** 4 | Hash values 5 | *********** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | 14 | The functions in this section can be used to produce fast, good hash 15 | values. 16 | 17 | .. note:: 18 | 19 | For the curious, libcork currently uses the public-domain 20 | `MurmurHash3 `_ as its hash 21 | implementation. 22 | 23 | 24 | Hashing in C code 25 | ----------------- 26 | 27 | A common pattern would be something along the lines of:: 28 | 29 | struct my_type { 30 | int a; 31 | long b; 32 | double c; 33 | size_t name_length; 34 | const char *name; 35 | }; 36 | 37 | cork_hash 38 | my_type_hash(const struct my_type *self) 39 | { 40 | /* hash of "struct my_type" */ 41 | cork_hash hash = 0xd4a130d8; 42 | hash = cork_hash_variable(hash, self->a); 43 | hash = cork_hash_variable(hash, self->b); 44 | hash = cork_hash_variable(hash, self->c); 45 | hash = cork_hash_buffer(hash, self->name, self->name_length); 46 | return hash; 47 | } 48 | 49 | In this example, the seed value (``0xd4a130d8``) is the hash of the 50 | constant string ``"struct my_type"``. You can produce seed values like 51 | this using the :ref:`cork-hash ` script described below:: 52 | 53 | $ cork-hash "struct my_type" 54 | 0xd4a130d8 55 | 56 | 57 | .. type:: uint32_t cork_hash 58 | 59 | .. function:: cork_hash cork_hash_buffer(cork_hash seed, const void \*src, size_t len) 60 | cork_hash cork_hash_variable(cork_hash seed, TYPE val) 61 | 62 | Incorporate the contents of the given binary buffer or variable into a hash 63 | value. For the ``_variable`` variant, *val* must be an lvalue visible in the 64 | current scope. 65 | 66 | The hash values produces by these functions can change over time, and might 67 | not be consistent across different platforms. The only guarantee is that 68 | hash values will be consistest for the duration of the current process. 69 | 70 | .. function:: cork_hash cork_stable_hash_buffer(cork_hash seed, const void \*src, size_t len) 71 | cork_hash cork_stable_hash_variable(cork_hash seed, TYPE val) 72 | 73 | Stable versions of :c:func:`cork_hash_buffer` and 74 | :c:func:`cork_hash_variable`. We guarantee that the hash values produced by 75 | this function will be consistent across different platforms, and across 76 | different versions of the libcork library. 77 | 78 | 79 | .. type:: cork_big_hash 80 | 81 | .. function:: cork_big_hash cork_big_hash_buffer(cork_big_hash seed, const void \*src, size_t len) 82 | 83 | Incorporate the contents of the given binary buffer into a "big" hash value. 84 | A big hash value has a much larger space of possible hash values (128 bits vs 85 | 32). 86 | 87 | 88 | .. function:: bool cork_big_hash_equal(cork_big_hash hash1, cork_big_hash hash2) 89 | 90 | Compare two big hash values for equality. 91 | 92 | 93 | .. _cork-hash: 94 | 95 | Hashing from the command line 96 | ----------------------------- 97 | 98 | Several parts of libcork use hash values as identifiers; you use a 99 | unique string to identify part of your code, and use the hash of that 100 | string as the actual identifier value. We provide a command-line 101 | utility that you can use to produce these hash values: 102 | 103 | .. code-block:: none 104 | 105 | cork-hash 106 | 107 | .. describe:: 108 | 109 | The string to hash. This should be provided as a single argument on 110 | the command line, so if your string contains spaces or other shell 111 | meta-characters, you must enclose the string in quotes. 112 | -------------------------------------------------------------------------------- /docs/old/index.rst: -------------------------------------------------------------------------------- 1 | .. _index: 2 | 3 | |project_name| documentation 4 | ============================ 5 | 6 | This is the documentation for |project_name| |release|, last updated 7 | |today|. 8 | 9 | 10 | Introduction 11 | ------------ 12 | 13 | So what is libcork, exactly? It's a “simple, easily embeddable, cross-platform 14 | C library”. It falls roughly into the same category as glib_ or APR_ in the C 15 | world; the STL, POCO_, or QtCore_ in the C++ world; or the standard libraries 16 | of any decent dynamic language. 17 | 18 | So if libcork has all of these comparables, why a new library? Well, none of 19 | the C++ options are really applicable here. And none of the C options work, 20 | because one of the main goals is to have the library be highly modular, and 21 | useful in resource-constrained systems. Once we describe some of the design 22 | decisions that we've made in libcork, you'll hopefully see how this fits into 23 | an interesting niche of its own. 24 | 25 | .. _glib: http://library.gnome.org/devel/glib/ 26 | .. _APR: http://apr.apache.org/ 27 | .. _POCO: http://pocoproject.org/ 28 | .. _QtCore: http://qt.nokia.com/ 29 | 30 | 31 | Contents 32 | -------- 33 | 34 | .. toctree:: 35 | :maxdepth: 2 36 | 37 | config 38 | versions 39 | visibility 40 | basic-types 41 | byte-order 42 | attributes 43 | allocation 44 | errors 45 | gc 46 | mempool 47 | ds 48 | cli 49 | files 50 | process 51 | subprocess 52 | threads 53 | 54 | 55 | Indices and tables 56 | ------------------ 57 | 58 | * :ref:`genindex` 59 | * :ref:`search` 60 | -------------------------------------------------------------------------------- /docs/old/managed-buffer.rst: -------------------------------------------------------------------------------- 1 | .. _managed-buffer: 2 | 3 | ********************** 4 | Managed binary buffers 5 | ********************** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | This section defines an interface for handling reference-counted binary 14 | buffers. The :c:type:`cork_managed_buffer` type wraps a buffer with a 15 | simple reference count, and takes care of freeing the necessary 16 | resources when the reference count drops to zero. There should only be 17 | a single :c:type:`cork_managed_buffer` instance for any given buffer, 18 | regardless of how many threads or functions access that buffer. Each 19 | thread or function that uses the buffer does so via a 20 | :c:type:`cork_slice` instance. This type is meant to be allocated 21 | directly on the stack (or in some other managed storage), and keeps a 22 | pointer to the managed buffer instance that it slices. As its name 23 | implies, a slice can refer to a subset of the buffer. 24 | 25 | 26 | .. type:: struct cork_managed_buffer 27 | 28 | A “managed buffer”, which wraps a buffer with a simple reference 29 | count. 30 | 31 | Managed buffer consumers should consider all of the fields of this 32 | class private. Managed buffer implementors should fill in this 33 | fields when constructing a new ``cork_managed_buffer`` instance. 34 | 35 | .. member:: const void \*buf 36 | 37 | The buffer that this instance manages. 38 | 39 | .. member:: size_t size 40 | 41 | The size of :c:member:`buf`. 42 | 43 | .. member:: volatile int ref_count 44 | 45 | A reference count for the buffer. If this drops to ``0``, the 46 | buffer will be finalized. 47 | 48 | .. member:: struct cork_managed_buffer_iface \*iface 49 | 50 | The managed buffer implementation for this instance. 51 | 52 | 53 | .. function:: struct cork_managed_buffer \*cork_managed_buffer_ref(struct cork_managed_buffer \*buf) 54 | 55 | Atomically increase the reference count of a managed buffer. This 56 | function is thread-safe. 57 | 58 | 59 | .. function:: void cork_managed_buffer_unref(struct cork_managed_buffer \*buf) 60 | 61 | Atomically decrease the reference count of a managed buffer. If the 62 | reference count falls to ``0``, the instance is freed. This function 63 | is thread-safe. 64 | 65 | .. function:: int cork_managed_buffer_slice(struct cork_slice \*dest, struct cork_managed_buffer \*buffer, size_t offset, size_t length) 66 | int cork_managed_buffer_slice_offset(struct cork_slice \*dest, struct cork_managed_buffer \*buffer, size_t offset) 67 | 68 | Initialize a new slice that refers to a subset of a managed buffer. 69 | The *offset* and *length* parameters identify the subset. (For the 70 | ``_slice_offset`` variant, the *length* is calculated automatically 71 | to include all of the managed buffer content starting from *offset*.) 72 | If these parameters don't refer to a valid portion of the buffer, we 73 | return ``false``, and you must not try to deference the slice's 74 | :c:member:`buf ` pointer. If the slice is valid, we 75 | return ``true``. 76 | 77 | Regardless of whether the new slice is valid, you **must** ensure 78 | that you call :c:func:`cork_slice_finish()` when you are done with 79 | the slice. 80 | 81 | 82 | Predefined managed buffer implementations 83 | ----------------------------------------- 84 | 85 | .. function:: struct cork_managed_buffer \*cork_managed_buffer_new_copy(const void \*buf, size_t size) 86 | 87 | Make a copy of *buf*, and allocate a new managed buffer to manage 88 | this copy. The copy will automatically be freed when the managed 89 | buffer's reference count drops to ``0``. 90 | 91 | 92 | .. type:: void (\*cork_managed_buffer_freer)(void \*buf, size_t size) 93 | 94 | A finalization function for a managed buffer created by 95 | :c:func:`cork_managed_buffer_new()`. 96 | 97 | .. function:: struct cork_managed_buffer \*cork_managed_buffer_new(const void \*buf, size_t size, cork_managed_buffer_freer free) 98 | 99 | Allocate a new managed buffer to manage an existing buffer (*buf*). 100 | The existing buffer is *not* copied; the new managed buffer instance 101 | takes control of it. When the managed buffer's reference count drops 102 | to ``0``, it will call *free* to finalize *buf*. 103 | 104 | This is a helper function, and keeps you from having to write a 105 | complete custom managed buffer implementation when you don't need to 106 | store any additional state in the managed buffer object. 107 | 108 | .. note:: 109 | 110 | The *free* function is *not* responsible for freeing the 111 | ``cork_managed_buffer`` instance itself. 112 | 113 | 114 | Custom managed buffer implementations 115 | ------------------------------------- 116 | 117 | .. type:: struct cork_managed_buffer_iface 118 | 119 | The interface of methods that managed buffer implementations must 120 | provide. 121 | 122 | .. member:: void (\*free)(struct cork_managed_buffer \*self) 123 | 124 | Free the contents of a managed buffer, and the 125 | ``cork_managed_buffer`` instance itself. 126 | -------------------------------------------------------------------------------- /docs/old/ring-buffer.rst: -------------------------------------------------------------------------------- 1 | .. _ring-buffer: 2 | 3 | ************ 4 | Ring buffers 5 | ************ 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | 14 | .. type:: struct cork_ring_buffer 15 | 16 | A ring buffer data structure that can be easily embedded into other 17 | types. All of the fields in ``cork_ring_buffer`` are private; you 18 | should only access the contents of the ring buffer via the functions 19 | defined below. 20 | 21 | The elements of a ring buffer are ``void *`` pointers. (You can also 22 | store integers via the :c:type:`intptr_t` and :c:type:`uintptr_t` 23 | types.) Ring buffers have a fixed capacity, which must be specified 24 | when the ring buffer instance is initialized. You cannot add extra 25 | space to an existing ring buffer. 26 | 27 | Ring buffers implement a FIFO queue structure; elements will be 28 | returned by :c:func:`cork_ring_buffer_pop()` in the same order that 29 | they're added by :c:func:`cork_ring_buffer_add()`. 30 | 31 | 32 | .. function:: int cork_ring_buffer_init(struct cork_ring_buffer \*buf, size_t size) 33 | struct cork_ring_buffer \*cork_ring_buffer_new(size_t size) 34 | 35 | Initializes a ring buffer instance, having a capacity of *size* elements. 36 | The ``_init`` version should be used to initialize an instance you 37 | allocated yourself on the stack. The ``_new`` version will allocate an 38 | instance from the heap. If memory allocation fails in either function, 39 | the program will abort with an error. 40 | 41 | 42 | .. function:: void cork_ring_buffer_done(struct cork_ring_buffer \*buf) 43 | void cork_ring_buffer_free(struct cork_ring_buffer \*buf) 44 | 45 | Finalizes a ring buffer instance. The ``_done`` variant should be used to 46 | finalize an instance that you allocated yourself (i.e., on the stack). The 47 | ``_free`` version should be used on instance allocated on the heap by using 48 | :c:func:`cork_hash_table_new()`. Nothing special is done to any 49 | remaining elements in the ring buffer; if they need to be finalized, 50 | you should do that yourself before calling this function. 51 | 52 | 53 | .. function:: bool cork_ring_buffer_is_empty(struct cork_ring_buffer \*buf) 54 | bool cork_ring_buffer_is_full(struct cork_ring_buffer \*buf) 55 | 56 | Returns whether the ring buffer is empty or full. (You cannot add 57 | elements to a full ring buffer, and you cannot pop elemenst from an 58 | empty one.) 59 | 60 | 61 | .. function:: int cork_ring_buffer_add(struct cork_ring_buffer \*buf, void \*element) 62 | 63 | Adds *element* to a ring buffer. If the ring buffer is full, we 64 | return ``-1``, and the ring buffer will be unchanged. Otherwise we 65 | return ``0``. 66 | 67 | .. function:: void \*cork_ring_buffer_pop(struct cork_ring_buffer \*buf) 68 | void \*cork_ring_buffer_peek(struct cork_ring_buffer \*buf) 69 | 70 | Returns the next element in the ring buffer. If the ring buffer is 71 | empty, we return ``NULL``. The ``_pop`` variant will remove the 72 | returned element from the ring buffer before returning it; the 73 | ``_peek`` variant will leave the element in the ring buffer. 74 | -------------------------------------------------------------------------------- /docs/old/timestamps.rst: -------------------------------------------------------------------------------- 1 | .. _timestamps: 2 | 3 | ************************* 4 | High-precision timestamps 5 | ************************* 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | 14 | .. type:: uint64_t cork_timestamp 15 | 16 | A high-precision timestamp type. A timestamp is represented by a 17 | 64-bit integer, whose unit is the *gammasecond* (γsec), where 18 | :math:`1~\textrm{γsec} = \frac{1}{2^{32}} \textrm{sec}`. With this 19 | representation, the upper 32 bits of a timestamp value represent the 20 | timestamp truncated (towards zero) to seconds. 21 | 22 | For this type, we don't concern ourselves with any higher-level 23 | issues of clock synchronization or time zones. ``cork_timestamp`` 24 | values can be used to represent any time quantity, regardless of 25 | which time standard (UTC, GMT, TAI) you use, or whether it takes into 26 | account the local time zone. 27 | 28 | 29 | .. function:: void cork_timestamp_init_sec(cork_timestamp \*ts, uint32_t sec) 30 | void cork_timestamp_init_gsec(cork_timestamp \*ts, uint32_t sec, uint32_t gsec) 31 | void cork_timestamp_init_msec(cork_timestamp \*ts, uint32_t sec, uint32_t msec) 32 | void cork_timestamp_init_usec(cork_timestamp \*ts, uint32_t sec, uint32_t usec) 33 | void cork_timestamp_init_nsec(cork_timestamp \*ts, uint32_t sec, uint32_t nsec) 34 | 35 | Initializes a timestamp from a separate seconds part and fractional 36 | part. For the ``_sec`` variant, the fractional part will be set to 37 | ``0``. For the ``_gsec`` variant, you provide the fractional part in 38 | gammaseconds. For the ``_msec``, ``_usec``, and ``_nsec`` variants, the 39 | fractional part will be translated into gammaseconds from milliseconds, 40 | microseconds, or nanoseconds, respectively. 41 | 42 | 43 | .. function:: void cork_timestamp_init_now(cork_timestamp \*ts) 44 | 45 | Initializes a timestamp with the current UTC time of day. 46 | 47 | .. note:: 48 | 49 | The resolution of this function is system-dependent. 50 | 51 | 52 | .. function:: uint32_t cork_timestamp_sec(const cork_timestamp ts) 53 | 54 | Returns the seconds portion of a timestamp. 55 | 56 | .. function:: uint32_t cork_timestamp_gsec(const cork_timestamp ts) 57 | uint32_t cork_timestamp_msec(const cork_timestamp ts) 58 | uint32_t cork_timestamp_usec(const cork_timestamp ts) 59 | uint32_t cork_timestamp_nsec(const cork_timestamp ts) 60 | 61 | Returns the fractional portion of a timestamp. The variants return the 62 | fractional portion in, respectively, gammaseconds, milliseconds, 63 | microseconds, or nanoseconds. 64 | 65 | 66 | .. function:: int cork_timestamp_format_utc(const cork_timestamp ts, const char \*format, struct cork_buffer \*buf) 67 | int cork_timestamp_format_local(const cork_timestamp ts, const char \*format, struct cork_buffer \*buf) 68 | 69 | Create the string representation of the given timestamp according to 70 | *format*, appending the result to the current contents of *buf*. 71 | 72 | The ``_utc`` variant assumes that *ts* represents a UTC time, whereas the 73 | ``_local`` variant assumes that it represents a time in the local time zone. 74 | 75 | *format* is a format string whose syntax is similar to that of the POSIX 76 | ``strftime`` function. *format* must contain arbitrary text interspersed 77 | with ``%`` specifiers, which will be replaced with portions of the timestamp. 78 | The following specifiers are recognized (note that this list does **not** 79 | include all of the specifiers supported by ``strftime``): 80 | 81 | ============== ==================================================== 82 | Specifier Replacement 83 | ============== ==================================================== 84 | ``%%`` A literal ``%`` character 85 | ``%d`` Day of month (``01``-``31``) 86 | ``%[width]f`` Fractional seconds (zero-padded, limited to ``[width]`` 87 | digits) 88 | ``%H`` Hour in current day (``00``-``23``) 89 | ``%m`` Month (``01``-``12``) 90 | ``%M`` Minute in current hour (``00``-``59``) 91 | ``%s`` Number of seconds since Unix epoch 92 | ``%S`` Second in current minute (``00``-``60``) 93 | ``%Y`` Four-digit year (including century) 94 | ============== ==================================================== 95 | 96 | If the format string is invalid, we will return an :ref:`error condition 97 | `. 98 | -------------------------------------------------------------------------------- /docs/old/unique-ids.rst: -------------------------------------------------------------------------------- 1 | .. _unique-ids: 2 | 3 | ****************** 4 | Unique identifiers 5 | ****************** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | 14 | The functions in this section let you define compile-time unique identifiers. 15 | These identifiers are simple C variables, and each one is guaranteed to be 16 | unique within the context of a single execution of your program. They are *not* 17 | appropriate for use as external identifiers --- for instance, for serializing 18 | into long-term storage or sending via a communications channel to another 19 | process. 20 | 21 | 22 | .. type:: cork_uid 23 | 24 | A unique identifier. 25 | 26 | 27 | .. macro:: cork_uid CORK_UID_NONE 28 | 29 | A unique identifier value that means "no identifier". This is guaranteed to 30 | be distinct from all other unique identifiers. It is invalid to call 31 | :c:func:`cork_uid_hash`, :c:func:`cork_uid_id`, or :c:func:`cork_uid_name` on 32 | this identifier. 33 | 34 | 35 | .. macro:: cork_uid_define(SYMBOL id) 36 | cork_uid_define_named(SYMBOL id, const char \*name) 37 | 38 | You use the :c:func:`cork_uid_define` macro to define a new unique identifier 39 | with the given C identifier *id*. The ``_define`` variant also uses *id* as 40 | the identifier's human-readable name; the ``_define_named`` variant let's you 41 | provide a separate human-readable name. Within the context of a single 42 | execution of this program, this identifier is guaranteed to be distinct from 43 | any other identifier, regardless of which library the identifiers are defined 44 | in. 45 | 46 | In the same compilation unit, you can then use the C identifier *id* to 47 | retrieve the :c:type:`cork_uid` instance for this identifier. 48 | 49 | .. note:: 50 | 51 | The unique identifier objects are declared ``static``, so they are only 52 | directly visible (using the C identifier *id*) in the same compilation 53 | unit as the :c:func:`cork_uid_define` call that created the identifier. 54 | The resulting :c:type:`cork_uid` value, however, can be passed around the 55 | rest of your code however you want. 56 | 57 | 58 | .. function:: bool cork_uid_equal(const cork_uid id1, const cork_uid id2) 59 | 60 | Return whether two :c:type:`cork_uid` values refer to the same unique 61 | identifier. 62 | 63 | 64 | .. function:: cork_hash cork_uid_hash(const cork_uid id) 65 | 66 | Return a :ref:`hash value ` for the given identifier. 67 | 68 | 69 | .. function:: const char \*cork_uid_name(const cork_uid id) 70 | 71 | Return the name of the given unique identifier. 72 | 73 | 74 | Example 75 | ======= 76 | 77 | :: 78 | 79 | #include 80 | #include 81 | 82 | cork_uid_define(test_id); 83 | 84 | int 85 | main(void) 86 | { 87 | cork_uid id = test_id; 88 | printf("Identifier %p has name %s\n", id, cork_uid_name(id)); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /docs/old/versions.rst: -------------------------------------------------------------------------------- 1 | .. _versions: 2 | 3 | *************** 4 | Library version 5 | *************** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | The macros and functions in this section let you determine the version of the 14 | libcork library at compile-time and runtime, and make it easier for you to 15 | define similar macros and functions in your own libraries. 16 | 17 | 18 | libcork version 19 | --------------- 20 | 21 | .. macro:: CORK_VERSION 22 | 23 | The libcork library version, encoded as a single number as follows:: 24 | 25 | (major * 1000000) + (minor * 1000) + patch 26 | 27 | For instance, version 1.2.10 would be encoded as 1002010. 28 | 29 | .. macro:: CORK_VERSION_MAJOR 30 | CORK_VERSION_MINOR 31 | CORK_VERSION_PATCH 32 | 33 | The libcork library version, with each part of the version number separated 34 | out into separate macros. 35 | 36 | 37 | .. function:: const char \*cork_version_string(void) 38 | const char \*cork_revision_string(void) 39 | 40 | Return the libcork library version or revision as a string. The *version* is 41 | the simple three-part version number (``major:minor:patch``). The 42 | *revision* is an opaque string that identifies the specific revision in 43 | libcork's code history. (Right now, this is a SHA-1 git commit identifier.) 44 | 45 | 46 | .. tip:: Compile-time vs runtime 47 | 48 | There's an important difference between the :c:macro:`CORK_VERSION` macro and 49 | :c:func:`cork_version_string` function, even though they seemingly return the 50 | same information. 51 | 52 | The macro version be evaluated by the preprocessor, and so it will return the 53 | version that was available *when your code was compiled*. If you later 54 | install a newer (but backwards-compatible) version of libcork, any code that 55 | called the macro will still have the original version, and not the new 56 | version. 57 | 58 | The function version, on the other hand, calculates the version information 59 | *at runtime*, when the function is actually called. That means that the 60 | function result will always give you the current installed libcork version, 61 | even as newer versions are installed on the system. 62 | 63 | 64 | Constructing version information 65 | -------------------------------- 66 | 67 | If you're writing a library that uses libcork, it's a good idea to provide your 68 | own version information, similar to how libcork does. 69 | 70 | 71 | .. function:: CORK_MAKE_VERSION(major, minor, patch) 72 | 73 | Assemble a ``major.minor.patch`` version into a single number, using the same 74 | pattern as :c:macro:`CORK_VERSION`. 75 | -------------------------------------------------------------------------------- /docs/old/visibility.rst: -------------------------------------------------------------------------------- 1 | .. _visibility: 2 | 3 | ***************** 4 | Symbol visibility 5 | ***************** 6 | 7 | .. highlight:: c 8 | 9 | :: 10 | 11 | #include 12 | 13 | When writing a shared library, you should always be careful to explicitly mark 14 | which functions and other symbols are part of the library's public API, and 15 | which should only be used internally by the library. There are a number of 16 | benefits to doing this; there is a good summary on the `GCC wiki`_. (Note that 17 | even though that summary is on the GCC wiki, the notes apply equally well to 18 | other compilers and platforms.) 19 | 20 | .. _GCC wiki: http://gcc.gnu.org/wiki/Visibility 21 | 22 | libcork provides several helper macros that make it easier to do this. We use 23 | these macros ourselves to define libcork's public API. 24 | 25 | 26 | Defining a library's public API 27 | ------------------------------- 28 | 29 | On some platforms (for instance, on Windows), you must declare each public 30 | function and symbol differently depending on whether you're compiling the 31 | library that *defines* the symbol, or a library or program that *uses* the 32 | symbol. The first is called an *export*, the second an *import*. On other 33 | platforms (for instance, GCC on Linux), the declaration of a public symbol is 34 | the same regardless of whether you're exporting or importing the symbol. 35 | libcork provides macros that let you explicitly declare a symbol as an export or 36 | an import in a platform-independent way. 37 | 38 | .. macro:: CORK_EXPORT 39 | CORK_IMPORT 40 | 41 | Explicitly declare that a symbol should be exported from the current shared 42 | library, or imported from some other shared library. 43 | 44 | However, you will rarely need to use these macros directly. Instead, when 45 | writing a new shared library, you should declare a new preprocessor macro 46 | (specific to the new library), which you'll use when declaring the library's 47 | public API. For instance, if you're creating a new library called 48 | *libfoo*, you would declare a new preprocessor macro called ``FOO_API``:: 49 | 50 | #if !defined(FOO_API) 51 | #define FOO_API CORK_IMPORT 52 | #endif 53 | 54 | This ensures that anyone who wants to *use* libfoo doesn't need to do anything 55 | special; the ``FOO_API`` macro will default to importing the symbols from 56 | libfoo's public API. 57 | 58 | When *building* libfoo, you must set up your build system to define this 59 | variable differently; since you need to *export* the symbols in this case, the 60 | ``FOO_API`` macro should be set to ``CORK_EXPORT``. Each build system will have 61 | a different way to do this. In CMake, for instance, you'd add the following: 62 | 63 | .. code-block:: cmake 64 | 65 | set_target_properties(libfoo PROPERTIES 66 | COMPILE_DEFINITIONS FOO_API=CORK_EXPORT 67 | ) 68 | 69 | Then, in all of your header files, you should use your new ``FOO_API`` macro 70 | when declaring each function or symbol in the public API:: 71 | 72 | FOO_API int 73 | foo_load_from_file(const char *name); 74 | 75 | FOO_API void 76 | foo_do_something_great(int flags); 77 | 78 | extern FOO_API const char *foo_name; 79 | 80 | 81 | Local symbols 82 | ------------- 83 | 84 | Normally, if you need a function to be local, and not be exported as part of the 85 | library's public API, you can just declare it ``static``:: 86 | 87 | static int 88 | file_local_function(void) 89 | { 90 | /* This function is not visible outside of this file. */ 91 | return 0; 92 | } 93 | 94 | This works great as long as the function is only needed within the current 95 | source file. Sometimes, though, you need to define a function that can be used 96 | in other source files within the same library, but which shouldn't be visible 97 | outside of the library. To do this, you should define the function using the 98 | :c:macro:`CORK_LOCAL` macro. 99 | 100 | .. macro:: CORK_LOCAL 101 | 102 | Declare a symbol that should be visible in any source file within the current 103 | library, but not visible outside of the library. 104 | 105 | As an example:: 106 | 107 | CORK_LOCAL int 108 | library_local_function(void) 109 | { 110 | /* This function is visible in other files, but not outside of the 111 | * library. */ 112 | return 0; 113 | } 114 | 115 | Since you're going to use this function in multiple files, you'll want to 116 | declare the function in a header file. However, since the function is not part 117 | of the public API, this should *not* be defined in a public header file (that 118 | is, one that's installed along with the shared library). Instead, you should 119 | include a private header file that's only available in your library's source 120 | code archive, and which should not be installed with the other public header 121 | files. 122 | -------------------------------------------------------------------------------- /extras/hashstring.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license 7 | # details. 8 | # ---------------------------------------------------------------------- 9 | 10 | # Calculates the 32-bit MurmurHash3 hash value [1] for a string provided on the 11 | # command line. 12 | # 13 | # [1] http://code.google.com/p/smhasher/wiki/MurmurHash3 14 | 15 | def rotl32(a, b): 16 | return (((a << (b & 0x1f)) & 0xffffffff) | 17 | ((a >> (32 - (b & 0x1f))) & 0xffffffff)) 18 | 19 | def fmix(h): 20 | h = h ^ (h >> 16) 21 | h = (h * 0x85ebca6b) & 0xffffffff 22 | h = h ^ (h >> 13) 23 | h = (h * 0xc2b2ae35) & 0xffffffff 24 | h = h ^ (h >> 16) 25 | return h 26 | 27 | def hash(value, seed): 28 | import struct 29 | length = len(value) 30 | num_blocks = length / 4 31 | tail_length = length % 4 32 | fmt = "<" + ("i" * num_blocks) + ("b" * tail_length) 33 | vals = struct.unpack(fmt, value) 34 | 35 | h1 = seed 36 | c1 = 0xcc9e2d51 37 | c2 = 0x1b873593 38 | for block in vals[:num_blocks]: 39 | k1 = block 40 | k1 = (k1 * c1) & 0xffffffff 41 | k1 = rotl32(k1, 15) 42 | k1 = (k1 * c2) & 0xffffffff 43 | 44 | h1 = h1 ^ k1 45 | h1 = rotl32(h1, 13) 46 | h1 = (h1 * 5 + 0xe6546b64) & 0xffffffff 47 | 48 | k1 = 0 49 | if tail_length >= 3: 50 | k1 = k1 ^ ((vals[num_blocks + 2] << 16) & 0xffffffff) 51 | if tail_length >= 2: 52 | k1 = k1 ^ ((vals[num_blocks + 1] << 8) & 0xffffffff) 53 | if tail_length >= 1: 54 | k1 = k1 ^ ( vals[num_blocks] & 0xffffffff) 55 | k1 = (k1 * c1) & 0xffffffff 56 | k1 = rotl32(k1, 15) 57 | k1 = (k1 * c2) & 0xffffffff 58 | h1 = h1 ^ k1 59 | 60 | h1 = h1 ^ (length & 0xffffffff) 61 | return fmix(h1) 62 | 63 | 64 | if __name__ == "__main__": 65 | import sys 66 | if len(sys.argv) != 2 and len(sys.argv) != 3: 67 | print("Usage: hashstring.py []") 68 | sys.exit(1) 69 | 70 | def myhex(v): 71 | return hex(v).rstrip("L") 72 | 73 | if len(sys.argv) == 3: 74 | seed = long(sys.argv[2]) & 0xffffffff 75 | else: 76 | seed = 0 77 | 78 | print(myhex(hash(sys.argv[1], seed))) 79 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2015, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | configure_file( 10 | ${CMAKE_CURRENT_SOURCE_DIR}/libcork/config/version.h.in 11 | ${CMAKE_CURRENT_BINARY_DIR}/libcork/config/version.h 12 | ESCAPE_QUOTES @ONLY 13 | ) 14 | 15 | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ 16 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 17 | FILES_MATCHING PATTERN "*.h") 18 | 19 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcork/config/version.h 20 | DESTINATION include/libcork/config) 21 | -------------------------------------------------------------------------------- /include/libcork/cli.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CLI_H 12 | #define LIBCORK_CLI_H 13 | 14 | /*** include all of the parts ***/ 15 | 16 | #include 17 | 18 | #endif /* LIBCORK_CLI_H */ 19 | -------------------------------------------------------------------------------- /include/libcork/cli/commands.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_COMMANDS_H 12 | #define LIBCORK_COMMANDS_H 13 | 14 | #include 15 | 16 | 17 | typedef void 18 | (*cork_leaf_command_run)(int argc, char **argv); 19 | 20 | typedef int 21 | (*cork_option_parser)(int argc, char **argv); 22 | 23 | enum cork_command_type { 24 | CORK_COMMAND_SET, 25 | CORK_LEAF_COMMAND 26 | }; 27 | 28 | struct cork_command { 29 | enum cork_command_type type; 30 | const char *name; 31 | const char *short_desc; 32 | const char *usage_suffix; 33 | const char *full_help; 34 | 35 | int 36 | (*parse_options)(int argc, char **argv); 37 | 38 | struct cork_command **set; 39 | cork_leaf_command_run run; 40 | }; 41 | 42 | #define cork_command_set(name, sd, parse_options, set) \ 43 | { \ 44 | CORK_COMMAND_SET, name, sd, NULL, NULL, \ 45 | parse_options, set, NULL \ 46 | } 47 | 48 | #define cork_leaf_command(name, sd, us, fh, parse_options, run) \ 49 | { \ 50 | CORK_LEAF_COMMAND, name, sd, us, fh, \ 51 | parse_options, NULL, run \ 52 | } 53 | 54 | CORK_API void 55 | cork_command_show_help(struct cork_command *command, const char *message); 56 | 57 | CORK_API int 58 | cork_command_main(struct cork_command *root, int argc, char **argv); 59 | 60 | 61 | #endif /* LIBCORK_COMMANDS_H */ 62 | -------------------------------------------------------------------------------- /include/libcork/config.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CONFIG_H 12 | #define LIBCORK_CONFIG_H 13 | 14 | /*** include all of the parts ***/ 15 | 16 | #include 17 | 18 | #endif /* LIBCORK_CONFIG_H */ 19 | -------------------------------------------------------------------------------- /include/libcork/config/arch.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012-2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CONFIG_ARCH_H 12 | #define LIBCORK_CONFIG_ARCH_H 13 | 14 | 15 | /*----------------------------------------------------------------------- 16 | * Platform 17 | */ 18 | 19 | #if defined(__i386__) || defined(_M_IX86) 20 | #define CORK_CONFIG_ARCH_X86 1 21 | #else 22 | #define CORK_CONFIG_ARCH_X86 0 23 | #endif 24 | 25 | #if defined(__x86_64__) || defined(_M_X64) 26 | #define CORK_CONFIG_ARCH_X64 1 27 | #else 28 | #define CORK_CONFIG_ARCH_X64 0 29 | #endif 30 | 31 | #if defined(__powerpc__) || defined(__ppc__) 32 | /* GCC-ish compiler */ 33 | #define CORK_CONFIG_ARCH_PPC 1 34 | #elif defined(_M_PPC) 35 | /* VS-ish compiler */ 36 | #define CORK_CONFIG_ARCH_PPC 1 37 | #elif defined(_ARCH_PPC) 38 | /* Something called XL C/C++? */ 39 | #define CORK_CONFIG_ARCH_PPC 1 40 | #else 41 | #define CORK_CONFIG_ARCH_PPC 0 42 | #endif 43 | 44 | 45 | #endif /* LIBCORK_CONFIG_ARCH_H */ 46 | -------------------------------------------------------------------------------- /include/libcork/config/bsd.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CONFIG_BSD_H 12 | #define LIBCORK_CONFIG_BSD_H 13 | 14 | /*----------------------------------------------------------------------- 15 | * Endianness 16 | */ 17 | 18 | #include 19 | 20 | #if BYTE_ORDER == BIG_ENDIAN 21 | #define CORK_CONFIG_IS_BIG_ENDIAN 1 22 | #define CORK_CONFIG_IS_LITTLE_ENDIAN 0 23 | #elif BYTE_ORDER == LITTLE_ENDIAN 24 | #define CORK_CONFIG_IS_BIG_ENDIAN 0 25 | #define CORK_CONFIG_IS_LITTLE_ENDIAN 1 26 | #else 27 | #error "Cannot determine system endianness" 28 | #endif 29 | 30 | #define CORK_HAVE_REALLOCF 1 31 | #define CORK_HAVE_PTHREADS 1 32 | 33 | 34 | #endif /* LIBCORK_CONFIG_BSD_H */ 35 | -------------------------------------------------------------------------------- /include/libcork/config/config.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2015, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CONFIG_CONFIG_H 11 | #define LIBCORK_CONFIG_CONFIG_H 12 | 13 | 14 | /* If you want to skip autodetection, define this to 1, and provide a 15 | * libcork/config/custom.h header file. */ 16 | 17 | #if !defined(CORK_CONFIG_SKIP_AUTODETECT) 18 | #define CORK_CONFIG_SKIP_AUTODETECT 0 19 | #endif 20 | 21 | 22 | #if CORK_CONFIG_SKIP_AUTODETECT 23 | /* The user has promised that they'll define everything themselves. */ 24 | #include 25 | 26 | #else 27 | /* Otherwise autodetect! */ 28 | 29 | 30 | /**** VERSION ****/ 31 | 32 | #include 33 | 34 | 35 | /**** ARCHITECTURES ****/ 36 | 37 | #include 38 | 39 | 40 | /**** PLATFORMS ****/ 41 | #if (defined(__unix__) || defined(unix)) && !defined(USG) 42 | /* We need this to test for BSD, but it's a good idea to have for 43 | * any brand of Unix.*/ 44 | #include 45 | #endif 46 | 47 | #if defined(__linux) || defined(__FreeBSD_kernel__) || defined(__GNU__) 48 | /* Do some Linux, kFreeBSD or GNU/Hurd specific autodetection. */ 49 | #include 50 | 51 | #elif defined(__APPLE__) && defined(__MACH__) 52 | /* Do some Mac OS X-specific autodetection. */ 53 | #include 54 | 55 | #elif defined(BSD) && (BSD >= 199103) 56 | /* Do some BSD (4.3 code base or newer)specific autodetection. */ 57 | #include 58 | 59 | #endif /* platforms */ 60 | 61 | 62 | /**** COMPILERS ****/ 63 | 64 | #if defined(__GNUC__) 65 | /* Do some GCC-specific autodetection. */ 66 | #include 67 | 68 | #endif /* compilers */ 69 | 70 | 71 | #endif /* autodetect or not */ 72 | 73 | 74 | #endif /* LIBCORK_CONFIG_CONFIG_H */ 75 | -------------------------------------------------------------------------------- /include/libcork/config/gcc.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CONFIG_GCC_H 12 | #define LIBCORK_CONFIG_GCC_H 13 | 14 | /* Figure out the GCC version */ 15 | 16 | #if defined(__GNUC_PATCHLEVEL__) 17 | #define CORK_CONFIG_GCC_VERSION (__GNUC__ * 10000 \ 18 | + __GNUC_MINOR__ * 100 \ 19 | + __GNUC_PATCHLEVEL__) 20 | #else 21 | #define CORK_CONFIG_GCC_VERSION (__GNUC__ * 10000 \ 22 | + __GNUC_MINOR__ * 100) 23 | #endif 24 | 25 | 26 | /*----------------------------------------------------------------------- 27 | * Compiler attributes 28 | */ 29 | 30 | /* The GCC assembly syntax has been available basically forever. */ 31 | 32 | #if defined(CORK_CONFIG_GCC_VERSION) 33 | #define CORK_CONFIG_HAVE_GCC_ASM 1 34 | #else 35 | #define CORK_CONFIG_HAVE_GCC_ASM 0 36 | #endif 37 | 38 | /* The GCC atomic instrinsics are available as of GCC 4.1.0. */ 39 | 40 | #if CORK_CONFIG_GCC_VERSION >= 40100 41 | #define CORK_CONFIG_HAVE_GCC_ATOMICS 1 42 | #else 43 | #define CORK_CONFIG_HAVE_GCC_ATOMICS 0 44 | #endif 45 | 46 | /* The attributes we want to use are available as of GCC 2.96. */ 47 | 48 | #if CORK_CONFIG_GCC_VERSION >= 29600 49 | #define CORK_CONFIG_HAVE_GCC_ATTRIBUTES 1 50 | #else 51 | #define CORK_CONFIG_HAVE_GCC_ATTRIBUTES 0 52 | #endif 53 | 54 | /* __int128 seems to be available on 64-bit platforms as of GCC 4.6. The 55 | * attribute((mode(TI))) syntax seems to be available as of 4.1. */ 56 | 57 | #if CORK_CONFIG_ARCH_X64 && CORK_CONFIG_GCC_VERSION >= 40600 58 | #define CORK_CONFIG_HAVE_GCC_INT128 1 59 | #else 60 | #define CORK_CONFIG_HAVE_GCC_INT128 0 61 | #endif 62 | 63 | #if CORK_CONFIG_ARCH_X64 && CORK_CONFIG_GCC_VERSION >= 40100 64 | #define CORK_CONFIG_HAVE_GCC_MODE_ATTRIBUTE 1 65 | #else 66 | #define CORK_CONFIG_HAVE_GCC_MODE_ATTRIBUTE 0 67 | #endif 68 | 69 | /* Statement expressions have been available since GCC 3.1. */ 70 | 71 | #if CORK_CONFIG_GCC_VERSION >= 30100 72 | #define CORK_CONFIG_HAVE_GCC_STATEMENT_EXPRS 1 73 | #else 74 | #define CORK_CONFIG_HAVE_GCC_STATEMENT_EXPRS 0 75 | #endif 76 | 77 | /* Thread-local storage has been available since GCC 3.3, but not on Mac 78 | * OS X. */ 79 | 80 | #if !(defined(__APPLE__) && defined(__MACH__)) 81 | #if CORK_CONFIG_GCC_VERSION >= 30300 82 | #define CORK_CONFIG_HAVE_THREAD_STORAGE_CLASS 1 83 | #else 84 | #define CORK_CONFIG_HAVE_THREAD_STORAGE_CLASS 0 85 | #endif 86 | #else 87 | #define CORK_CONFIG_HAVE_THREAD_STORAGE_CLASS 0 88 | #endif 89 | 90 | 91 | #endif /* LIBCORK_CONFIG_GCC_H */ 92 | -------------------------------------------------------------------------------- /include/libcork/config/linux.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CONFIG_LINUX_H 12 | #define LIBCORK_CONFIG_LINUX_H 13 | 14 | /*----------------------------------------------------------------------- 15 | * Endianness 16 | */ 17 | 18 | #include 19 | 20 | #if __BYTE_ORDER == __BIG_ENDIAN 21 | #define CORK_CONFIG_IS_BIG_ENDIAN 1 22 | #define CORK_CONFIG_IS_LITTLE_ENDIAN 0 23 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 24 | #define CORK_CONFIG_IS_BIG_ENDIAN 0 25 | #define CORK_CONFIG_IS_LITTLE_ENDIAN 1 26 | #else 27 | #error "Cannot determine system endianness" 28 | #endif 29 | 30 | #define CORK_HAVE_REALLOCF 0 31 | #define CORK_HAVE_PTHREADS 1 32 | 33 | 34 | #endif /* LIBCORK_CONFIG_LINUX_H */ 35 | -------------------------------------------------------------------------------- /include/libcork/config/macosx.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CONFIG_MACOSX_H 12 | #define LIBCORK_CONFIG_MACOSX_H 13 | 14 | /*----------------------------------------------------------------------- 15 | * Endianness 16 | */ 17 | 18 | #include 19 | 20 | #if BYTE_ORDER == BIG_ENDIAN 21 | #define CORK_CONFIG_IS_BIG_ENDIAN 1 22 | #define CORK_CONFIG_IS_LITTLE_ENDIAN 0 23 | #elif BYTE_ORDER == LITTLE_ENDIAN 24 | #define CORK_CONFIG_IS_BIG_ENDIAN 0 25 | #define CORK_CONFIG_IS_LITTLE_ENDIAN 1 26 | #else 27 | #error "Cannot determine system endianness" 28 | #endif 29 | 30 | #define CORK_HAVE_REALLOCF 1 31 | #define CORK_HAVE_PTHREADS 1 32 | 33 | 34 | #endif /* LIBCORK_CONFIG_MACOSX_H */ 35 | -------------------------------------------------------------------------------- /include/libcork/config/version.h.in: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2015, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CONFIG_VERSION_H 11 | #define LIBCORK_CONFIG_VERSION_H 12 | 13 | 14 | /*----------------------------------------------------------------------- 15 | * Library version 16 | */ 17 | 18 | #define CORK_CONFIG_VERSION_MAJOR @VERSION_MAJOR@ 19 | #define CORK_CONFIG_VERSION_MINOR @VERSION_MINOR@ 20 | #define CORK_CONFIG_VERSION_PATCH @VERSION_PATCH@ 21 | #define CORK_CONFIG_VERSION_STRING "@VERSION@" 22 | #define CORK_CONFIG_REVISION "@GIT_SHA1@" 23 | 24 | 25 | #endif /* LIBCORK_CONFIG_VERSION_H */ 26 | -------------------------------------------------------------------------------- /include/libcork/core.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORE_H 11 | #define LIBCORK_CORE_H 12 | 13 | /*** include all of the parts ***/ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #endif /* LIBCORK_CORE_H */ 30 | -------------------------------------------------------------------------------- /include/libcork/core/api.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012-2015, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORE_API_H 11 | #define LIBCORK_CORE_API_H 12 | 13 | #include 14 | #include 15 | 16 | 17 | /*----------------------------------------------------------------------- 18 | * Calling conventions 19 | */ 20 | 21 | /* If you're using libcork as a shared library, you don't need to do anything 22 | * special; the following will automatically set things up so that libcork's 23 | * public symbols are imported from the library. When we build the shared 24 | * library, we define this ourselves to export the symbols. */ 25 | 26 | #if !defined(CORK_API) 27 | #define CORK_API CORK_IMPORT 28 | #endif 29 | 30 | 31 | /*----------------------------------------------------------------------- 32 | * Library version 33 | */ 34 | 35 | #define CORK_VERSION_MAJOR CORK_CONFIG_VERSION_MAJOR 36 | #define CORK_VERSION_MINOR CORK_CONFIG_VERSION_MINOR 37 | #define CORK_VERSION_PATCH CORK_CONFIG_VERSION_PATCH 38 | 39 | #define CORK_MAKE_VERSION(major, minor, patch) \ 40 | ((major * 1000000) + (minor * 1000) + patch) 41 | 42 | #define CORK_VERSION \ 43 | CORK_MAKE_VERSION(CORK_VERSION_MAJOR, \ 44 | CORK_VERSION_MINOR, \ 45 | CORK_VERSION_PATCH) 46 | 47 | CORK_API const char * 48 | cork_version_string(void) 49 | CORK_ATTR_CONST; 50 | 51 | CORK_API const char * 52 | cork_revision_string(void) 53 | CORK_ATTR_CONST; 54 | 55 | 56 | #endif /* LIBCORK_CORE_API_H */ 57 | -------------------------------------------------------------------------------- /include/libcork/core/attributes.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CORE_ATTRIBUTES_H 12 | #define LIBCORK_CORE_ATTRIBUTES_H 13 | 14 | #include 15 | 16 | 17 | /* 18 | * Declare a “const” function. 19 | * 20 | * A const function is one whose return value depends only on its 21 | * parameters. This is slightly more strict than a “pure” function; a 22 | * const function is not allowed to read from global variables, whereas 23 | * a pure function is. 24 | * 25 | * int square(int x) CORK_ATTR_CONST; 26 | */ 27 | 28 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 29 | #define CORK_ATTR_CONST __attribute__((const)) 30 | #else 31 | #define CORK_ATTR_CONST 32 | #endif 33 | 34 | 35 | /* 36 | * Declare a “pure” function. 37 | * 38 | * A pure function is one whose return value depends only on its 39 | * parameters, and global variables. 40 | * 41 | * int square(int x) CORK_ATTR_PURE; 42 | */ 43 | 44 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 45 | #define CORK_ATTR_PURE __attribute__((pure)) 46 | #else 47 | #define CORK_ATTR_PURE 48 | #endif 49 | 50 | 51 | /* 52 | * Declare that a function returns a newly allocated pointer. 53 | * 54 | * The compiler can use this information to generate more accurate 55 | * aliasing information, since it can infer that the result of the 56 | * function cannot alias any other existing pointer. 57 | */ 58 | 59 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 60 | #define CORK_ATTR_MALLOC __attribute__((malloc)) 61 | #else 62 | #define CORK_ATTR_MALLOC 63 | #endif 64 | 65 | 66 | /* 67 | * Declare that a function shouldn't be inlined. 68 | */ 69 | 70 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 71 | #define CORK_ATTR_NOINLINE __attribute__((noinline)) 72 | #else 73 | #define CORK_ATTR_NOINLINE 74 | #endif 75 | 76 | 77 | /* 78 | * Declare an entity that isn't used. 79 | * 80 | * This lets you keep -Wall activated in several cases where you're 81 | * obligated to define something that you don't intend to use. 82 | */ 83 | 84 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 85 | #define CORK_ATTR_UNUSED __attribute__((unused)) 86 | #else 87 | #define CORK_ATTR_UNUSED 88 | #endif 89 | 90 | 91 | /* 92 | * Declare a function that takes in printf-like parameters. 93 | * 94 | * When the compiler supports this attribute, it will check the format 95 | * string, and the following arguments, to make sure that they match. 96 | * format_index and args_index are 1-based. 97 | */ 98 | 99 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 100 | #define CORK_ATTR_PRINTF(format_index, args_index) \ 101 | __attribute__((format(printf, format_index, args_index))) 102 | #else 103 | #define CORK_ATTR_PRINTF(format_index, args_index) 104 | #endif 105 | 106 | 107 | /* 108 | * Declare a var-arg function whose last parameter must be a NULL 109 | * sentinel value. 110 | * 111 | * When the compiler supports this attribute, it will check the actual 112 | * parameters whenever this function is called, and ensure that the last 113 | * parameter is a @c NULL. 114 | */ 115 | 116 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 117 | #define CORK_ATTR_SENTINEL __attribute__((sentinel)) 118 | #else 119 | #define CORK_ATTR_SENTINEL 120 | #endif 121 | 122 | 123 | /* 124 | * Declare that a boolean expression is likely to be true or false. 125 | */ 126 | 127 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 128 | #define CORK_LIKELY(expr) __builtin_expect((expr), 1) 129 | #define CORK_UNLIKELY(expr) __builtin_expect((expr), 0) 130 | #else 131 | #define CORK_LIKELY(expr) (expr) 132 | #define CORK_UNLIKELY(expr) (expr) 133 | #endif 134 | 135 | /* 136 | * Declare that a function is part of the current library's public API, or that 137 | * it's internal to the current library. 138 | */ 139 | 140 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 141 | #define CORK_EXPORT __attribute__((visibility("default"))) 142 | #define CORK_IMPORT __attribute__((visibility("default"))) 143 | #define CORK_LOCAL __attribute__((visibility("hidden"))) 144 | #else 145 | #define CORK_EXPORT 146 | #define CORK_IMPORT 147 | #define CORK_LOCAL 148 | #endif 149 | 150 | 151 | /* 152 | * Declare a static function that should automatically be called at program 153 | * startup. 154 | */ 155 | 156 | /* TODO: When we implement a full Windows port, [1] describes how best to 157 | * implement an initialization function under Visual Studio. 158 | * 159 | * [1] http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc 160 | */ 161 | 162 | #if CORK_CONFIG_HAVE_GCC_ATTRIBUTES 163 | #define CORK_INITIALIZER(name) \ 164 | __attribute__((constructor)) \ 165 | static void \ 166 | name(void) 167 | #else 168 | #error "Don't know how to implement initialization functions of this platform" 169 | #endif 170 | 171 | 172 | #endif /* LIBCORK_CORE_ATTRIBUTES_H */ 173 | -------------------------------------------------------------------------------- /include/libcork/core/callbacks.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORE_CALLBACKS_H 11 | #define LIBCORK_CORE_CALLBACKS_H 12 | 13 | 14 | #include 15 | 16 | 17 | typedef int 18 | (*cork_copy_f)(void *user_data, void *dest, const void *src); 19 | 20 | typedef void 21 | (*cork_done_f)(void *user_data, void *value); 22 | 23 | typedef void 24 | (*cork_free_f)(void *value); 25 | 26 | typedef cork_hash 27 | (*cork_hash_f)(void *user_data, const void *value); 28 | 29 | typedef bool 30 | (*cork_equals_f)(void *user_data, const void *value1, const void *value2); 31 | 32 | typedef void 33 | (*cork_init_f)(void *user_data, void *value); 34 | 35 | #define cork_free_user_data(parent) \ 36 | ((parent)->free_user_data == NULL? (void) 0: \ 37 | (parent)->free_user_data((parent)->user_data)) 38 | 39 | typedef void * 40 | (*cork_new_f)(void *user_data); 41 | 42 | typedef int 43 | (*cork_run_f)(void *user_data); 44 | 45 | 46 | #endif /* LIBCORK_CORE_CALLBACKS_H */ 47 | -------------------------------------------------------------------------------- /include/libcork/core/error.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORE_ERROR_H 11 | #define LIBCORK_CORE_ERROR_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | /* Should be a hash of a string representing the error code. */ 24 | typedef uint32_t cork_error; 25 | 26 | /* An error code that represents “no error”. */ 27 | #define CORK_ERROR_NONE ((cork_error) 0) 28 | 29 | CORK_API bool 30 | cork_error_occurred(void); 31 | 32 | CORK_API cork_error 33 | cork_error_code(void); 34 | 35 | CORK_API const char * 36 | cork_error_message(void); 37 | 38 | 39 | CORK_API void 40 | cork_error_clear(void); 41 | 42 | CORK_API void 43 | cork_error_set_printf(cork_error code, const char *format, ...) 44 | CORK_ATTR_PRINTF(2,3); 45 | 46 | CORK_API void 47 | cork_error_set_string(cork_error code, const char *str); 48 | 49 | CORK_API void 50 | cork_error_set_vprintf(cork_error code, const char *format, va_list args) 51 | CORK_ATTR_PRINTF(2,0); 52 | 53 | CORK_API void 54 | cork_error_prefix_printf(const char *format, ...) 55 | CORK_ATTR_PRINTF(1,2); 56 | 57 | CORK_API void 58 | cork_error_prefix_string(const char *str); 59 | 60 | CORK_API void 61 | cork_error_prefix_vprintf(const char *format, va_list arg) 62 | CORK_ATTR_PRINTF(1,0); 63 | 64 | 65 | /* deprecated */ 66 | CORK_API void 67 | cork_error_set(uint32_t error_class, unsigned int error_code, 68 | const char *format, ...) 69 | CORK_ATTR_PRINTF(3,4); 70 | 71 | /* deprecated */ 72 | CORK_API void 73 | cork_error_prefix(const char *format, ...) 74 | CORK_ATTR_PRINTF(1,2); 75 | 76 | 77 | /*----------------------------------------------------------------------- 78 | * Built-in errors 79 | */ 80 | 81 | #define CORK_PARSE_ERROR 0x95dfd3c8 82 | #define CORK_REDEFINED 0x171629cb 83 | #define CORK_UNDEFINED 0xedc3d7d9 84 | #define CORK_UNKNOWN_ERROR 0x8cb0880d 85 | 86 | #define cork_parse_error(...) \ 87 | cork_error_set_printf(CORK_PARSE_ERROR, __VA_ARGS__) 88 | #define cork_redefined(...) \ 89 | cork_error_set_printf(CORK_REDEFINED, __VA_ARGS__) 90 | #define cork_undefined(...) \ 91 | cork_error_set_printf(CORK_UNDEFINED, __VA_ARGS__) 92 | 93 | CORK_API void 94 | cork_system_error_set(void); 95 | 96 | CORK_API void 97 | cork_system_error_set_explicit(int err); 98 | 99 | CORK_API void 100 | cork_unknown_error_set_(const char *location); 101 | 102 | #define cork_unknown_error() \ 103 | cork_unknown_error_set_(__func__) 104 | 105 | 106 | /*----------------------------------------------------------------------- 107 | * Abort on failure 108 | */ 109 | 110 | #define cork_abort_(func, file, line, fmt, ...) \ 111 | do { \ 112 | fprintf(stderr, fmt "\n in %s (%s:%u)\n", \ 113 | __VA_ARGS__, (func), (file), (unsigned int) (line)); \ 114 | abort(); \ 115 | } while (0) 116 | 117 | #define cork_abort(fmt, ...) \ 118 | cork_abort_(__func__, __FILE__, __LINE__, fmt, __VA_ARGS__) 119 | 120 | CORK_ATTR_UNUSED 121 | static void * 122 | cork_abort_if_null_(void *ptr, const char *msg, const char *func, 123 | const char *file, unsigned int line) 124 | { 125 | if (CORK_UNLIKELY(ptr == NULL)) { 126 | cork_abort_(func, file, line, "%s", msg); 127 | } else { 128 | return ptr; 129 | } 130 | } 131 | 132 | #define cork_abort_if_null(ptr, msg) \ 133 | (cork_abort_if_null_(ptr, msg, __func__, __FILE__, __LINE__)) 134 | 135 | #define cork_unreachable() \ 136 | cork_abort("%s", "Code should not be reachable") 137 | 138 | 139 | #endif /* LIBCORK_CORE_ERROR_H */ 140 | -------------------------------------------------------------------------------- /include/libcork/core/gc.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_GC_REFCOUNT_H 12 | #define LIBCORK_GC_REFCOUNT_H 13 | 14 | 15 | #include 16 | #include 17 | 18 | 19 | struct cork_gc; 20 | 21 | /* A callback for recursing through the children of a garbage-collected 22 | * object. */ 23 | typedef void 24 | (*cork_gc_recurser)(struct cork_gc *gc, void *obj, void *ud); 25 | 26 | typedef void 27 | (*cork_gc_free_func)(void *obj); 28 | 29 | typedef void 30 | (*cork_gc_recurse_func)(struct cork_gc *gc, void *self, 31 | cork_gc_recurser recurser, void *ud); 32 | 33 | /* An interface that each garbage-collected object must implement. */ 34 | struct cork_gc_obj_iface { 35 | /* Perform additional cleanup; does *NOT* need to deallocate the 36 | * object itself, or release any child references */ 37 | cork_gc_free_func free; 38 | cork_gc_recurse_func recurse; 39 | }; 40 | 41 | 42 | CORK_API void 43 | cork_gc_init(void); 44 | 45 | CORK_API void 46 | cork_gc_done(void); 47 | 48 | 49 | CORK_API void * 50 | cork_gc_alloc(size_t instance_size, struct cork_gc_obj_iface *iface); 51 | 52 | #define cork_gc_new_iface(obj_type, iface) \ 53 | ((obj_type *) \ 54 | (cork_gc_alloc(sizeof(obj_type), (iface)))) 55 | 56 | #define cork_gc_new(struct_name) \ 57 | (cork_gc_new_iface(struct struct_name, &struct_name##__gc)) 58 | 59 | 60 | CORK_API void * 61 | cork_gc_incref(void *obj); 62 | 63 | CORK_API void 64 | cork_gc_decref(void *obj); 65 | 66 | 67 | #endif /* LIBCORK_GC_REFCOUNT_H */ 68 | -------------------------------------------------------------------------------- /include/libcork/core/id.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORE_ID_H 11 | #define LIBCORK_CORE_ID_H 12 | 13 | #include 14 | 15 | 16 | struct cork_uid { 17 | const char *name; 18 | }; 19 | 20 | typedef const struct cork_uid *cork_uid; 21 | 22 | #define CORK_UID_NONE ((cork_uid) NULL) 23 | 24 | #define cork_uid_define_named(c_name, name) \ 25 | static const struct cork_uid c_name##__id = { name }; \ 26 | static cork_uid c_name = &c_name##__id; 27 | #define cork_uid_define(c_name) \ 28 | cork_uid_define_named(c_name, #c_name) 29 | 30 | #define cork_uid_equal(id1, id2) ((id1) == (id2)) 31 | #define cork_uid_hash(id) ((cork_hash) (uintptr_t) (id)) 32 | #define cork_uid_name(id) ((id)->name) 33 | 34 | 35 | #endif /* LIBCORK_CORE_ID_H */ 36 | -------------------------------------------------------------------------------- /include/libcork/core/mempool.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012-2015, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORK_MEMPOOL_H 11 | #define LIBCORK_CORK_MEMPOOL_H 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | #define CORK_MEMPOOL_DEFAULT_BLOCK_SIZE 4096 22 | 23 | 24 | struct cork_mempool; 25 | 26 | 27 | CORK_API struct cork_mempool * 28 | cork_mempool_new_size_ex(size_t element_size, size_t block_size); 29 | 30 | #define cork_mempool_new_size(element_size) \ 31 | (cork_mempool_new_size_ex \ 32 | ((element_size), CORK_MEMPOOL_DEFAULT_BLOCK_SIZE)) 33 | 34 | #define cork_mempool_new_ex(type, block_size) \ 35 | (cork_mempool_new_size_ex(sizeof(type), (block_size))) 36 | 37 | #define cork_mempool_new(type) \ 38 | (cork_mempool_new_size(sizeof(type))) 39 | 40 | CORK_API void 41 | cork_mempool_free(struct cork_mempool *mp); 42 | 43 | 44 | CORK_API void 45 | cork_mempool_set_user_data(struct cork_mempool *mp, 46 | void *user_data, cork_free_f free_user_data); 47 | 48 | CORK_API void 49 | cork_mempool_set_init_object(struct cork_mempool *mp, cork_init_f init_object); 50 | 51 | CORK_API void 52 | cork_mempool_set_done_object(struct cork_mempool *mp, cork_done_f done_object); 53 | 54 | /* Deprecated; you should now use separate calls to cork_mempool_set_user_data, 55 | * cork_mempool_set_init_object, and cork_mempool_set_done_object. */ 56 | CORK_API void 57 | cork_mempool_set_callbacks(struct cork_mempool *mp, 58 | void *user_data, cork_free_f free_user_data, 59 | cork_init_f init_object, 60 | cork_done_f done_object); 61 | 62 | 63 | CORK_API void * 64 | cork_mempool_new_object(struct cork_mempool *mp); 65 | 66 | 67 | CORK_API void 68 | cork_mempool_free_object(struct cork_mempool *mp, void *ptr); 69 | 70 | 71 | #endif /* LIBCORK_CORK_MEMPOOL_H */ 72 | -------------------------------------------------------------------------------- /include/libcork/core/net-addresses.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_CORE_NET_ADDRESSES_H 11 | #define LIBCORK_CORE_NET_ADDRESSES_H 12 | 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | /*----------------------------------------------------------------------- 22 | * IP addresses 23 | */ 24 | 25 | struct cork_ipv4 { 26 | union { 27 | uint8_t u8[4]; 28 | uint16_t u16[2]; 29 | uint32_t u32; 30 | } _; 31 | }; 32 | 33 | struct cork_ipv6 { 34 | union { 35 | uint8_t u8[16]; 36 | uint16_t u16[8]; 37 | uint32_t u32[4]; 38 | uint64_t u64[2]; 39 | } _; 40 | }; 41 | 42 | struct cork_ip { 43 | /* Which version of IP address this is. */ 44 | unsigned int version; 45 | union { 46 | struct cork_ipv4 v4; 47 | struct cork_ipv6 v6; 48 | } ip; 49 | }; 50 | 51 | 52 | #define CORK_IPV4_STRING_LENGTH (sizeof "xxx.xxx.xxx.xxx") 53 | #define CORK_IPV6_STRING_LENGTH \ 54 | (sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") 55 | #define CORK_IP_STRING_LENGTH CORK_IPV6_STRING_LENGTH 56 | 57 | 58 | /*** IPv4 ***/ 59 | 60 | /* src must be well-formed: 4 bytes, big-endian */ 61 | #define cork_ipv4_copy(addr, src) \ 62 | (memcpy((addr), (src), sizeof(struct cork_ipv4))) 63 | 64 | #define cork_ipv4_equal(a1, a2) \ 65 | ((a1)->_.u32 == (a2)->_.u32) 66 | 67 | CORK_API int 68 | cork_ipv4_init(struct cork_ipv4 *addr, const char *str); 69 | 70 | CORK_API bool 71 | cork_ipv4_equal_(const struct cork_ipv4 *addr1, const struct cork_ipv4 *addr2); 72 | 73 | CORK_API void 74 | cork_ipv4_to_raw_string(const struct cork_ipv4 *addr, char *dest); 75 | 76 | CORK_API bool 77 | cork_ipv4_is_valid_network(const struct cork_ipv4 *addr, 78 | unsigned int cidr_prefix); 79 | 80 | 81 | /*** IPv6 ***/ 82 | 83 | /* src must be well-formed: 16 bytes, big-endian */ 84 | #define cork_ipv6_copy(addr, src) \ 85 | (memcpy((addr), (src), sizeof(struct cork_ipv6))) 86 | 87 | #define cork_ipv6_equal(a1, a2) \ 88 | ((a1)->_.u64[0] == (a2)->_.u64[0] && \ 89 | (a1)->_.u64[1] == (a2)->_.u64[1]) 90 | 91 | CORK_API int 92 | cork_ipv6_init(struct cork_ipv6 *addr, const char *str); 93 | 94 | CORK_API bool 95 | cork_ipv6_equal_(const struct cork_ipv6 *addr1, const struct cork_ipv6 *addr2); 96 | 97 | CORK_API void 98 | cork_ipv6_to_raw_string(const struct cork_ipv6 *addr, char *dest); 99 | 100 | CORK_API bool 101 | cork_ipv6_is_valid_network(const struct cork_ipv6 *addr, 102 | unsigned int cidr_prefix); 103 | 104 | 105 | /*** Generic IP ***/ 106 | 107 | #define cork_ip_equal(a1, a2) \ 108 | ((a1)->version == 4? \ 109 | ((a2)->version == 4 && cork_ipv4_equal(&(a1)->ip.v4, &(a2)->ip.v4)): \ 110 | ((a2)->version == 6 && cork_ipv6_equal(&(a1)->ip.v6, &(a2)->ip.v6))) 111 | 112 | /* src must be well-formed: 4 bytes, big-endian */ 113 | #define cork_ip_from_ipv4(addr, src) \ 114 | do { \ 115 | (addr)->version = 4; \ 116 | cork_ipv4_copy(&(addr)->ip.v4, (src)); \ 117 | } while (0) 118 | 119 | /* src must be well-formed: 16 bytes, big-endian */ 120 | #define cork_ip_from_ipv6(addr, src) \ 121 | do { \ 122 | (addr)->version = 6; \ 123 | cork_ipv6_copy(&(addr)->ip.v6, (src)); \ 124 | } while (0) 125 | 126 | /* src must be well-formed: 4 bytes, big-endian */ 127 | CORK_API void 128 | cork_ip_from_ipv4_(struct cork_ip *addr, const void *src); 129 | 130 | /* src must be well-formed: 16 bytes, big-endian */ 131 | CORK_API void 132 | cork_ip_from_ipv6_(struct cork_ip *addr, const void *src); 133 | 134 | CORK_API int 135 | cork_ip_init(struct cork_ip *addr, const char *str); 136 | 137 | CORK_API bool 138 | cork_ip_equal_(const struct cork_ip *addr1, const struct cork_ip *addr2); 139 | 140 | CORK_API void 141 | cork_ip_to_raw_string(const struct cork_ip *addr, char *dest); 142 | 143 | CORK_API bool 144 | cork_ip_is_valid_network(const struct cork_ip *addr, unsigned int cidr_prefix); 145 | 146 | 147 | #endif /* LIBCORK_CORE_NET_ADDRESSES_H */ 148 | -------------------------------------------------------------------------------- /include/libcork/core/timestamp.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CORE_TIMESTAMP_H 12 | #define LIBCORK_CORE_TIMESTAMP_H 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | typedef uint64_t cork_timestamp; 22 | 23 | 24 | #define cork_timestamp_init_sec(ts, sec) \ 25 | do { \ 26 | *(ts) = (((uint64_t) (sec)) << 32); \ 27 | } while (0) 28 | 29 | #define cork_timestamp_init_gsec(ts, sec, gsec) \ 30 | do { \ 31 | *(ts) = (((uint64_t) (sec)) << 32) | \ 32 | (((uint64_t) (gsec)) & 0xffffffff); \ 33 | } while (0) 34 | 35 | #define cork_timestamp_init_msec(ts, sec, msec) \ 36 | do { \ 37 | *(ts) = (((uint64_t) (sec)) << 32) | \ 38 | ((((uint64_t) (msec)) << 32) / 1000); \ 39 | } while (0) 40 | 41 | #define cork_timestamp_init_usec(ts, sec, usec) \ 42 | do { \ 43 | *(ts) = (((uint64_t) (sec)) << 32) | \ 44 | ((((uint64_t) (usec)) << 32) / 1000000); \ 45 | } while (0) 46 | 47 | #define cork_timestamp_init_nsec(ts, sec, nsec) \ 48 | do { \ 49 | *(ts) = (((uint64_t) (sec)) << 32) | \ 50 | ((((uint64_t) (nsec)) << 32) / 1000000000); \ 51 | } while (0) 52 | 53 | 54 | CORK_API void 55 | cork_timestamp_init_now(cork_timestamp *ts); 56 | 57 | 58 | #define cork_timestamp_sec(ts) ((uint32_t) ((ts) >> 32)) 59 | #define cork_timestamp_gsec(ts) ((uint32_t) ((ts) & 0xffffffff)) 60 | 61 | CORK_ATTR_UNUSED 62 | static inline uint64_t 63 | cork_timestamp_gsec_to_units(const cork_timestamp ts, uint64_t denom) 64 | { 65 | uint64_t half = ((uint64_t) 1 << 31) / denom; 66 | uint64_t gsec = cork_timestamp_gsec(ts); 67 | gsec += half; 68 | gsec *= denom; 69 | gsec >>= 32; 70 | return gsec; 71 | } 72 | 73 | #define cork_timestamp_msec(ts) cork_timestamp_gsec_to_units(ts, 1000) 74 | #define cork_timestamp_usec(ts) cork_timestamp_gsec_to_units(ts, 1000000) 75 | #define cork_timestamp_nsec(ts) cork_timestamp_gsec_to_units(ts, 1000000000) 76 | 77 | 78 | CORK_API int 79 | cork_timestamp_format_utc(const cork_timestamp ts, const char *format, 80 | struct cork_buffer *dest); 81 | 82 | CORK_API int 83 | cork_timestamp_format_local(const cork_timestamp ts, const char *format, 84 | struct cork_buffer *dest); 85 | 86 | 87 | #endif /* LIBCORK_CORE_TIMESTAMP_H */ 88 | -------------------------------------------------------------------------------- /include/libcork/core/types.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CORE_TYPES_H 12 | #define LIBCORK_CORE_TYPES_H 13 | 14 | /* For now, we assume that the C99 integer types are available using the 15 | * standard headers. */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | /* Define preprocessor macros that contain the size of several built-in 25 | * types. Again, we assume that we have the C99 definitions available. */ 26 | 27 | #if SHRT_MAX == INT8_MAX 28 | #define CORK_SIZEOF_SHORT 1 29 | #elif SHRT_MAX == INT16_MAX 30 | #define CORK_SIZEOF_SHORT 2 31 | #elif SHRT_MAX == INT32_MAX 32 | #define CORK_SIZEOF_SHORT 4 33 | #elif SHRT_MAX == INT64_MAX 34 | #define CORK_SIZEOF_SHORT 8 35 | #else 36 | #error "Cannot determine size of short" 37 | #endif 38 | 39 | #if INT_MAX == INT8_MAX 40 | #define CORK_SIZEOF_INT 1 41 | #elif INT_MAX == INT16_MAX 42 | #define CORK_SIZEOF_INT 2 43 | #elif INT_MAX == INT32_MAX 44 | #define CORK_SIZEOF_INT 4 45 | #elif INT_MAX == INT64_MAX 46 | #define CORK_SIZEOF_INT 8 47 | #else 48 | #error "Cannot determine size of int" 49 | #endif 50 | 51 | #if LONG_MAX == INT8_MAX 52 | #define CORK_SIZEOF_LONG 1 53 | #elif LONG_MAX == INT16_MAX 54 | #define CORK_SIZEOF_LONG 2 55 | #elif LONG_MAX == INT32_MAX 56 | #define CORK_SIZEOF_LONG 4 57 | #elif LONG_MAX == INT64_MAX 58 | #define CORK_SIZEOF_LONG 8 59 | #else 60 | #error "Cannot determine size of long" 61 | #endif 62 | 63 | #if INTPTR_MAX == INT8_MAX 64 | #define CORK_SIZEOF_POINTER 1 65 | #elif INTPTR_MAX == INT16_MAX 66 | #define CORK_SIZEOF_POINTER 2 67 | #elif INTPTR_MAX == INT32_MAX 68 | #define CORK_SIZEOF_POINTER 4 69 | #elif INTPTR_MAX == INT64_MAX 70 | #define CORK_SIZEOF_POINTER 8 71 | #else 72 | #error "Cannot determine size of void *" 73 | #endif 74 | 75 | 76 | /* Return a pointer to a @c struct, given a pointer to one of its 77 | * fields. */ 78 | #define cork_container_of(field, struct_type, field_name) \ 79 | ((struct_type *) (- offsetof(struct_type, field_name) + \ 80 | (void *) (field))) 81 | 82 | #endif /* LIBCORK_CORE_TYPES_H */ 83 | -------------------------------------------------------------------------------- /include/libcork/ds.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_DS_H 12 | #define LIBCORK_DS_H 13 | 14 | /*** include all of the parts ***/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #endif /* LIBCORK_DS_H */ 27 | -------------------------------------------------------------------------------- /include/libcork/ds/bitset.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_DS_BITS_H 11 | #define LIBCORK_DS_BITS_H 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | /*----------------------------------------------------------------------- 19 | * Bit sets 20 | */ 21 | 22 | struct cork_bitset { 23 | uint8_t *bits; 24 | size_t bit_count; 25 | size_t byte_count; 26 | }; 27 | 28 | CORK_API struct cork_bitset * 29 | cork_bitset_new(size_t bit_count); 30 | 31 | CORK_API void 32 | cork_bitset_init(struct cork_bitset *set, size_t bit_count); 33 | 34 | CORK_API void 35 | cork_bitset_free(struct cork_bitset *set); 36 | 37 | CORK_API void 38 | cork_bitset_done(struct cork_bitset *set); 39 | 40 | CORK_API void 41 | cork_bitset_clear(struct cork_bitset *set); 42 | 43 | /* Extract the byte that contains a particular bit in an array. */ 44 | #define cork_bitset_byte_for_bit(set, i) \ 45 | ((set)->bits[(i) / 8]) 46 | 47 | /* Create a bit mask that extracts a particular bit from the byte that it lives 48 | * in. */ 49 | #define cork_bitset_pos_mask_for_bit(i) \ 50 | (0x80 >> ((i) % 8)) 51 | 52 | /* Create a bit mask that extracts everything except for a particular bit from 53 | * the byte that it lives in. */ 54 | #define cork_bitset_neg_mask_for_bit(i) \ 55 | (~cork_bitset_pos_mask_for_bit(i)) 56 | 57 | /* Return whether a particular bit is set in a byte array. Bits are numbered 58 | * from 0, in a big-endian order. */ 59 | #define cork_bitset_get(set, i) \ 60 | ((cork_bitset_byte_for_bit(set, i) & cork_bitset_pos_mask_for_bit(i)) != 0) 61 | 62 | /* Set (or unset) a particular bit is set in a byte array. Bits are numbered 63 | * from 0, in a big-endian order. */ 64 | #define cork_bitset_set(set, i, val) \ 65 | (cork_bitset_byte_for_bit(set, i) = \ 66 | (cork_bitset_byte_for_bit(set, i) & cork_bitset_neg_mask_for_bit(i)) \ 67 | | ((val)? cork_bitset_pos_mask_for_bit(i): 0)) 68 | 69 | 70 | #endif /* LIBCORK_DS_BITS_H */ 71 | -------------------------------------------------------------------------------- /include/libcork/ds/buffer.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_DS_BUFFER_H 12 | #define LIBCORK_DS_BUFFER_H 13 | 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | struct cork_buffer { 23 | /* The current contents of the buffer. */ 24 | void *buf; 25 | /* The current size of the buffer. */ 26 | size_t size; 27 | /* The amount of space allocated for buf. */ 28 | size_t allocated_size; 29 | }; 30 | 31 | 32 | CORK_API void 33 | cork_buffer_init(struct cork_buffer *buffer); 34 | 35 | #define CORK_BUFFER_INIT() { NULL, 0, 0 } 36 | 37 | CORK_API struct cork_buffer * 38 | cork_buffer_new(void); 39 | 40 | CORK_API void 41 | cork_buffer_done(struct cork_buffer *buffer); 42 | 43 | CORK_API void 44 | cork_buffer_free(struct cork_buffer *buffer); 45 | 46 | 47 | CORK_API bool 48 | cork_buffer_equal(const struct cork_buffer *buffer1, 49 | const struct cork_buffer *buffer2); 50 | 51 | 52 | CORK_API void 53 | cork_buffer_ensure_size(struct cork_buffer *buffer, size_t desired_size); 54 | 55 | 56 | CORK_API void 57 | cork_buffer_clear(struct cork_buffer *buffer); 58 | 59 | CORK_API void 60 | cork_buffer_truncate(struct cork_buffer *buffer, size_t length); 61 | 62 | #define cork_buffer_byte(buffer, i) (((const uint8_t *) (buffer)->buf)[(i)]) 63 | #define cork_buffer_char(buffer, i) (((const char *) (buffer)->buf)[(i)]) 64 | 65 | 66 | /*----------------------------------------------------------------------- 67 | * A whole bunch of methods for adding data 68 | */ 69 | 70 | #define cork_buffer_copy(dest, src) \ 71 | (cork_buffer_set((dest), (src)->buf, (src)->size)) 72 | 73 | CORK_API void 74 | cork_buffer_set(struct cork_buffer *buffer, const void *src, size_t length); 75 | 76 | #define cork_buffer_append_copy(dest, src) \ 77 | (cork_buffer_append((dest), (src)->buf, (src)->size)) 78 | 79 | CORK_API void 80 | cork_buffer_append(struct cork_buffer *buffer, const void *src, size_t length); 81 | 82 | 83 | CORK_API void 84 | cork_buffer_set_string(struct cork_buffer *buffer, const char *str); 85 | 86 | CORK_API void 87 | cork_buffer_append_string(struct cork_buffer *buffer, const char *str); 88 | 89 | #define cork_buffer_set_literal(buffer, str) \ 90 | (cork_buffer_set((buffer), (str), sizeof((str)) - 1)) 91 | 92 | #define cork_buffer_append_literal(buffer, str) \ 93 | (cork_buffer_append((buffer), (str), sizeof((str)) - 1)) 94 | 95 | 96 | CORK_API void 97 | cork_buffer_printf(struct cork_buffer *buffer, const char *format, ...) 98 | CORK_ATTR_PRINTF(2,3); 99 | 100 | CORK_API void 101 | cork_buffer_append_printf(struct cork_buffer *buffer, const char *format, ...) 102 | CORK_ATTR_PRINTF(2,3); 103 | 104 | CORK_API void 105 | cork_buffer_vprintf(struct cork_buffer *buffer, const char *format, 106 | va_list args) 107 | CORK_ATTR_PRINTF(2,0); 108 | 109 | CORK_API void 110 | cork_buffer_append_vprintf(struct cork_buffer *buffer, const char *format, 111 | va_list args) 112 | CORK_ATTR_PRINTF(2,0); 113 | 114 | 115 | /*----------------------------------------------------------------------- 116 | * Some helpers for pretty-printing data 117 | */ 118 | 119 | CORK_API void 120 | cork_buffer_append_indent(struct cork_buffer *buffer, size_t indent); 121 | 122 | CORK_API void 123 | cork_buffer_append_c_string(struct cork_buffer *buffer, 124 | const char *src, size_t length); 125 | 126 | CORK_API void 127 | cork_buffer_append_hex_dump(struct cork_buffer *buffer, size_t indent, 128 | const char *src, size_t length); 129 | 130 | CORK_API void 131 | cork_buffer_append_multiline(struct cork_buffer *buffer, size_t indent, 132 | const char *src, size_t length); 133 | 134 | CORK_API void 135 | cork_buffer_append_binary(struct cork_buffer *buffer, size_t indent, 136 | const char *src, size_t length); 137 | 138 | 139 | /*----------------------------------------------------------------------- 140 | * Buffer's managed buffer/slice implementation 141 | */ 142 | 143 | #include 144 | #include 145 | 146 | CORK_API struct cork_managed_buffer * 147 | cork_buffer_to_managed_buffer(struct cork_buffer *buffer); 148 | 149 | CORK_API int 150 | cork_buffer_to_slice(struct cork_buffer *buffer, struct cork_slice *slice); 151 | 152 | 153 | /*----------------------------------------------------------------------- 154 | * Buffer's stream consumer implementation 155 | */ 156 | 157 | #include 158 | 159 | CORK_API struct cork_stream_consumer * 160 | cork_buffer_to_stream_consumer(struct cork_buffer *buffer); 161 | 162 | 163 | #endif /* LIBCORK_DS_BUFFER_H */ 164 | -------------------------------------------------------------------------------- /include/libcork/ds/managed-buffer.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_DS_MANAGED_BUFFER_H 12 | #define LIBCORK_DS_MANAGED_BUFFER_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | /*----------------------------------------------------------------------- 20 | * Managed buffers 21 | */ 22 | 23 | struct cork_managed_buffer; 24 | 25 | struct cork_managed_buffer_iface { 26 | /* Free the contents of a managed buffer, and the managed buffer 27 | * object itself. */ 28 | void 29 | (*free)(struct cork_managed_buffer *buf); 30 | }; 31 | 32 | 33 | struct cork_managed_buffer { 34 | /* The buffer that this instance manages */ 35 | const void *buf; 36 | /* The size of buf */ 37 | size_t size; 38 | /* A reference count for the buffer. If this drops to 0, the buffer 39 | * will be finalized. */ 40 | volatile int ref_count; 41 | /* The managed buffer implementation for this instance. */ 42 | struct cork_managed_buffer_iface *iface; 43 | }; 44 | 45 | 46 | CORK_API struct cork_managed_buffer * 47 | cork_managed_buffer_new_copy(const void *buf, size_t size); 48 | 49 | 50 | typedef void 51 | (*cork_managed_buffer_freer)(void *buf, size_t size); 52 | 53 | CORK_API struct cork_managed_buffer * 54 | cork_managed_buffer_new(const void *buf, size_t size, 55 | cork_managed_buffer_freer free); 56 | 57 | 58 | CORK_API struct cork_managed_buffer * 59 | cork_managed_buffer_ref(struct cork_managed_buffer *buf); 60 | 61 | CORK_API void 62 | cork_managed_buffer_unref(struct cork_managed_buffer *buf); 63 | 64 | 65 | CORK_API int 66 | cork_managed_buffer_slice(struct cork_slice *dest, 67 | struct cork_managed_buffer *buffer, 68 | size_t offset, size_t length); 69 | 70 | CORK_API int 71 | cork_managed_buffer_slice_offset(struct cork_slice *dest, 72 | struct cork_managed_buffer *buffer, 73 | size_t offset); 74 | 75 | 76 | #endif /* LIBCORK_DS_MANAGED_BUFFER_H */ 77 | -------------------------------------------------------------------------------- /include/libcork/ds/ring-buffer.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_DS_RING_BUFFER_H 12 | #define LIBCORK_DS_RING_BUFFER_H 13 | 14 | #include 15 | #include 16 | 17 | 18 | struct cork_ring_buffer { 19 | /* The elements of the ring buffer */ 20 | void **elements; 21 | /* The number of elements that can be stored in this ring 22 | * buffer. */ 23 | size_t allocated_size; 24 | /* The actual number of elements currently in the ring buffer. */ 25 | size_t size; 26 | /* The index of the next element to read from the buffer */ 27 | size_t read_index; 28 | /* The index of the next element to write into the buffer */ 29 | size_t write_index; 30 | }; 31 | 32 | 33 | CORK_API int 34 | cork_ring_buffer_init(struct cork_ring_buffer *buf, size_t size); 35 | 36 | CORK_API struct cork_ring_buffer * 37 | cork_ring_buffer_new(size_t size); 38 | 39 | CORK_API void 40 | cork_ring_buffer_done(struct cork_ring_buffer *buf); 41 | 42 | CORK_API void 43 | cork_ring_buffer_free(struct cork_ring_buffer *buf); 44 | 45 | 46 | #define cork_ring_buffer_is_empty(buf) ((buf)->size == 0) 47 | #define cork_ring_buffer_is_full(buf) ((buf)->size == (buf)->allocated_size) 48 | 49 | 50 | CORK_API int 51 | cork_ring_buffer_add(struct cork_ring_buffer *buf, void *element); 52 | 53 | CORK_API void * 54 | cork_ring_buffer_pop(struct cork_ring_buffer *buf); 55 | 56 | CORK_API void * 57 | cork_ring_buffer_peek(struct cork_ring_buffer *buf); 58 | 59 | 60 | #endif /* LIBCORK_DS_RING_BUFFER_H */ 61 | -------------------------------------------------------------------------------- /include/libcork/ds/stream.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_DS_STREAM_H 12 | #define LIBCORK_DS_STREAM_H 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | 20 | struct cork_stream_consumer { 21 | int 22 | (*data)(struct cork_stream_consumer *consumer, 23 | const void *buf, size_t size, bool is_first_chunk); 24 | 25 | int 26 | (*eof)(struct cork_stream_consumer *consumer); 27 | 28 | void 29 | (*free)(struct cork_stream_consumer *consumer); 30 | }; 31 | 32 | 33 | #define cork_stream_consumer_data(consumer, buf, size, is_first) \ 34 | ((consumer)->data((consumer), (buf), (size), (is_first))) 35 | 36 | #define cork_stream_consumer_eof(consumer) \ 37 | ((consumer)->eof((consumer))) 38 | 39 | #define cork_stream_consumer_free(consumer) \ 40 | ((consumer)->free((consumer))) 41 | 42 | 43 | CORK_API int 44 | cork_consume_fd(struct cork_stream_consumer *consumer, int fd); 45 | 46 | CORK_API int 47 | cork_consume_file(struct cork_stream_consumer *consumer, FILE *fp); 48 | 49 | CORK_API int 50 | cork_consume_file_from_path(struct cork_stream_consumer *consumer, 51 | const char *path, int flags); 52 | 53 | 54 | CORK_API struct cork_stream_consumer * 55 | cork_fd_consumer_new(int fd); 56 | 57 | CORK_API struct cork_stream_consumer * 58 | cork_file_consumer_new(FILE *fp); 59 | 60 | CORK_API struct cork_stream_consumer * 61 | cork_file_from_path_consumer_new(const char *path, int flags); 62 | 63 | 64 | #endif /* LIBCORK_DS_STREAM_H */ 65 | -------------------------------------------------------------------------------- /include/libcork/helpers/errors.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_HELPERS_ERRORS_H 12 | #define LIBCORK_HELPERS_ERRORS_H 13 | 14 | 15 | /* This header is *not* automatically included when you include 16 | * libcork/core.h, since we define some macros that don't include a 17 | * cork_ or CORK_ prefix. Don't want to pollute your namespace unless 18 | * you ask for it! */ 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | #if !defined(CORK_PRINT_ERRORS) 27 | #define CORK_PRINT_ERRORS 0 28 | #endif 29 | 30 | #if !defined(CORK_PRINT_ERROR) 31 | #if CORK_PRINT_ERRORS 32 | #include 33 | #define CORK_PRINT_ERROR_(func, file, line) \ 34 | fprintf(stderr, "---\nError in %s (%s:%u)\n %s\n", \ 35 | (func), (file), (unsigned int) (line), \ 36 | cork_error_message()); 37 | #define CORK_PRINT_ERROR() CORK_PRINT_ERROR_(__func__, __FILE__, __LINE__) 38 | #else 39 | #define CORK_PRINT_ERROR() /* do nothing */ 40 | #endif 41 | #endif 42 | 43 | 44 | /* A bunch of macros for calling a function that returns an error. If 45 | * an error occurs, it will automatically be propagated out as the 46 | * result of your own function. With these macros, you won't have a 47 | * check to check or modify the error condition; it's returned as-is. 48 | * 49 | * XZ_check 50 | * 51 | * where: 52 | * 53 | * X = what happens if an error occurs 54 | * "e" = jump to the "error" label 55 | * "rY" = return a default error result (Y defined below) 56 | * "x" = return an error result that you specify 57 | * 58 | * Y = your return type 59 | * "i" = int 60 | * "p" = some pointer type 61 | * 62 | * Z = the return type of the function you're calling 63 | * "e" = use cork_error_occurred() to check 64 | * "i" = int 65 | * "p" = some pointer type 66 | * 67 | * In all cases, we assume that your function has a cork_error parameter 68 | * called "err". 69 | */ 70 | 71 | 72 | /* jump to "error" label */ 73 | 74 | #define ee_check(call) \ 75 | do { \ 76 | (call); \ 77 | if (CORK_UNLIKELY(cork_error_occurred())) { \ 78 | CORK_PRINT_ERROR(); \ 79 | goto error; \ 80 | } \ 81 | } while (0) 82 | 83 | #define ei_check(call) \ 84 | do { \ 85 | int __rc = (call); \ 86 | if (CORK_UNLIKELY(__rc != 0)) { \ 87 | CORK_PRINT_ERROR(); \ 88 | goto error; \ 89 | } \ 90 | } while (0) 91 | 92 | #define ep_check(call) \ 93 | do { \ 94 | const void *__result = (call); \ 95 | if (CORK_UNLIKELY(__result == NULL)) { \ 96 | CORK_PRINT_ERROR(); \ 97 | goto error; \ 98 | } \ 99 | } while (0) 100 | 101 | 102 | /* return specific error code */ 103 | 104 | #define xe_check(result, call) \ 105 | do { \ 106 | (call); \ 107 | if (CORK_UNLIKELY(cork_error_occurred())) { \ 108 | CORK_PRINT_ERROR(); \ 109 | return result; \ 110 | } \ 111 | } while (0) 112 | 113 | #define xi_check(result, call) \ 114 | do { \ 115 | int __rc = (call); \ 116 | if (CORK_UNLIKELY(__rc != 0)) { \ 117 | CORK_PRINT_ERROR(); \ 118 | return result; \ 119 | } \ 120 | } while (0) 121 | 122 | #define xp_check(result, call) \ 123 | do { \ 124 | const void *__result = (call); \ 125 | if (CORK_UNLIKELY(__result == NULL)) { \ 126 | CORK_PRINT_ERROR(); \ 127 | return result; \ 128 | } \ 129 | } while (0) 130 | 131 | 132 | /* return default error code */ 133 | 134 | #define rie_check(call) xe_check(-1, call) 135 | #define rii_check(call) xi_check(__rc, call) 136 | #define rip_check(call) xp_check(-1, call) 137 | #define rpe_check(call) xe_check(NULL, call) 138 | #define rpi_check(call) xi_check(NULL, call) 139 | #define rpp_check(call) xp_check(NULL, call) 140 | 141 | 142 | #endif /* LIBCORK_HELPERS_ERRORS_H */ 143 | -------------------------------------------------------------------------------- /include/libcork/helpers/gc.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_HELPERS_REFCOUNT_H 12 | #define LIBCORK_HELPERS_REFCOUNT_H 13 | 14 | 15 | #include 16 | #include 17 | 18 | 19 | #define _free_(name) \ 20 | static void \ 21 | name##__free(void *obj) 22 | 23 | 24 | #define _recurse_(name) \ 25 | static void \ 26 | name##__recurse(struct cork_gc *gc, void *obj, \ 27 | cork_gc_recurser recurse, void *ud) 28 | 29 | 30 | #define _gc_(name) \ 31 | static struct cork_gc_obj_iface name##__gc = { \ 32 | name##__free, name##__recurse \ 33 | }; 34 | 35 | #define _gc_no_free_(name) \ 36 | static struct cork_gc_obj_iface name##__gc = { \ 37 | NULL, name##__recurse \ 38 | }; 39 | 40 | #define _gc_no_recurse_(name) \ 41 | static struct cork_gc_obj_iface name##__gc = { \ 42 | name##__free, NULL \ 43 | }; 44 | 45 | #define _gc_leaf_(name) \ 46 | static struct cork_gc_obj_iface name##__gc = { \ 47 | NULL, NULL \ 48 | }; 49 | 50 | 51 | #endif /* LIBCORK_HELPERS_REFCOUNT_H */ 52 | -------------------------------------------------------------------------------- /include/libcork/helpers/posix.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef LIBCORK_HELPERS_POSIX_H 11 | #define LIBCORK_HELPERS_POSIX_H 12 | 13 | /* This header is *not* automatically included when you include 14 | * libcork/core.h, since we define some macros that don't include a 15 | * cork_ or CORK_ prefix. Don't want to pollute your namespace unless 16 | * you ask for it! */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | #if !defined(CORK_PRINT_ERRORS) 26 | #define CORK_PRINT_ERRORS 0 27 | #endif 28 | 29 | #if !defined(CORK_PRINT_ERROR) 30 | #if CORK_PRINT_ERRORS 31 | #include 32 | #define CORK_PRINT_ERROR_(func, file, line) \ 33 | fprintf(stderr, "---\nError in %s (%s:%u)\n %s\n", \ 34 | (func), (file), (unsigned int) (line), \ 35 | cork_error_message()); 36 | #define CORK_PRINT_ERROR() CORK_PRINT_ERROR_(__func__, __FILE__, __LINE__) 37 | #else 38 | #define CORK_PRINT_ERROR() /* do nothing */ 39 | #endif 40 | #endif 41 | 42 | 43 | #define xi_check_posix(call, on_error) \ 44 | do { \ 45 | while (true) { \ 46 | if ((call) == -1) { \ 47 | if (errno == EINTR) { \ 48 | continue; \ 49 | } else { \ 50 | cork_system_error_set(); \ 51 | CORK_PRINT_ERROR(); \ 52 | on_error; \ 53 | } \ 54 | } else { \ 55 | break; \ 56 | } \ 57 | } \ 58 | } while (0) 59 | 60 | #define xp_check_posix(call, on_error) \ 61 | do { \ 62 | while (true) { \ 63 | if ((call) == NULL) { \ 64 | if (errno == EINTR) { \ 65 | continue; \ 66 | } else { \ 67 | cork_system_error_set(); \ 68 | CORK_PRINT_ERROR(); \ 69 | on_error; \ 70 | } \ 71 | } else { \ 72 | break; \ 73 | } \ 74 | } \ 75 | } while (0) 76 | 77 | 78 | #define ei_check_posix(call) xi_check_posix(call, goto error) 79 | #define rii_check_posix(call) xi_check_posix(call, return -1) 80 | #define rpi_check_posix(call) xi_check_posix(call, return NULL) 81 | 82 | #define ep_check_posix(call) xp_check_posix(call, goto error) 83 | #define rip_check_posix(call) xp_check_posix(call, return -1) 84 | #define rpp_check_posix(call) xp_check_posix(call, return NULL) 85 | 86 | 87 | #endif /* LIBCORK_HELPERS_POSIX_H */ 88 | -------------------------------------------------------------------------------- /include/libcork/os.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012-2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_OS_H 12 | #define LIBCORK_OS_H 13 | 14 | /*** include all of the parts ***/ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #endif /* LIBCORK_OS_H */ 21 | -------------------------------------------------------------------------------- /include/libcork/os/process.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_CORE_PROCESS_H 12 | #define LIBCORK_CORE_PROCESS_H 13 | 14 | #include 15 | 16 | 17 | typedef void 18 | (*cork_cleanup_function)(void); 19 | 20 | CORK_API void 21 | cork_cleanup_at_exit_named(const char *name, int priority, 22 | cork_cleanup_function function); 23 | 24 | #define cork_cleanup_at_exit(priority, function) \ 25 | cork_cleanup_at_exit_named(#function, priority, function) 26 | 27 | 28 | #endif /* LIBCORK_CORE_PROCESS_H */ 29 | -------------------------------------------------------------------------------- /include/libcork/threads.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_THREADS_H 12 | #define LIBCORK_THREADS_H 13 | 14 | /*** include all of the parts ***/ 15 | 16 | #include 17 | #include 18 | 19 | #endif /* LIBCORK_THREADS_H */ 20 | -------------------------------------------------------------------------------- /include/libcork/threads/atomics.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef LIBCORK_THREADS_ATOMICS_H 12 | #define LIBCORK_THREADS_ATOMICS_H 13 | 14 | #include 15 | #include 16 | 17 | /*----------------------------------------------------------------------- 18 | * GCC intrinsics 19 | */ 20 | 21 | /* Ideally we can use GCC's intrinsics to define everything */ 22 | #if defined(CORK_CONFIG_HAVE_GCC_ATOMICS) 23 | 24 | #define cork_int_atomic_add __sync_add_and_fetch 25 | #define cork_uint_atomic_add __sync_add_and_fetch 26 | #define cork_size_atomic_add __sync_add_and_fetch 27 | #define cork_int_atomic_pre_add __sync_fetch_and_add 28 | #define cork_uint_atomic_pre_add __sync_fetch_and_add 29 | #define cork_size_atomic_pre_add __sync_fetch_and_add 30 | #define cork_int_atomic_sub __sync_sub_and_fetch 31 | #define cork_uint_atomic_sub __sync_sub_and_fetch 32 | #define cork_size_atomic_sub __sync_sub_and_fetch 33 | #define cork_int_atomic_pre_sub __sync_fetch_and_sub 34 | #define cork_uint_atomic_pre_sub __sync_fetch_and_sub 35 | #define cork_size_atomic_pre_sub __sync_fetch_and_sub 36 | #define cork_int_cas __sync_val_compare_and_swap 37 | #define cork_uint_cas __sync_val_compare_and_swap 38 | #define cork_size_cas __sync_val_compare_and_swap 39 | #define cork_ptr_cas __sync_val_compare_and_swap 40 | 41 | 42 | /*----------------------------------------------------------------------- 43 | * End of atomic implementations 44 | */ 45 | #else 46 | #error "No atomics implementation!" 47 | #endif 48 | 49 | 50 | #endif /* LIBCORK_THREADS_ATOMICS_H */ 51 | -------------------------------------------------------------------------------- /make-dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PROJECT=libcork 4 | 5 | COMMIT="$1" 6 | if [ -z "$COMMIT" ]; then 7 | COMMIT="HEAD" 8 | fi 9 | 10 | VERSION=$(git describe ${COMMIT}) 11 | git archive --prefix=${PROJECT}-${VERSION}/ --format=tar ${COMMIT} | \ 12 | bzip2 -c > ${PROJECT}-${VERSION}.tar.bz2 13 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Usage: run.sh [debug|release] program arguments 3 | # 4 | # Runs a program from one of the build directories, with 5 | # LD_LIBRARY_PATH set correctly so that it can find all of the shared 6 | # libraries before they're installed. 7 | 8 | 9 | # Check that there are enough command-line parameters. 10 | 11 | if [ $# -lt 1 ]; then 12 | echo "Usage: run.sh [debug|release] program arguments" 13 | exit 1 14 | fi 15 | 16 | 17 | # Verify that the user chose a valid build type. 18 | 19 | BUILD="$1" 20 | shift 21 | 22 | case "$BUILD" in 23 | debug) 24 | ;; 25 | release) 26 | ;; 27 | *) 28 | echo "Unknown build type $BUILD" 29 | exit 1 30 | ;; 31 | esac 32 | 33 | 34 | # Find all of the src subdirectories in the build directory, and use 35 | # those as the LD_LIBRARY_PATH. 36 | 37 | SRC_DIRS=$(find build/$BUILD -name src) 38 | JOINED=$(echo $SRC_DIRS | perl -ne 'print join(":", split)') 39 | 40 | 41 | # Run the desired program, and pass on any command-line arguments 42 | # as-is. 43 | 44 | LD_LIBRARY_PATH="$JOINED:$LD_LIBRARY_PATH" \ 45 | DYLD_LIBRARY_PATH="$JOINED:$DYLD_LIBRARY_PATH" \ 46 | "$@" 47 | -------------------------------------------------------------------------------- /share/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2012, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license 7 | # details. 8 | # ---------------------------------------------------------------------- 9 | 10 | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/valgrind 11 | DESTINATION share 12 | FILES_MATCHING PATTERN "*.supp") 13 | -------------------------------------------------------------------------------- /share/valgrind/libcork.supp: -------------------------------------------------------------------------------- 1 | # Valgrind suppressions for libcork 2 | 3 | { 4 | libcork/cork_gc_get 5 | Memcheck:Leak 6 | fun:calloc 7 | fun:cork_gc_get 8 | } 9 | -------------------------------------------------------------------------------- /src/APPNAME.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | sharedir=${prefix}/share 6 | sphinxdir=${sharedir}/doc/APPNAME/html 7 | 8 | Name: APPNAME 9 | Description: FILL_THIS_IN 10 | Version: @VERSION@ 11 | URL: FILL_THIS_IN 12 | Libs: -L${libdir} -lAPPNAME 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2015, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | #----------------------------------------------------------------------- 10 | # libcork 11 | 12 | # Update the VERSION property below according to the following rules (taken from 13 | # [1]): 14 | # 15 | # VERSION = current.revision.age 16 | # 17 | # 1. Start with a VERSION of `0.0.0` for each shared library. 18 | # 2. Update VERSION only immediately before a public release of your software. 19 | # More frequent updates are unnecessary, and only guarantee that the 20 | # current interface number gets larger faster. 21 | # 3. If the library source code has changed at all since the last update, then 22 | # increment `revision` (`c.r.a` becomes `c.r+1.a`). 23 | # 4. If any interfaces have been added, removed, or changed since the last 24 | # update, increment `current`, and set `revision` to 0. 25 | # 5. If any interfaces have been added since the last public release, then 26 | # increment `age`. 27 | # 6. If any interfaces have been removed or changed since the last public 28 | # release, then set `age` to 0. 29 | # 30 | # Note that changing `current` means that you are releasing a new 31 | # backwards-incompatible version of the library. This has implications on 32 | # packaging, so once an API has stabilized, this should be a rare occurrence. 33 | # 34 | # [1] http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info 35 | 36 | add_c_library( 37 | libcork 38 | OUTPUT_NAME cork 39 | PKGCONFIG_NAME libcork 40 | VERSION 16.0.1 41 | SOURCES 42 | libcork/cli/commands.c 43 | libcork/core/allocator.c 44 | libcork/core/error.c 45 | libcork/core/gc.c 46 | libcork/core/hash.c 47 | libcork/core/ip-address.c 48 | libcork/core/mempool.c 49 | libcork/core/timestamp.c 50 | libcork/core/u128.c 51 | libcork/core/version.c 52 | libcork/ds/array.c 53 | libcork/ds/bitset.c 54 | libcork/ds/buffer.c 55 | libcork/ds/dllist.c 56 | libcork/ds/file-stream.c 57 | libcork/ds/hash-table.c 58 | libcork/ds/managed-buffer.c 59 | libcork/ds/ring-buffer.c 60 | libcork/ds/slice.c 61 | libcork/posix/directory-walker.c 62 | libcork/posix/env.c 63 | libcork/posix/exec.c 64 | libcork/posix/files.c 65 | libcork/posix/process.c 66 | libcork/posix/subprocess.c 67 | libcork/pthreads/thread.c 68 | LIBRARIES 69 | threads 70 | ) 71 | 72 | if (ENABLE_SHARED OR ENABLE_SHARED_EXECUTABLES) 73 | set_target_properties(libcork-shared PROPERTIES 74 | COMPILE_DEFINITIONS CORK_API=CORK_EXPORT 75 | ) 76 | endif (ENABLE_SHARED OR ENABLE_SHARED_EXECUTABLES) 77 | 78 | if (ENABLE_STATIC OR NOT ENABLE_SHARED_EXECUTABLES) 79 | set_target_properties(libcork-static PROPERTIES 80 | COMPILE_DEFINITIONS CORK_API=CORK_LOCAL 81 | ) 82 | endif (ENABLE_STATIC OR NOT ENABLE_SHARED_EXECUTABLES) 83 | 84 | 85 | #----------------------------------------------------------------------- 86 | # Utility commands 87 | 88 | add_c_executable( 89 | cork-hash 90 | OUTPUT_NAME cork-hash 91 | SOURCES cork-hash/cork-hash.c 92 | LOCAL_LIBRARIES 93 | libcork 94 | ) 95 | 96 | add_c_executable( 97 | cork-initializer 98 | SKIP_INSTALL 99 | OUTPUT_NAME cork-initializer 100 | SOURCES 101 | cork-initializer/init1.c 102 | cork-initializer/init2.c 103 | cork-initializer/main.c 104 | LOCAL_LIBRARIES 105 | libcork 106 | ) 107 | 108 | add_c_executable( 109 | cork-test 110 | SKIP_INSTALL 111 | OUTPUT_NAME cork-test 112 | SOURCES cork-test/cork-test.c 113 | LOCAL_LIBRARIES 114 | libcork 115 | ) 116 | -------------------------------------------------------------------------------- /src/cork-hash/cork-hash.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012-2015, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | enum cork_hash_type { 18 | CORK_HASH_BIG, 19 | CORK_HASH_FASTEST, 20 | CORK_HASH_STABLE 21 | }; 22 | 23 | static enum cork_hash_type type = CORK_HASH_STABLE; 24 | static const char *string = NULL; 25 | 26 | #define OPT_VERSION 1000 27 | 28 | static struct option opts[] = { 29 | { "big", no_argument, NULL, 'b' }, 30 | { "fastest", no_argument, NULL, 'f' }, 31 | { "stable", no_argument, NULL, 's' }, 32 | { "version", no_argument, NULL, OPT_VERSION }, 33 | { NULL, 0, NULL, 0 } 34 | }; 35 | 36 | static void 37 | usage(void) 38 | { 39 | fprintf(stderr, 40 | "Usage: cork-hash [] \n" 41 | "\n" 42 | "Options:\n" 43 | " -b, --big\n" 44 | " -f, --fastest\n" 45 | " -s, --stable\n"); 46 | } 47 | 48 | static void 49 | print_version(void) 50 | { 51 | const char *version = cork_version_string(); 52 | const char *revision = cork_revision_string(); 53 | 54 | printf("cork-hash %s\n", version); 55 | if (strcmp(version, revision) != 0) { 56 | printf("Revision %s\n", revision); 57 | } 58 | } 59 | 60 | static void 61 | parse_options(int argc, char **argv) 62 | { 63 | int ch; 64 | while ((ch = getopt_long(argc, argv, "+bfs", opts, NULL)) != -1) { 65 | switch (ch) { 66 | case 'b': 67 | type = CORK_HASH_BIG; 68 | break; 69 | case 'f': 70 | type = CORK_HASH_FASTEST; 71 | break; 72 | case 's': 73 | type = CORK_HASH_STABLE; 74 | break; 75 | case OPT_VERSION: 76 | print_version(); 77 | exit(EXIT_SUCCESS); 78 | default: 79 | usage(); 80 | exit(EXIT_FAILURE); 81 | } 82 | } 83 | 84 | if (optind != argc-1) { 85 | usage(); 86 | exit(EXIT_FAILURE); 87 | } 88 | 89 | string = argv[optind]; 90 | } 91 | 92 | int 93 | main(int argc, char **argv) 94 | { 95 | parse_options(argc, argv); 96 | 97 | if (type == CORK_HASH_BIG) { 98 | cork_big_hash result = CORK_BIG_HASH_INIT(); 99 | result = cork_big_hash_buffer(result, string, strlen(string)); 100 | printf("%016" PRIx64 "%016" PRIx64 "\n", 101 | cork_u128_be64(result.u128, 0), 102 | cork_u128_be64(result.u128, 1)); 103 | } 104 | 105 | if (type == CORK_HASH_FASTEST) { 106 | /* don't include NUL terminator in hash */ 107 | cork_hash result = 0; 108 | result = cork_hash_buffer(result, string, strlen(string)); 109 | printf("0x%08" PRIx32 "\n", result); 110 | } 111 | 112 | if (type == CORK_HASH_STABLE) { 113 | /* don't include NUL terminator in hash */ 114 | cork_hash result = 0; 115 | result = cork_stable_hash_buffer(result, string, strlen(string)); 116 | printf("0x%08" PRIx32 "\n", result); 117 | } 118 | 119 | return EXIT_SUCCESS; 120 | } 121 | -------------------------------------------------------------------------------- /src/cork-initializer/init1.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #include 12 | 13 | #include 14 | 15 | CORK_INITIALIZER(init) 16 | { 17 | printf("Initializer 1\n"); 18 | } 19 | -------------------------------------------------------------------------------- /src/cork-initializer/init2.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #include 12 | 13 | #include 14 | 15 | CORK_INITIALIZER(init) 16 | { 17 | printf("Initializer 2\n"); 18 | } 19 | -------------------------------------------------------------------------------- /src/cork-initializer/main.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | int 12 | main(int argc, char **argv) 13 | { 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/libcork.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ 4 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 5 | sharedir=${prefix}/share 6 | sphinxdir=${sharedir}/doc/libcork/html 7 | 8 | Name: libcork 9 | Description: A simple, easily embeddable cross-platform C library 10 | Version: @VERSION@ 11 | URL: http://github.com/redjack/libcork 12 | Libs: -L${libdir} -lcork 13 | Libs.private: @CMAKE_THREAD_LIBS_INIT@ 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /src/libcork/core/hash.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #define CORK_HASH_ATTRIBUTES CORK_API 12 | 13 | #include "libcork/core/hash.h" 14 | #include "libcork/core/types.h" 15 | 16 | /* All of the following functions will be defined for us by libcork/core/hash.h: 17 | * cork_hash_buffer 18 | * cork_big_hash_buffer 19 | * cork_stable_hash_buffer 20 | */ 21 | -------------------------------------------------------------------------------- /src/libcork/core/timestamp.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "libcork/core/timestamp.h" 15 | #include "libcork/core/types.h" 16 | #include "libcork/helpers/errors.h" 17 | 18 | void 19 | cork_timestamp_init_now(cork_timestamp *ts) 20 | { 21 | struct timeval tp; 22 | gettimeofday(&tp, NULL); 23 | cork_timestamp_init_usec(ts, tp.tv_sec, tp.tv_usec); 24 | } 25 | 26 | 27 | #define is_digit(ch) ((ch) >= '0' && (ch) <= '9') 28 | 29 | static uint64_t 30 | power_of_10(unsigned int width) 31 | { 32 | uint64_t accumulator = 10; 33 | uint64_t result = 1; 34 | while (width != 0) { 35 | if ((width % 2) == 1) { 36 | result *= accumulator; 37 | width--; 38 | } 39 | accumulator *= accumulator; 40 | width /= 2; 41 | } 42 | return result; 43 | } 44 | 45 | static int 46 | append_fractional(const cork_timestamp ts, unsigned int width, 47 | struct cork_buffer *dest) 48 | { 49 | if (CORK_UNLIKELY(width == 0 || width > 9)) { 50 | cork_error_set_printf 51 | (EINVAL, 52 | "Invalid width %u for fractional cork_timestamp", width); 53 | return -1; 54 | } else { 55 | uint64_t denom = power_of_10(width); 56 | uint64_t frac = cork_timestamp_gsec_to_units(ts, denom); 57 | cork_buffer_append_printf(dest, "%0*" PRIu64, width, frac); 58 | return 0; 59 | } 60 | } 61 | 62 | static int 63 | cork_timestamp_format_parts(const cork_timestamp ts, struct tm *tm, 64 | const char *format, struct cork_buffer *dest) 65 | { 66 | const char *next_percent; 67 | 68 | while ((next_percent = strchr(format, '%')) != NULL) { 69 | const char *spec = next_percent + 1; 70 | unsigned int width = 0; 71 | 72 | /* First append any text in between the previous format specifier and 73 | * this one. */ 74 | cork_buffer_append(dest, format, next_percent - format); 75 | 76 | /* Then parse the format specifier */ 77 | while (is_digit(*spec)) { 78 | width *= 10; 79 | width += (*spec++ - '0'); 80 | } 81 | 82 | switch (*spec) { 83 | case '\0': 84 | cork_error_set_string 85 | (EINVAL, 86 | "Trailing %% at end of cork_timestamp format string"); 87 | return -1; 88 | 89 | case '%': 90 | cork_buffer_append(dest, "%", 1); 91 | break; 92 | 93 | case 'Y': 94 | cork_buffer_append_printf(dest, "%04d", tm->tm_year + 1900); 95 | break; 96 | 97 | case 'm': 98 | cork_buffer_append_printf(dest, "%02d", tm->tm_mon + 1); 99 | break; 100 | 101 | case 'd': 102 | cork_buffer_append_printf(dest, "%02d", tm->tm_mday); 103 | break; 104 | 105 | case 'H': 106 | cork_buffer_append_printf(dest, "%02d", tm->tm_hour); 107 | break; 108 | 109 | case 'M': 110 | cork_buffer_append_printf(dest, "%02d", tm->tm_min); 111 | break; 112 | 113 | case 'S': 114 | cork_buffer_append_printf(dest, "%02d", tm->tm_sec); 115 | break; 116 | 117 | case 's': 118 | cork_buffer_append_printf 119 | (dest, "%" PRIu32, cork_timestamp_sec(ts)); 120 | break; 121 | 122 | case 'f': 123 | rii_check(append_fractional(ts, width, dest)); 124 | break; 125 | 126 | default: 127 | cork_error_set_printf 128 | (EINVAL, 129 | "Unknown cork_timestamp format specifier %%%c", *spec); 130 | return -1; 131 | } 132 | 133 | format = spec + 1; 134 | } 135 | 136 | /* When we fall through, there is some additional content after the final 137 | * format specifier. */ 138 | cork_buffer_append_string(dest, format); 139 | return 0; 140 | } 141 | 142 | int 143 | cork_timestamp_format_utc(const cork_timestamp ts, const char *format, 144 | struct cork_buffer *dest) 145 | { 146 | time_t clock; 147 | struct tm tm; 148 | clock = cork_timestamp_sec(ts); 149 | gmtime_r(&clock, &tm); 150 | return cork_timestamp_format_parts(ts, &tm, format, dest); 151 | } 152 | 153 | int 154 | cork_timestamp_format_local(const cork_timestamp ts, const char *format, 155 | struct cork_buffer *dest) 156 | { 157 | time_t clock; 158 | struct tm tm; 159 | clock = cork_timestamp_sec(ts); 160 | localtime_r(&clock, &tm); 161 | return cork_timestamp_format_parts(ts, &tm, format, dest); 162 | } 163 | -------------------------------------------------------------------------------- /src/libcork/core/u128.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "libcork/core/types.h" 14 | #include "libcork/core/u128.h" 15 | 16 | 17 | /* From http://stackoverflow.com/questions/8023414/how-to-convert-a-128-bit-integer-to-a-decimal-ascii-string-in-c */ 18 | 19 | const char * 20 | cork_u128_to_decimal(char *dest, cork_u128 val) 21 | { 22 | uint32_t n[4]; 23 | char *s = dest; 24 | char *p = dest; 25 | unsigned int i; 26 | 27 | /* This algorithm assumes that n[3] is the MSW. */ 28 | n[3] = cork_u128_be32(val, 0); 29 | n[2] = cork_u128_be32(val, 1); 30 | n[1] = cork_u128_be32(val, 2); 31 | n[0] = cork_u128_be32(val, 3); 32 | 33 | memset(s, '0', CORK_U128_DECIMAL_LENGTH - 1); 34 | s[CORK_U128_DECIMAL_LENGTH - 1] = '\0'; 35 | 36 | for (i = 0; i < 128; i++) { 37 | unsigned int j; 38 | unsigned int carry; 39 | 40 | carry = (n[3] >= 0x80000000); 41 | /* Shift n[] left, doubling it */ 42 | n[3] = ((n[3] << 1) & 0xFFFFFFFF) + (n[2] >= 0x80000000); 43 | n[2] = ((n[2] << 1) & 0xFFFFFFFF) + (n[1] >= 0x80000000); 44 | n[1] = ((n[1] << 1) & 0xFFFFFFFF) + (n[0] >= 0x80000000); 45 | n[0] = ((n[0] << 1) & 0xFFFFFFFF); 46 | 47 | /* Add s[] to itself in decimal, doubling it */ 48 | for (j = CORK_U128_DECIMAL_LENGTH - 1; j-- > 0; ) { 49 | s[j] += s[j] - '0' + carry; 50 | carry = (s[j] > '9'); 51 | if (carry) { 52 | s[j] -= 10; 53 | } 54 | } 55 | } 56 | 57 | while ((p[0] == '0') && (p < &s[CORK_U128_DECIMAL_LENGTH - 2])) { 58 | p++; 59 | } 60 | 61 | return p; 62 | } 63 | 64 | 65 | const char * 66 | cork_u128_to_hex(char *buf, cork_u128 val) 67 | { 68 | uint64_t hi = val._.be64.hi; 69 | uint64_t lo = val._.be64.lo; 70 | if (hi == 0) { 71 | snprintf(buf, CORK_U128_HEX_LENGTH, "%" PRIx64, lo); 72 | } else { 73 | snprintf(buf, CORK_U128_HEX_LENGTH, "%" PRIx64 "%016" PRIx64, hi, lo); 74 | } 75 | return buf; 76 | } 77 | 78 | const char * 79 | cork_u128_to_padded_hex(char *buf, cork_u128 val) 80 | { 81 | uint64_t hi = val._.be64.hi; 82 | uint64_t lo = val._.be64.lo; 83 | snprintf(buf, CORK_U128_HEX_LENGTH, "%016" PRIx64 "%016" PRIx64, hi, lo); 84 | return buf; 85 | } 86 | -------------------------------------------------------------------------------- /src/libcork/core/version.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2015, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include "libcork/config.h" 11 | #include "libcork/core/api.h" 12 | 13 | 14 | /*----------------------------------------------------------------------- 15 | * Library version 16 | */ 17 | 18 | const char * 19 | cork_version_string(void) 20 | { 21 | return CORK_CONFIG_VERSION_STRING; 22 | } 23 | 24 | const char * 25 | cork_revision_string(void) 26 | { 27 | return CORK_CONFIG_REVISION; 28 | } 29 | -------------------------------------------------------------------------------- /src/libcork/ds/bitset.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | 12 | #include "libcork/core/allocator.h" 13 | #include "libcork/core/api.h" 14 | #include "libcork/core/types.h" 15 | #include "libcork/ds/bitset.h" 16 | 17 | 18 | static size_t 19 | bytes_needed(size_t bit_count) 20 | { 21 | /* We need one byte for every bit... */ 22 | size_t bytes_needed = bit_count / 8; 23 | /* Plus one extra for the leftovers that don't fit into a whole byte. */ 24 | bytes_needed += ((bit_count % 8) > 0); 25 | return bytes_needed; 26 | } 27 | 28 | void 29 | cork_bitset_init(struct cork_bitset *set, size_t bit_count) 30 | { 31 | set->bit_count = bit_count; 32 | set->byte_count = bytes_needed(bit_count); 33 | set->bits = cork_malloc(set->byte_count); 34 | memset(set->bits, 0, set->byte_count); 35 | } 36 | 37 | struct cork_bitset * 38 | cork_bitset_new(size_t bit_count) 39 | { 40 | struct cork_bitset *set = cork_new(struct cork_bitset); 41 | cork_bitset_init(set, bit_count); 42 | return set; 43 | } 44 | 45 | void 46 | cork_bitset_done(struct cork_bitset *set) 47 | { 48 | cork_free(set->bits, set->byte_count); 49 | } 50 | 51 | void 52 | cork_bitset_free(struct cork_bitset *set) 53 | { 54 | cork_bitset_done(set); 55 | cork_delete(struct cork_bitset, set); 56 | } 57 | 58 | void 59 | cork_bitset_clear(struct cork_bitset *set) 60 | { 61 | memset(set->bits, 0, set->byte_count); 62 | } 63 | -------------------------------------------------------------------------------- /src/libcork/ds/dllist.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include "libcork/core/api.h" 11 | #include "libcork/core/types.h" 12 | #include "libcork/ds/dllist.h" 13 | 14 | 15 | /* Include a linkable (but deprecated) version of this to maintain ABI 16 | * compatibility. */ 17 | #undef cork_dllist_init 18 | CORK_API void 19 | cork_dllist_init(struct cork_dllist *list) 20 | { 21 | list->head.next = &list->head; 22 | list->head.prev = &list->head; 23 | } 24 | 25 | 26 | void 27 | cork_dllist_map(struct cork_dllist *list, 28 | cork_dllist_map_func func, void *user_data) 29 | { 30 | struct cork_dllist_item *curr; 31 | struct cork_dllist_item *next; 32 | cork_dllist_foreach_void(list, curr, next) { 33 | func(curr, user_data); 34 | } 35 | } 36 | 37 | int 38 | cork_dllist_visit(struct cork_dllist *list, void *ud, 39 | cork_dllist_visit_f *visit) 40 | { 41 | struct cork_dllist_item *curr; 42 | struct cork_dllist_item *next; 43 | cork_dllist_foreach_void(list, curr, next) { 44 | int rc = visit(ud, curr); 45 | if (rc != 0) { 46 | return rc; 47 | } 48 | } 49 | return 0; 50 | } 51 | 52 | 53 | size_t 54 | cork_dllist_size(const struct cork_dllist *list) 55 | { 56 | size_t size = 0; 57 | struct cork_dllist_item *curr; 58 | struct cork_dllist_item *next; 59 | cork_dllist_foreach_void(list, curr, next) { 60 | size++; 61 | } 62 | return size; 63 | } 64 | -------------------------------------------------------------------------------- /src/libcork/ds/ring-buffer.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | 12 | #include "libcork/core/allocator.h" 13 | #include "libcork/core/types.h" 14 | #include "libcork/ds/ring-buffer.h" 15 | 16 | 17 | int 18 | cork_ring_buffer_init(struct cork_ring_buffer *self, size_t size) 19 | { 20 | self->elements = cork_calloc(size, sizeof(void *)); 21 | self->allocated_size = size; 22 | self->size = 0; 23 | self->read_index = 0; 24 | self->write_index = 0; 25 | return 0; 26 | } 27 | 28 | struct cork_ring_buffer * 29 | cork_ring_buffer_new(size_t size) 30 | { 31 | struct cork_ring_buffer *buf = cork_new(struct cork_ring_buffer); 32 | cork_ring_buffer_init(buf, size); 33 | return buf; 34 | } 35 | 36 | void 37 | cork_ring_buffer_done(struct cork_ring_buffer *self) 38 | { 39 | cork_cfree(self->elements, self->allocated_size, sizeof(void *)); 40 | } 41 | 42 | void 43 | cork_ring_buffer_free(struct cork_ring_buffer *buf) 44 | { 45 | cork_ring_buffer_done(buf); 46 | cork_delete(struct cork_ring_buffer, buf); 47 | } 48 | 49 | int 50 | cork_ring_buffer_add(struct cork_ring_buffer *self, void *element) 51 | { 52 | if (cork_ring_buffer_is_full(self)) { 53 | return -1; 54 | } 55 | 56 | self->elements[self->write_index++] = element; 57 | self->size++; 58 | if (self->write_index == self->allocated_size) { 59 | self->write_index = 0; 60 | } 61 | return 0; 62 | } 63 | 64 | void * 65 | cork_ring_buffer_pop(struct cork_ring_buffer *self) 66 | { 67 | if (cork_ring_buffer_is_empty(self)) { 68 | return NULL; 69 | } else { 70 | void *result = self->elements[self->read_index++]; 71 | self->size--; 72 | if (self->read_index == self->allocated_size) { 73 | self->read_index = 0; 74 | } 75 | return result; 76 | } 77 | } 78 | 79 | void * 80 | cork_ring_buffer_peek(struct cork_ring_buffer *self) 81 | { 82 | if (cork_ring_buffer_is_empty(self)) { 83 | return NULL; 84 | } else { 85 | return self->elements[self->read_index]; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/libcork/posix/directory-walker.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2012, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "libcork/core/attributes.h" 20 | #include "libcork/core/error.h" 21 | #include "libcork/core/types.h" 22 | #include "libcork/ds/buffer.h" 23 | #include "libcork/helpers/errors.h" 24 | #include "libcork/helpers/posix.h" 25 | #include "libcork/os/files.h" 26 | 27 | 28 | static int 29 | cork_walk_one_directory(struct cork_dir_walker *w, struct cork_buffer *path, 30 | size_t root_path_size) 31 | { 32 | DIR *dir = NULL; 33 | struct dirent *entry; 34 | size_t dir_path_size; 35 | 36 | rip_check_posix(dir = opendir(path->buf)); 37 | 38 | cork_buffer_append(path, "/", 1); 39 | dir_path_size = path->size; 40 | errno = 0; 41 | while ((entry = readdir(dir)) != NULL) { 42 | struct stat info; 43 | 44 | /* Skip the "." and ".." entries */ 45 | if (strcmp(entry->d_name, ".") == 0 || 46 | strcmp(entry->d_name, "..") == 0) { 47 | continue; 48 | } 49 | 50 | /* Stat the directory entry */ 51 | cork_buffer_append_string(path, entry->d_name); 52 | ei_check_posix(stat(path->buf, &info)); 53 | 54 | /* If the entry is a subdirectory, recurse into it. */ 55 | if (S_ISDIR(info.st_mode)) { 56 | int rc = cork_dir_walker_enter_directory 57 | (w, path->buf, path->buf + root_path_size, 58 | path->buf + dir_path_size); 59 | if (rc != CORK_SKIP_DIRECTORY) { 60 | ei_check(cork_walk_one_directory(w, path, root_path_size)); 61 | ei_check(cork_dir_walker_leave_directory 62 | (w, path->buf, path->buf + root_path_size, 63 | path->buf + dir_path_size)); 64 | } 65 | } else if (S_ISREG(info.st_mode)) { 66 | ei_check(cork_dir_walker_file 67 | (w, path->buf, path->buf + root_path_size, 68 | path->buf + dir_path_size)); 69 | } 70 | 71 | /* Remove this entry name from the path buffer. */ 72 | cork_buffer_truncate(path, dir_path_size); 73 | 74 | /* We have to reset errno to 0 because of the ambiguous way 75 | * readdir uses a return value of NULL. Other functions may 76 | * return normally yet set errno to a non-zero value. dlopen 77 | * on Mac OS X is an ogreish example. Since an error readdir 78 | * is indicated by returning NULL and setting errno to indicate 79 | * the error, then we need to reset it to zero before each call. 80 | * We shall assume, perhaps to our great misery, that functions 81 | * within this loop do proper error checking and act accordingly. 82 | */ 83 | errno = 0; 84 | } 85 | 86 | /* Check errno immediately after the while loop terminates */ 87 | if (CORK_UNLIKELY(errno != 0)) { 88 | cork_system_error_set(); 89 | goto error; 90 | } 91 | 92 | /* Remove the trailing '/' from the path buffer. */ 93 | cork_buffer_truncate(path, dir_path_size - 1); 94 | rii_check_posix(closedir(dir)); 95 | return 0; 96 | 97 | error: 98 | if (dir != NULL) { 99 | rii_check_posix(closedir(dir)); 100 | } 101 | return -1; 102 | } 103 | 104 | int 105 | cork_walk_directory(const char *path, struct cork_dir_walker *w) 106 | { 107 | int rc; 108 | char *p; 109 | struct cork_buffer buf = CORK_BUFFER_INIT(); 110 | 111 | /* Seed the buffer with the directory's path, ensuring that there's no 112 | * trailing '/' */ 113 | cork_buffer_append_string(&buf, path); 114 | p = buf.buf; 115 | while (p[buf.size-1] == '/') { 116 | buf.size--; 117 | p[buf.size] = '\0'; 118 | } 119 | rc = cork_walk_one_directory(w, &buf, buf.size + 1); 120 | cork_buffer_done(&buf); 121 | return rc; 122 | } 123 | -------------------------------------------------------------------------------- /src/libcork/posix/process.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | 12 | #include "libcork/core.h" 13 | #include "libcork/ds.h" 14 | #include "libcork/os/process.h" 15 | #include "libcork/helpers/errors.h" 16 | 17 | 18 | #if !defined(CORK_DEBUG_PROCESS) 19 | #define CORK_DEBUG_PROCESS 0 20 | #endif 21 | 22 | #if CORK_DEBUG_PROCESS 23 | #include 24 | #define DEBUG(...) fprintf(stderr, __VA_ARGS__) 25 | #else 26 | #define DEBUG(...) /* no debug messages */ 27 | #endif 28 | 29 | 30 | struct cork_cleanup_entry { 31 | struct cork_dllist_item item; 32 | int priority; 33 | const char *name; 34 | cork_cleanup_function function; 35 | }; 36 | 37 | static struct cork_cleanup_entry * 38 | cork_cleanup_entry_new(const char *name, int priority, 39 | cork_cleanup_function function) 40 | { 41 | struct cork_cleanup_entry *self = cork_new(struct cork_cleanup_entry); 42 | self->priority = priority; 43 | self->name = cork_strdup(name); 44 | self->function = function; 45 | return self; 46 | } 47 | 48 | static void 49 | cork_cleanup_entry_free(struct cork_cleanup_entry *self) 50 | { 51 | cork_strfree(self->name); 52 | cork_delete(struct cork_cleanup_entry, self); 53 | } 54 | 55 | static struct cork_dllist cleanup_entries = CORK_DLLIST_INIT(cleanup_entries); 56 | static bool cleanup_registered = false; 57 | 58 | static void 59 | cork_cleanup_call_one(struct cork_dllist_item *item, void *user_data) 60 | { 61 | struct cork_cleanup_entry *entry = 62 | cork_container_of(item, struct cork_cleanup_entry, item); 63 | cork_cleanup_function function = entry->function; 64 | DEBUG("Call cleanup function [%d] %s\n", entry->priority, entry->name); 65 | /* We need to free the entry before calling the entry's function, since one 66 | * of the functions that libcork registers frees the allocator instance that 67 | * we'd use to free the entry. If we called the function first, the 68 | * allocator would be freed before we could use it to free the entry. */ 69 | cork_cleanup_entry_free(entry); 70 | function(); 71 | } 72 | 73 | static void 74 | cork_cleanup_call_all(void) 75 | { 76 | cork_dllist_map(&cleanup_entries, cork_cleanup_call_one, NULL); 77 | } 78 | 79 | static void 80 | cork_cleanup_entry_add(struct cork_cleanup_entry *entry) 81 | { 82 | struct cork_dllist_item *curr; 83 | 84 | if (CORK_UNLIKELY(!cleanup_registered)) { 85 | atexit(cork_cleanup_call_all); 86 | cleanup_registered = true; 87 | } 88 | 89 | /* Linear search through the list of existing cleanup functions. When we 90 | * find the first existing function with a higher priority, we've found 91 | * where to insert the new function. */ 92 | for (curr = cork_dllist_start(&cleanup_entries); 93 | !cork_dllist_is_end(&cleanup_entries, curr); curr = curr->next) { 94 | struct cork_cleanup_entry *existing = 95 | cork_container_of(curr, struct cork_cleanup_entry, item); 96 | if (existing->priority > entry->priority) { 97 | cork_dllist_add_before(&existing->item, &entry->item); 98 | return; 99 | } 100 | } 101 | 102 | /* If we fall through the loop, then the new function should be appended to 103 | * the end of the list. */ 104 | cork_dllist_add(&cleanup_entries, &entry->item); 105 | } 106 | 107 | 108 | CORK_API void 109 | cork_cleanup_at_exit_named(const char *name, int priority, 110 | cork_cleanup_function function) 111 | { 112 | struct cork_cleanup_entry *entry = 113 | cork_cleanup_entry_new(name, priority, function); 114 | DEBUG("Register cleanup function [%d] %s\n", priority, name); 115 | cork_cleanup_entry_add(entry); 116 | } 117 | -------------------------------------------------------------------------------- /tests/.gitattributes: -------------------------------------------------------------------------------- 1 | *.t -whitespace 2 | cram.py -diff 3 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.t.err 2 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2015, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license details. 7 | # ---------------------------------------------------------------------- 8 | 9 | include_directories( 10 | ${CMAKE_SOURCE_DIR}/include 11 | ${CMAKE_BINARY_DIR}/include 12 | ) 13 | 14 | #----------------------------------------------------------------------- 15 | # Build the test cases 16 | 17 | # For each test cases, we create two executables: one that links with a 18 | # shared libcork, and the other that simulates embedding libcork into 19 | # another project. For the embedded version, we need to know which of 20 | # the libcork submodules should be included when compiling the test 21 | # case. These are provided as additional parameters to the make_test 22 | # macro. 23 | 24 | macro(make_test test_name) 25 | if (ENABLE_SHARED OR ENABLE_SHARED_EXECUTABLES) 26 | add_executable(shared-${test_name} ${test_name}.c) 27 | target_link_libraries(shared-${test_name} ${CHECK_LIBRARIES} 28 | libcork-shared) 29 | add_test(shared-${test_name} shared-${test_name}) 30 | endif (ENABLE_SHARED OR ENABLE_SHARED_EXECUTABLES) 31 | 32 | if (ENABLE_STATIC OR NOT ENABLE_SHARED_EXECUTABLES) 33 | add_executable(embedded-${test_name} ${test_name}.c) 34 | set_target_properties(embedded-${test_name} PROPERTIES 35 | COMPILE_DEFINITIONS CORK_EMBEDDED_TEST=1) 36 | target_link_libraries(embedded-${test_name} ${CHECK_LIBRARIES} 37 | libcork-static) 38 | add_test(embedded-${test_name} embedded-${test_name}) 39 | endif (ENABLE_STATIC OR NOT ENABLE_SHARED_EXECUTABLES) 40 | endmacro(make_test) 41 | 42 | make_test(test-array) 43 | make_test(test-bitset) 44 | make_test(test-buffer) 45 | make_test(test-core) 46 | make_test(test-dllist) 47 | make_test(test-files) 48 | make_test(test-gc) 49 | make_test(test-hash-table) 50 | make_test(test-managed-buffer) 51 | make_test(test-mempool) 52 | make_test(test-ring-buffer) 53 | make_test(test-slice) 54 | make_test(test-subprocess) 55 | make_test(test-threads) 56 | 57 | #----------------------------------------------------------------------- 58 | # Command-line tests 59 | 60 | if(TILERA) 61 | configure_file(tile-test ${CMAKE_BINARY_DIR}/tile-test COPYONLY) 62 | endif(TILERA) 63 | 64 | find_package(PythonInterp) 65 | 66 | if (PYTHON_EXECUTABLE) 67 | configure_file(ccram ${CMAKE_BINARY_DIR}/ccram COPYONLY) 68 | file(GLOB_RECURSE TESTS "${CMAKE_CURRENT_SOURCE_DIR}/*.t") 69 | foreach(TEST ${TESTS}) 70 | get_filename_component(TEST_NAME "${TEST}" NAME_WE) 71 | add_test( 72 | ${TEST_NAME} 73 | ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} 74 | ${CMAKE_BINARY_DIR}/ccram 75 | --python ${PYTHON_EXECUTABLE} 76 | --root ${CMAKE_SOURCE_DIR} 77 | --tests ${TEST} 78 | ) 79 | endforeach(TEST) 80 | else (PYTHON_EXECUTABLE) 81 | message(WARNING "Unable to find Python; skipping cram tests.") 82 | endif (PYTHON_EXECUTABLE) 83 | -------------------------------------------------------------------------------- /tests/ccram: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$1" = "--python" ]; then 4 | shift 5 | PYTHON="$1" 6 | shift 7 | else 8 | PYTHON=python 9 | fi 10 | 11 | if [ "$1" = "--root" ]; then 12 | shift 13 | ROOT="$1" 14 | shift 15 | else 16 | ROOT=$(dirname $PWD) 17 | fi 18 | 19 | if [ "$1" = "--tests" ]; then 20 | shift 21 | TESTS="$1" 22 | shift 23 | else 24 | TESTS=../tests 25 | fi 26 | 27 | export ROOT 28 | 29 | LD_LIBRARY_PATH="$PWD/src:$LD_LIBRARY_PATH" \ 30 | PATH="$PWD/src:$PATH" \ 31 | "$PYTHON" "$ROOT/tests/cram.py" "$@" "$TESTS" 32 | -------------------------------------------------------------------------------- /tests/cork-hash.t: -------------------------------------------------------------------------------- 1 | Make sure that our stable hash is really stable. 2 | 3 | $ cork-hash foo 4 | 0xf6a5c420 5 | $ cork-hash bar 6 | 0x450e998d 7 | $ cork-hash tests.h 8 | 0x0b0628ee 9 | $ cork-hash "A longer string" 10 | 0x53a2c885 11 | -------------------------------------------------------------------------------- /tests/cork-initializer.t: -------------------------------------------------------------------------------- 1 | We need to sort the output, since there's no guarantee about which order our 2 | initializer functions will run in. 3 | 4 | $ cork-initializer | sort 5 | Initializer 1 6 | Initializer 2 7 | -------------------------------------------------------------------------------- /tests/cork-test/cleanup.t: -------------------------------------------------------------------------------- 1 | $ cork-test cleanup 2 | Cleanup function 0 3 | Cleanup function 1 4 | Cleanup function 2 5 | Cleanup function 3 6 | Cleanup function 4 7 | Cleanup function 5 8 | -------------------------------------------------------------------------------- /tests/cork-test/directory-watcher.t: -------------------------------------------------------------------------------- 1 | This first test makes sure to only create one file or subdirectory in each 2 | directory. That means that we don't have to sort the output to get a 3 | reproducible result, which lets us check the ordering of the different events in 4 | the callback stucture. 5 | 6 | $ mkdir test1 7 | $ mkdir test1/a 8 | $ mkdir test1/a/b 9 | $ touch test1/a/b/c 10 | $ cork-test dir test1 11 | Entering a (a) 12 | Entering b (a/b) 13 | c (a/b/c) (test1/a/b/c) 14 | Leaving a/b 15 | Leaving a 16 | $ cork-test dir --shallow test1 17 | Skipping a 18 | 19 | $ mkdir test2 20 | $ touch test2/a 21 | $ cork-test dir test2 22 | a (a) (test2/a) 23 | $ cork-test dir --shallow test2 24 | a (a) (test2/a) 25 | 26 | A more complex directory structure. We have to sort the output, since there's 27 | no guarantee in what order the directory walker will encounter the files. 28 | 29 | $ mkdir test3 30 | $ mkdir test3/d1 31 | $ mkdir test3/d2 32 | $ touch test3/d2/a 33 | $ touch test3/d2/b 34 | $ mkdir test3/d3 35 | $ touch test3/d3/a 36 | $ touch test3/d3/b 37 | $ touch test3/d3/c 38 | $ mkdir test3/d3/s1 39 | $ mkdir test3/d3/s1/s2 40 | $ touch test3/d3/s1/s2/a 41 | $ cork-test dir --only-files test3 | sort 42 | d2/a 43 | d2/b 44 | d3/a 45 | d3/b 46 | d3/c 47 | d3/s1/s2/a 48 | 49 | Test what happens when the directory doesn't exit. 50 | 51 | $ cork-test dir missing 52 | No such file or directory 53 | [1] 54 | $ cork-test dir --only-files missing 55 | No such file or directory 56 | [1] 57 | $ cork-test dir --shallow missing 58 | No such file or directory 59 | [1] 60 | -------------------------------------------------------------------------------- /tests/cork-test/help1-c1-s1.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s1 --help 2 | Usage: cork-test c1 s1 [] 3 | 4 | This is a pretty cool command. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help1-c1-s2.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s2 --help 2 | Usage: cork-test c1 s2 [] 3 | 4 | This is an excellent command. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help1-c1.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 --help 2 | Usage: cork-test c1 [] 3 | 4 | Available commands: 5 | s1 Subcommand 1 6 | s2 Subcommand 2 7 | -------------------------------------------------------------------------------- /tests/cork-test/help1-c2.t: -------------------------------------------------------------------------------- 1 | $ cork-test c2 --help 2 | Usage: cork-test c2 [] 3 | 4 | This command is pretty decent. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help1-root.t: -------------------------------------------------------------------------------- 1 | $ cork-test --help 2 | Usage: cork-test [] 3 | 4 | Available commands: 5 | c1 Command 1 (now with subcommands) 6 | c2 Command 2 7 | pwd Print working directory 8 | mkdir Create a directory 9 | rm Remove a file or directory 10 | find Search for a file in a list of directories 11 | paths Print out standard paths for the current user 12 | dir Print the contents of a directory 13 | sub Run a subcommand 14 | cleanup Test process cleanup functions 15 | -------------------------------------------------------------------------------- /tests/cork-test/help2-c1-s1.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s1 -h 2 | Usage: cork-test c1 s1 [] 3 | 4 | This is a pretty cool command. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help2-c1-s2.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s2 -h 2 | Usage: cork-test c1 s2 [] 3 | 4 | This is an excellent command. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help2-c1.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 -h 2 | Usage: cork-test c1 [] 3 | 4 | Available commands: 5 | s1 Subcommand 1 6 | s2 Subcommand 2 7 | -------------------------------------------------------------------------------- /tests/cork-test/help2-c2.t: -------------------------------------------------------------------------------- 1 | $ cork-test c2 -h 2 | Usage: cork-test c2 [] 3 | 4 | This command is pretty decent. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help2-root.t: -------------------------------------------------------------------------------- 1 | $ cork-test -h 2 | Usage: cork-test [] 3 | 4 | Available commands: 5 | c1 Command 1 (now with subcommands) 6 | c2 Command 2 7 | pwd Print working directory 8 | mkdir Create a directory 9 | rm Remove a file or directory 10 | find Search for a file in a list of directories 11 | paths Print out standard paths for the current user 12 | dir Print the contents of a directory 13 | sub Run a subcommand 14 | cleanup Test process cleanup functions 15 | -------------------------------------------------------------------------------- /tests/cork-test/help3-c1-s1.t: -------------------------------------------------------------------------------- 1 | $ cork-test help c1 s1 2 | Usage: cork-test c1 s1 [] 3 | 4 | This is a pretty cool command. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help3-c1-s2.t: -------------------------------------------------------------------------------- 1 | $ cork-test help c1 s2 2 | Usage: cork-test c1 s2 [] 3 | 4 | This is an excellent command. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help3-c1.t: -------------------------------------------------------------------------------- 1 | $ cork-test help c1 2 | Usage: cork-test c1 [] 3 | 4 | Available commands: 5 | s1 Subcommand 1 6 | s2 Subcommand 2 7 | -------------------------------------------------------------------------------- /tests/cork-test/help3-c2.t: -------------------------------------------------------------------------------- 1 | $ cork-test help c2 2 | Usage: cork-test c2 [] 3 | 4 | This command is pretty decent. 5 | -------------------------------------------------------------------------------- /tests/cork-test/help3-root.t: -------------------------------------------------------------------------------- 1 | $ cork-test help 2 | Usage: cork-test [] 3 | 4 | Available commands: 5 | c1 Command 1 (now with subcommands) 6 | c2 Command 2 7 | pwd Print working directory 8 | mkdir Create a directory 9 | rm Remove a file or directory 10 | find Search for a file in a list of directories 11 | paths Print out standard paths for the current user 12 | dir Print the contents of a directory 13 | sub Run a subcommand 14 | cleanup Test process cleanup functions 15 | -------------------------------------------------------------------------------- /tests/cork-test/no-command-c1.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 2 | No command given. 3 | Usage: cork-test c1 [] 4 | 5 | Available commands: 6 | s1 Subcommand 1 7 | s2 Subcommand 2 8 | [1] 9 | -------------------------------------------------------------------------------- /tests/cork-test/no-command-root.t: -------------------------------------------------------------------------------- 1 | $ cork-test 2 | No command given. 3 | Usage: cork-test [] 4 | 5 | Available commands: 6 | c1 Command 1 (now with subcommands) 7 | c2 Command 2 8 | pwd Print working directory 9 | mkdir Create a directory 10 | rm Remove a file or directory 11 | find Search for a file in a list of directories 12 | paths Print out standard paths for the current user 13 | dir Print the contents of a directory 14 | sub Run a subcommand 15 | cleanup Test process cleanup functions 16 | [1] 17 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s1-f-t.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 -f foo s1 -t 2 | You chose command "c1 s1". Good for you! 3 | And you gave the --test option! Look at that. 4 | And you want the file to be foo. Sure thing. 5 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s1-f.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 -f foo s1 2 | You chose command "c1 s1". Good for you! 3 | And you want the file to be foo. Sure thing. 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s1-t.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s1 -t 2 | You chose command "c1 s1". Good for you! 3 | And you gave the --test option! Look at that. 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s1-test.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s1 --test 2 | You chose command "c1 s1". Good for you! 3 | And you gave the --test option! Look at that. 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s1.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s1 2 | You chose command "c1 s1". Good for you! 3 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s2-f.t: -------------------------------------------------------------------------------- 1 | $ cd $TESTDIR 2 | $ cork-test c1 -f ../test-input.txt s2 3 | You chose command "c1 s2". Fantastico! 4 | And you want the file to be ../test-input.txt. Sure thing. 5 | Hello, world 6 | What is up 7 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s2-file.t: -------------------------------------------------------------------------------- 1 | $ cd $TESTDIR 2 | $ cork-test c1 --file ../test-input.txt s2 3 | You chose command "c1 s2". Fantastico! 4 | And you want the file to be ../test-input.txt. Sure thing. 5 | Hello, world 6 | What is up 7 | -------------------------------------------------------------------------------- /tests/cork-test/run-c1-s2.t: -------------------------------------------------------------------------------- 1 | $ cork-test c1 s2 2 | You chose command "c1 s2". Fantastico! 3 | -------------------------------------------------------------------------------- /tests/cork-test/run-c2.t: -------------------------------------------------------------------------------- 1 | $ cork-test c2 2 | You chose command "c2". That's pretty good. 3 | -------------------------------------------------------------------------------- /tests/cork-test/run-find-01.t: -------------------------------------------------------------------------------- 1 | $ cork-test mkdir --recursive a/b/c/b 2 | 3 | $ cork-test find b a 4 | a/b 5 | $ cork-test find b a/b/c 6 | a/b/c/b 7 | $ cork-test find b a:a/b/c 8 | a/b 9 | $ cork-test find b a/b/c:a 10 | a/b/c/b 11 | 12 | $ cork-test find b/c a 13 | a/b/c 14 | $ cork-test find b/c a/b/c 15 | b/c not found in a/b/c 16 | [1] 17 | 18 | $ cork-test find d a 19 | d not found in a 20 | [1] 21 | $ cork-test find d a:a/b:a/b/c 22 | d not found in a:a/b:a/b/c 23 | [1] 24 | -------------------------------------------------------------------------------- /tests/cork-test/run-find-all-01.t: -------------------------------------------------------------------------------- 1 | $ cork-test mkdir --recursive a/b/c/b 2 | 3 | $ cork-test find --all b a 4 | a/b 5 | $ cork-test find --all b a/b/c 6 | a/b/c/b 7 | $ cork-test find --all b a:a/b/c 8 | a/b 9 | a/b/c/b 10 | $ cork-test find --all b a/b/c:a 11 | a/b/c/b 12 | a/b 13 | 14 | $ cork-test find --all b/c a 15 | a/b/c 16 | $ cork-test find --all b/c a/b/c 17 | 18 | $ cork-test find --all d a 19 | $ cork-test find --all d a:a/b:a/b/c 20 | -------------------------------------------------------------------------------- /tests/cork-test/run-mkdir-01.t: -------------------------------------------------------------------------------- 1 | $ cork-test mkdir a 2 | $ find a | sort 3 | a 4 | 5 | $ cork-test mkdir a 6 | $ find a | sort 7 | a 8 | 9 | $ cork-test mkdir --require a 10 | File exists 11 | [1] 12 | $ find a | sort 13 | a 14 | 15 | $ cork-test mkdir --recursive a/b/c 16 | $ find a | sort 17 | a 18 | a/b 19 | a/b/c 20 | 21 | $ cork-test mkdir --recursive a/b 22 | $ find a | sort 23 | a 24 | a/b 25 | a/b/c 26 | 27 | $ cork-test mkdir --recursive --require a/b 28 | File exists 29 | [1] 30 | $ find a | sort 31 | a 32 | a/b 33 | a/b/c 34 | 35 | $ cork-test mkdir --recursive --require a/b/d 36 | $ find a | sort 37 | a 38 | a/b 39 | a/b/c 40 | a/b/d 41 | -------------------------------------------------------------------------------- /tests/cork-test/run-paths-01.t: -------------------------------------------------------------------------------- 1 | $ HOME= \ 2 | > cork-test paths 3 | Cannot determine home directory 4 | [1] 5 | 6 | $ HOME=/home/test \ 7 | > XDG_CONFIG_HOME= \ 8 | > XDG_DATA_HOME= \ 9 | > XDG_CONFIG_DIRS= \ 10 | > XDG_DATA_DIRS= \ 11 | > XDG_CACHE_HOME= \ 12 | > XDG_RUNTIME_DIR= \ 13 | > cork-test paths 14 | Cannot determine user-specific runtime directory 15 | Home: /home/test 16 | Config: /home/test/.config:/etc/xdg 17 | Data: /home/test/.local/share:/usr/local/share:/usr/share 18 | Cache: /home/test/.cache 19 | [1] 20 | 21 | $ HOME=/home/test \ 22 | > XDG_CONFIG_HOME= \ 23 | > XDG_DATA_HOME= \ 24 | > XDG_CONFIG_DIRS= \ 25 | > XDG_DATA_DIRS= \ 26 | > XDG_CACHE_HOME= \ 27 | > XDG_RUNTIME_DIR=/run/user/test \ 28 | > cork-test paths 29 | Home: /home/test 30 | Config: /home/test/.config:/etc/xdg 31 | Data: /home/test/.local/share:/usr/local/share:/usr/share 32 | Cache: /home/test/.cache 33 | Runtime: /run/user/test 34 | 35 | $ HOME=/home/test \ 36 | > XDG_CONFIG_HOME=/home/test/custom-config \ 37 | > XDG_DATA_HOME=/home/test/share \ 38 | > XDG_CONFIG_DIRS=/etc \ 39 | > XDG_DATA_DIRS=/usr/share \ 40 | > XDG_CACHE_HOME=/tmp/cache/test \ 41 | > XDG_RUNTIME_DIR=/run/user/test \ 42 | > cork-test paths 43 | Home: /home/test 44 | Config: /home/test/custom-config:/etc 45 | Data: /home/test/share:/usr/share 46 | Cache: /tmp/cache/test 47 | Runtime: /run/user/test 48 | -------------------------------------------------------------------------------- /tests/cork-test/run-pwd-01.t: -------------------------------------------------------------------------------- 1 | $ a=$(cork-test pwd) 2 | $ b=$(pwd) 3 | $ [ "$a" = "$b" ] 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-rm-01.t: -------------------------------------------------------------------------------- 1 | $ cork-test mkdir --recursive --require a/b/c 2 | $ cork-test mkdir --recursive --require a/b/d 3 | $ find a 2>/dev/null | sort 4 | a 5 | a/b 6 | a/b/c 7 | a/b/d 8 | 9 | $ cork-test rm --require a/b/d 10 | $ find a 2>/dev/null | sort 11 | a 12 | a/b 13 | a/b/c 14 | 15 | $ cork-test rm --require a/b/d 16 | No such file or directory 17 | [1] 18 | $ find a 2>/dev/null | sort 19 | a 20 | a/b 21 | a/b/c 22 | 23 | $ cork-test rm --require --recursive a/b/c 24 | $ find a 2>/dev/null | sort 25 | a 26 | a/b 27 | 28 | $ cork-test rm --recursive a 29 | $ find a 2>/dev/null | sort 30 | -------------------------------------------------------------------------------- /tests/cork-test/run-sub-01.t: -------------------------------------------------------------------------------- 1 | $ cork-test sub echo Hello world 2 | echo Hello world 3 | Hello world 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-sub-02.t: -------------------------------------------------------------------------------- 1 | $ cork-test sub false 2 | false 3 | -------------------------------------------------------------------------------- /tests/cork-test/run-sub-03.t: -------------------------------------------------------------------------------- 1 | $ CORK_TEST_VAR="Hello world" cork-test sub sh -c 'echo $CORK_TEST_VAR' 2 | sh -c echo $CORK_TEST_VAR 3 | Hello world 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-sub-04.t: -------------------------------------------------------------------------------- 1 | $ cork-test sub bad-command 2 | bad-command 3 | No such file or directory 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-sub-05.t: -------------------------------------------------------------------------------- 1 | $ cork-test sub -d / pwd 2 | pwd 3 | / 4 | -------------------------------------------------------------------------------- /tests/cork-test/run-sub-06.t: -------------------------------------------------------------------------------- 1 | $ cork-test sub -i foo cat 2 | cat 3 | foo 4 | -------------------------------------------------------------------------------- /tests/helpers.h: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license 7 | * details. 8 | * ---------------------------------------------------------------------- 9 | */ 10 | 11 | #ifndef TESTS_HELPERS_H 12 | #define TESTS_HELPERS_H 13 | 14 | #include "libcork/core/allocator.h" 15 | #include "libcork/core/error.h" 16 | 17 | 18 | /*----------------------------------------------------------------------- 19 | * Allocators 20 | */ 21 | 22 | /* For the "embedded" tests, use a custom allocator that debugs every 23 | * allocation. For the "shared" tests, use the default allocator. */ 24 | 25 | #if CORK_EMBEDDED_TEST 26 | 27 | static void 28 | setup_allocator(void) 29 | { 30 | struct cork_alloc *debug = cork_debug_alloc_new(cork_allocator); 31 | cork_set_allocator(debug); 32 | } 33 | 34 | #else /* !CORK_EMBEDDED_TEST */ 35 | 36 | static void 37 | setup_allocator(void) 38 | { 39 | /* do nothing */ 40 | } 41 | 42 | #endif 43 | 44 | 45 | /*----------------------------------------------------------------------- 46 | * Error reporting 47 | */ 48 | 49 | #if !defined(PRINT_EXPECTED_FAILURES) 50 | #define PRINT_EXPECTED_FAILURES 1 51 | #endif 52 | 53 | #if PRINT_EXPECTED_FAILURES 54 | #define print_expected_failure() \ 55 | printf("[expected: %s]\n", cork_error_message()); 56 | #else 57 | #define print_expected_failure() /* do nothing */ 58 | #endif 59 | 60 | 61 | #define DESCRIBE_TEST \ 62 | fprintf(stderr, "--- %s\n", __func__); 63 | 64 | 65 | #define fail_if_error(call) \ 66 | do { \ 67 | call; \ 68 | if (cork_error_occurred()) { \ 69 | fail("%s", cork_error_message()); \ 70 | } \ 71 | } while (0) 72 | 73 | #define fail_unless_error(call, ...) \ 74 | do { \ 75 | call; \ 76 | if (!cork_error_occurred()) { \ 77 | fail(__VA_ARGS__); \ 78 | } else { \ 79 | print_expected_failure(); \ 80 | } \ 81 | cork_error_clear(); \ 82 | } while (0) 83 | 84 | #define fail_unless_equal(what, format, expected, actual) \ 85 | (fail_unless((expected) == (actual), \ 86 | "%s not equal (expected " format \ 87 | ", got " format ")", \ 88 | (what), (expected), (actual))) 89 | 90 | #define fail_unless_streq(what, expected, actual) \ 91 | (fail_unless(strcmp((expected), (actual)) == 0, \ 92 | "%s not equal (expected \"%s\", got \"%s\")", \ 93 | (char *) (what), (char *) (expected), (char *) (actual))) 94 | 95 | 96 | #endif /* TESTS_HELPERS_H */ 97 | -------------------------------------------------------------------------------- /tests/test-bitset.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2013-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "libcork/core/types.h" 17 | #include "libcork/ds/bitset.h" 18 | 19 | #include "helpers.h" 20 | 21 | 22 | /*----------------------------------------------------------------------- 23 | * Bit sets 24 | */ 25 | 26 | static void 27 | test_bitset_of_size(size_t bit_count) 28 | { 29 | size_t i; 30 | struct cork_bitset *set1 = cork_bitset_new(bit_count); 31 | struct cork_bitset set2; 32 | 33 | for (i = 0; i < bit_count; i++) { 34 | cork_bitset_set(set1, i, true); 35 | fail_unless(cork_bitset_get(set1, i), "Unexpected value for bit %zu", i); 36 | } 37 | 38 | for (i = 0; i < bit_count; i++) { 39 | cork_bitset_set(set1, i, false); 40 | fail_if(cork_bitset_get(set1, i), "Unexpected value for bit %zu", i); 41 | } 42 | cork_bitset_free(set1); 43 | 44 | cork_bitset_init(&set2, bit_count); 45 | for (i = 0; i < bit_count; i++) { 46 | cork_bitset_set(&set2, i, true); 47 | fail_unless(cork_bitset_get(&set2, i), "Unexpected value for bit %zu", i); 48 | } 49 | 50 | for (i = 0; i < bit_count; i++) { 51 | cork_bitset_set(&set2, i, false); 52 | fail_if(cork_bitset_get(&set2, i), "Unexpected value for bit %zu", i); 53 | } 54 | cork_bitset_done(&set2); 55 | } 56 | 57 | START_TEST(test_bitset) 58 | { 59 | DESCRIBE_TEST; 60 | /* Test a variety of sizes, with and without spillover bits. */ 61 | test_bitset_of_size(1); 62 | test_bitset_of_size(2); 63 | test_bitset_of_size(3); 64 | test_bitset_of_size(4); 65 | test_bitset_of_size(5); 66 | test_bitset_of_size(6); 67 | test_bitset_of_size(7); 68 | test_bitset_of_size(8); 69 | test_bitset_of_size(9); 70 | test_bitset_of_size(10); 71 | test_bitset_of_size(11); 72 | test_bitset_of_size(12); 73 | test_bitset_of_size(13); 74 | test_bitset_of_size(14); 75 | test_bitset_of_size(15); 76 | test_bitset_of_size(16); 77 | test_bitset_of_size(65535); 78 | test_bitset_of_size(65536); 79 | test_bitset_of_size(65537); 80 | } 81 | END_TEST 82 | 83 | 84 | /*----------------------------------------------------------------------- 85 | * Testing harness 86 | */ 87 | 88 | Suite * 89 | test_suite() 90 | { 91 | Suite *s = suite_create("bits"); 92 | 93 | TCase *tc_ds = tcase_create("bits"); 94 | tcase_set_timeout(tc_ds, 20.0); 95 | tcase_add_test(tc_ds, test_bitset); 96 | suite_add_tcase(s, tc_ds); 97 | 98 | return s; 99 | } 100 | 101 | 102 | int 103 | main(int argc, const char **argv) 104 | { 105 | int number_failed; 106 | Suite *suite = test_suite(); 107 | SRunner *runner = srunner_create(suite); 108 | 109 | setup_allocator(); 110 | srunner_run_all(runner, CK_NORMAL); 111 | number_failed = srunner_ntests_failed(runner); 112 | srunner_free(runner); 113 | 114 | return (number_failed == 0)? EXIT_SUCCESS: EXIT_FAILURE; 115 | } 116 | -------------------------------------------------------------------------------- /tests/test-gc.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2011-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "libcork/core/attributes.h" 17 | #include "libcork/core/gc.h" 18 | #include "libcork/core/types.h" 19 | #include "libcork/helpers/gc.h" 20 | 21 | #include "helpers.h" 22 | 23 | 24 | /*----------------------------------------------------------------------- 25 | * Garbage collector 26 | */ 27 | 28 | struct tree { 29 | int id; 30 | struct tree *left; 31 | struct tree *right; 32 | }; 33 | 34 | _free_(tree) { 35 | /* nothing to do, I just want to test the macro */ 36 | } 37 | 38 | _recurse_(tree) { 39 | struct tree *self = obj; 40 | recurse(gc, self->left, ud); 41 | recurse(gc, self->right, ud); 42 | } 43 | 44 | /* test all the variations, even though we're only going to use "tree" */ 45 | _gc_(tree); 46 | 47 | #define tree0__recurse tree__recurse 48 | CORK_ATTR_UNUSED static struct cork_gc_obj_iface tree0__gc; 49 | _gc_no_free_(tree0); 50 | 51 | #define tree1__free tree__free 52 | CORK_ATTR_UNUSED static struct cork_gc_obj_iface tree1__gc; 53 | _gc_no_recurse_(tree1); 54 | 55 | CORK_ATTR_UNUSED static struct cork_gc_obj_iface tree2__gc; 56 | _gc_leaf_(tree2); 57 | 58 | struct tree * 59 | tree_new(int id, struct tree *l, struct tree *r) 60 | { 61 | struct tree *self = cork_gc_new(tree); 62 | self->id = id; 63 | self->left = cork_gc_incref(l); 64 | self->right = cork_gc_incref(r); 65 | return self; 66 | } 67 | 68 | START_TEST(test_gc_acyclic_01) 69 | { 70 | DESCRIBE_TEST; 71 | cork_gc_init(); 72 | 73 | struct tree *t1 = tree_new(0, NULL, NULL); 74 | struct tree *t2 = tree_new(0, NULL, NULL); 75 | struct tree *t0 = tree_new(0, t1, t2); 76 | 77 | cork_gc_decref(t1); 78 | cork_gc_decref(t2); 79 | cork_gc_decref(t0); 80 | 81 | cork_gc_done(); 82 | } 83 | END_TEST 84 | 85 | START_TEST(test_gc_cyclic_01) 86 | { 87 | DESCRIBE_TEST; 88 | cork_gc_init(); 89 | 90 | struct tree *t1 = tree_new(0, NULL, NULL); 91 | struct tree *t2 = tree_new(0, NULL, NULL); 92 | struct tree *t0 = tree_new(0, t1, t2); 93 | 94 | t1->left = cork_gc_incref(t0); 95 | 96 | cork_gc_decref(t1); 97 | cork_gc_decref(t2); 98 | cork_gc_decref(t0); 99 | 100 | cork_gc_done(); 101 | } 102 | END_TEST 103 | 104 | START_TEST(test_gc_cyclic_02) 105 | { 106 | DESCRIBE_TEST; 107 | cork_gc_init(); 108 | 109 | struct tree *t1 = tree_new(0, NULL, NULL); 110 | struct tree *t2 = tree_new(0, NULL, NULL); 111 | struct tree *t0 = tree_new(0, t1, t2); 112 | 113 | t1->left = cork_gc_incref(t0); 114 | t2->left = cork_gc_incref(t2); 115 | t2->right = cork_gc_incref(t0); 116 | 117 | cork_gc_decref(t1); 118 | cork_gc_decref(t2); 119 | cork_gc_decref(t0); 120 | 121 | cork_gc_done(); 122 | } 123 | END_TEST 124 | 125 | 126 | /*----------------------------------------------------------------------- 127 | * Testing harness 128 | */ 129 | 130 | Suite * 131 | test_suite() 132 | { 133 | Suite *s = suite_create("gc"); 134 | 135 | TCase *tc_gc = tcase_create("gc"); 136 | tcase_add_test(tc_gc, test_gc_acyclic_01); 137 | tcase_add_test(tc_gc, test_gc_cyclic_01); 138 | tcase_add_test(tc_gc, test_gc_cyclic_02); 139 | suite_add_tcase(s, tc_gc); 140 | 141 | return s; 142 | } 143 | 144 | 145 | int 146 | main(int argc, const char **argv) 147 | { 148 | int number_failed; 149 | Suite *suite = test_suite(); 150 | SRunner *runner = srunner_create(suite); 151 | 152 | setup_allocator(); 153 | srunner_run_all(runner, CK_NORMAL); 154 | number_failed = srunner_ntests_failed(runner); 155 | srunner_free(runner); 156 | 157 | return (number_failed == 0)? EXIT_SUCCESS: EXIT_FAILURE; 158 | } 159 | 160 | -------------------------------------------------------------------------------- /tests/test-input.txt: -------------------------------------------------------------------------------- 1 | Hello, world 2 | What is up 3 | -------------------------------------------------------------------------------- /tests/test-slice.c: -------------------------------------------------------------------------------- 1 | /* -*- coding: utf-8 -*- 2 | * ---------------------------------------------------------------------- 3 | * Copyright © 2009-2014, RedJack, LLC. 4 | * All rights reserved. 5 | * 6 | * Please see the COPYING file in this distribution for license details. 7 | * ---------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "libcork/ds/slice.h" 17 | 18 | #include "helpers.h" 19 | 20 | 21 | /*----------------------------------------------------------------------- 22 | * Static slices 23 | */ 24 | 25 | START_TEST(test_static_slice) 26 | { 27 | static char SRC[] = "Here is some text."; 28 | size_t SRC_LEN = sizeof(SRC) - 1; 29 | 30 | struct cork_slice slice; 31 | struct cork_slice copy1; 32 | struct cork_slice lcopy1; 33 | cork_slice_init_static(&slice, SRC, SRC_LEN); 34 | fail_if_error(cork_slice_copy(©1, &slice, 8, 4)); 35 | fail_if_error(cork_slice_light_copy(&lcopy1, &slice, 8, 4)); 36 | fail_if_error(cork_slice_slice(&slice, 8, 4)); 37 | fail_unless(cork_slice_equal(&slice, ©1), "Slices should be equal"); 38 | fail_unless(cork_slice_equal(&slice, &lcopy1), "Slices should be equal"); 39 | /* We have to finish lcopy1 first, since it's a light copy. */ 40 | cork_slice_finish(&lcopy1); 41 | cork_slice_finish(&slice); 42 | cork_slice_finish(©1); 43 | } 44 | END_TEST 45 | 46 | 47 | /*----------------------------------------------------------------------- 48 | * Copy-once slices 49 | */ 50 | 51 | START_TEST(test_copy_once_slice) 52 | { 53 | static char SRC[] = "Here is some text."; 54 | size_t SRC_LEN = sizeof(SRC) - 1; 55 | 56 | struct cork_slice slice; 57 | struct cork_slice copy1; 58 | struct cork_slice copy2; 59 | struct cork_slice lcopy1; 60 | struct cork_slice lcopy2; 61 | 62 | cork_slice_init_copy_once(&slice, SRC, SRC_LEN); 63 | fail_unless(slice.buf == SRC, "Unexpected slice buffer"); 64 | 65 | fail_if_error(cork_slice_light_copy(&lcopy1, &slice, 8, 4)); 66 | /* We should still be using the original SRC buffer directly, since we only 67 | * created a light copy. */ 68 | fail_unless(slice.buf == SRC, "Unexpected slice buffer"); 69 | fail_unless(slice.buf + 8 == lcopy1.buf, "Unexpected slice buffer"); 70 | 71 | fail_if_error(cork_slice_copy(©1, &slice, 8, 4)); 72 | fail_if_error(cork_slice_slice(&slice, 8, 4)); 73 | /* Once we create a full copy, the content should have been moved into a 74 | * managed buffer, which will exist somewhere else in memory than the 75 | * original SRC pointer. */ 76 | fail_unless(slice.buf != SRC, "Unexpected slice buffer"); 77 | fail_unless(slice.buf == copy1.buf, "Unexpected slice buffer"); 78 | /* The light copy that we made previously won't have been moved over to the 79 | * new managed buffer, though. */ 80 | fail_unless(cork_slice_equal(&slice, ©1), "Slices should be equal"); 81 | 82 | /* Once we've switched over to the managed buffer, a new light copy should 83 | * still point into the managed buffer. */ 84 | fail_if_error(cork_slice_light_copy(&lcopy2, &slice, 0, 4)); 85 | fail_unless(slice.buf != SRC, "Unexpected slice buffer"); 86 | fail_unless(slice.buf == lcopy2.buf, "Unexpected slice buffer"); 87 | 88 | fail_if_error(cork_slice_copy(©2, &slice, 0, 4)); 89 | /* The second full copy should not create a new managed buffer, it should 90 | * just increment the existing managed buffer's refcount. */ 91 | fail_unless(slice.buf == copy2.buf, "Unexpected slice buffer"); 92 | fail_unless(copy1.buf == copy2.buf, "Unexpected slice buffer"); 93 | fail_unless(cork_slice_equal(&slice, ©2), "Slices should be equal"); 94 | fail_unless(cork_slice_equal(©1, ©2), "Slices should be equal"); 95 | 96 | /* We have to finish the light copies first. */ 97 | cork_slice_finish(&lcopy1); 98 | cork_slice_finish(&lcopy2); 99 | cork_slice_finish(&slice); 100 | cork_slice_finish(©1); 101 | cork_slice_finish(©2); 102 | } 103 | END_TEST 104 | 105 | 106 | /*----------------------------------------------------------------------- 107 | * Testing harness 108 | */ 109 | 110 | Suite * 111 | test_suite() 112 | { 113 | Suite *s = suite_create("slice"); 114 | 115 | TCase *tc_slice = tcase_create("slice"); 116 | tcase_add_test(tc_slice, test_static_slice); 117 | tcase_add_test(tc_slice, test_copy_once_slice); 118 | suite_add_tcase(s, tc_slice); 119 | 120 | return s; 121 | } 122 | 123 | 124 | int 125 | main(int argc, const char **argv) 126 | { 127 | int number_failed; 128 | Suite *suite = test_suite(); 129 | SRunner *runner = srunner_create(suite); 130 | 131 | setup_allocator(); 132 | srunner_run_all(runner, CK_NORMAL); 133 | number_failed = srunner_ntests_failed(runner); 134 | srunner_free(runner); 135 | 136 | return (number_failed == 0)? EXIT_SUCCESS: EXIT_FAILURE; 137 | } 138 | -------------------------------------------------------------------------------- /tests/tile-test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ ! -x $TILERA_ROOT/bin/tile-monitor ]; then 4 | # If no tile-monitor is installed, then there is nothing to test. 5 | echo "No tile-monitor installed in $TILERA_ROOT/bin" 6 | exit 1 7 | fi 8 | 9 | export TEST_DIR="/tmp/test" 10 | export TILERA_COMMON_ARGS=" \ 11 | --debug-on-crash \ 12 | --mkdir $TEST_DIR/build \ 13 | --mkdir $TEST_DIR/tests \ 14 | --tile standard \ 15 | --mount-tile /usr \ 16 | --mount-tile /lib \ 17 | --upload . $TEST_DIR/build \ 18 | --upload ../tests $TEST_DIR/tests \ 19 | --env LD_LIBRARY_PATH="$TEST_DIR/build/src:/usr/local/lib:/usr/lib:/lib" \ 20 | --env PATH="/usr/local/bin:$PATH" \ 21 | --cd $TEST_DIR/build \ 22 | --run -+- ctest -+- --quit" 23 | 24 | # Note: we assume the Tilera processor is connected to the MDE by an IP 25 | # connection and has a hostname of 'tilera'. Trust us - you don't want 26 | # to run tests over the serial connection. 27 | export TILERA_DEV_ARGS="$TILERA_COMMON_ARGS --net tilera --resume" 28 | $TILERA_ROOT/bin/tile-monitor $TILERA_DEV_ARGS 29 | 30 | ## Uncomment the following four lines and comment the previous two if 31 | ## you want to run the tests on the Tilera simulator. 32 | #export SIM_IMAGE_SIZE="4x4" 33 | #export TILERA_SIM_ARGS=" \ 34 | # --image $SIM_IMAGE_SIZE $TILERA_COMMON_ARGS --functional" 35 | #$TILERA_ROOT/bin/tile-monitor $TILERA_SIM_ARGS 36 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------- 3 | # Copyright © 2011-2013, RedJack, LLC. 4 | # All rights reserved. 5 | # 6 | # Please see the COPYING file in this distribution for license 7 | # details. 8 | # ---------------------------------------------------------------------- 9 | 10 | # Calculates the current version number. If possible, this is the 11 | # output of “git describe”. If “git describe” returns an error (most 12 | # likely because we're in an unpacked copy of a release tarball, rather 13 | # than in a git working copy), then we fall back on reading the contents 14 | # of the RELEASE-VERSION file. 15 | # 16 | # This will automatically update the RELEASE-VERSION file, if necessary. 17 | # Note that the RELEASE-VERSION file should *not* be checked into git; 18 | # please add it to your top-level .gitignore file. 19 | 20 | version=$(git describe) 21 | if [ -n ${version} ]; then 22 | # If we got something from git-describe, write the version to the 23 | # output file. 24 | echo ${version} > RELEASE-VERSION 25 | else 26 | version=$(cat RELEASE-VERSION) 27 | if [ -z ${version} ]; then 28 | echo "Cannot find the version number!" >&2 29 | exit 1 30 | fi 31 | fi 32 | 33 | echo ${version} 34 | --------------------------------------------------------------------------------