Compare commits

67 Commits

Author SHA1 Message Date
wash 7058a14be0 meta: update clang-format config 2026-05-04 19:41:15 +01:00
wash bf251dd818 fx.reflection: optimise linux dynamic function calling 2026-05-04 19:37:44 +01:00
wash bebc67537d fx.reflection: implement dynamic function calling on linux-x86_64 2026-05-04 19:23:10 +01:00
wash e954a15d92 fx.reflection: cleanup darwin implementation of dynamic function calling 2026-05-04 19:22:41 +01:00
wash 18c9d30c60 meta: re-organise tests 2026-05-04 16:37:06 +01:00
wash 716b939d4f fx.serial: toml: replace fx_number with new number types 2026-05-04 16:36:43 +01:00
wash 5aae7dff6b fx: add macro to initialise an empty fx_value 2026-05-04 16:36:07 +01:00
wash 32264d693c fx: add stub files for enum type registration 2026-05-04 16:34:32 +01:00
wash fd35c2b03e fx.reflection: add stub files for object properties 2026-05-04 16:33:51 +01:00
wash bf7d8cfb75 fx.reflection: implement dynamic function calling 2026-05-04 16:33:16 +01:00
wash 85ff8b7eaa fx.collections: dict: remove duplicate cstr hash function 2026-05-03 20:36:50 +01:00
wash dab3fec6b8 fx: add a generic container for primitive values and objects 2026-05-03 20:22:05 +01:00
wash 7d44a6ec98 fx: split fx_number into dedicated int, uint, double, and bool types 2026-05-03 20:21:02 +01:00
wash 7b5173127c build: remove relative directory paths 2026-05-03 20:20:16 +01:00
wash 6777c09f67 fx.collections: move fx_uuid to fx 2026-05-03 17:18:50 +01:00
wash d75ec65721 fx.collections: move fx_number to fx 2026-05-03 17:18:39 +01:00
wash 87270b686c build: re-organise assembly build files 2026-05-03 17:05:48 +01:00
wash f4469c9eb0 fx.cmdline: convert to new assembly build system 2026-05-03 16:49:33 +01:00
wash 44fed67d43 fx.term: convert to new assembly build system 2026-05-03 16:49:23 +01:00
wash 0c53974ac9 fx.serial: convert to new assembly build system 2026-05-03 16:48:42 +01:00
wash 3f7ad3ab08 fx.compression: convert to new assembly build system 2026-05-03 16:29:23 +01:00
wash cefb548824 fx.io: convert to assembly build system 2026-05-03 14:51:11 +01:00
wash 55ba15b1fa fx: fix darwin compilation 2026-05-03 14:51:01 +01:00
wash 90d180d839 meta: update clang-format config 2026-05-03 14:50:50 +01:00
wash a0283da135 build: fix namespace build macro 2026-05-03 14:47:59 +01:00
wash 7b42a023e4 runtime: add assembly system to collect and export type definitions 2026-05-03 13:11:22 +01:00
wash 7d78d7d314 meta: update clang-format config 2026-05-03 13:10:36 +01:00
wash 4f40bfd9a0 fx.collections: move string to fx 2026-05-02 21:07:00 +01:00
wash a339b6e01a build: use dots instead of hyphens in library names 2026-05-02 21:03:46 +01:00
wash 604ddfcebf build: build fx and fx.collections assemblies 2026-05-02 21:02:10 +01:00
wash c78ea4bfa6 fx.collections: update header directories 2026-05-02 21:01:51 +01:00
wash b951577f48 fx: update header directories 2026-05-02 21:01:17 +01:00
wash 5d1b2aabbb build: update template for building assemblies 2026-05-02 21:00:59 +01:00
wash a65eb5c161 meta: rename compress module to fx.compression namespace 2026-05-02 14:38:31 +01:00
wash 9b8c0f8763 meta: rename ds module to fx.collections namespace 2026-05-02 14:38:11 +01:00
wash c04c2e8f12 meta: rename serial module to fx.serial namespace 2026-05-02 14:37:56 +01:00
wash b8cf2b379b meta: rename term module to fx.term namespace 2026-05-02 14:37:43 +01:00
wash 274a48a845 meta: rename io module to fx.io namespace 2026-05-02 14:37:29 +01:00
wash 47feee7b1a meta: rename cmd module to fx.cmdline namespace 2026-05-02 14:37:15 +01:00
wash 7db5fefe25 meta: rename core module to fx namespace 2026-05-02 14:36:59 +01:00
wash b072632499 test: update tests 2026-05-02 14:31:17 +01:00
wash 15a9147e15 term: update string api usage 2026-05-02 14:31:00 +01:00
wash d24592dde4 core: encoding: fix incorrect function call in fx_wchar_is_number 2026-05-02 14:30:48 +01:00
wash ce56eacafe cmd: update string api usage 2026-05-02 14:30:27 +01:00
wash dbf50395d0 ds: add verbs to string function names 2026-05-02 14:29:58 +01:00
wash 4aaa165e5f term: add POSIX defines for linux support 2026-05-02 14:29:32 +01:00
wash 4fcbcfdfb2 io: add linux support 2026-05-02 14:28:52 +01:00
wash cb39baa233 test: update write_string function references 2026-04-20 22:05:42 +01:00
wash 5646c8c2b8 term: update write_string function references 2026-04-20 22:05:25 +01:00
wash 3529e8525a io: update write_string function references 2026-04-20 22:05:04 +01:00
wash 6a26e00438 serial: implement returning fx_result values from (de)serialisers 2026-04-20 22:04:29 +01:00
wash c76008e498 ds: formatting tweaks 2026-04-20 22:03:20 +01:00
wash 321622ac16 ds: string: add verbs to function names 2026-04-20 22:03:11 +01:00
wash c39f50a0ee core: stream: formatting tweaks 2026-04-20 21:41:47 +01:00
wash 5ab348fd30 core: rename write_string functions to write_cstr 2026-04-20 21:41:38 +01:00
wash 709d11331c meta: update clang-format config 2026-04-19 20:57:56 +01:00
wash 912c450e6e core: add rosetta support 2026-04-01 19:04:41 +01:00
wash fc43d104dc core: dict: fix fx_cstr_hash using different constants than other string hashing functions 2026-04-01 19:04:30 +01:00
wash 8eba5c7462 core: hash: add missing include 2026-04-01 19:03:52 +01:00
wash 5212ef4bc8 core: stringstream: fix internal buffer not always being null-terminated 2026-04-01 19:03:27 +01:00
wash fc4a422a79 core: encoding: fix fx_wchar_is_hex_digit calling wrong function 2026-04-01 19:02:54 +01:00
wash ef3f64f095 meta: update clang-format config 2026-04-01 19:02:19 +01:00
wash 467c13e161 build: add some build options to customise library functionality 2026-04-01 19:02:04 +01:00
wash 6b04920d29 cmd: update references to fx_btree 2026-03-16 15:11:45 +00:00
wash e4bacb7360 ds: update references to fx_btree 2026-03-16 15:11:29 +00:00
wash 9c34aa7996 core: rename btree to bst 2026-03-16 15:11:17 +00:00
wash e9d0e323f0 meta: rename to fx 2026-03-16 10:35:43 +00:00
367 changed files with 30738 additions and 26169 deletions
+73 -15
View File
@@ -1,7 +1,7 @@
BasedOnStyle: WebKit
IndentWidth: 8
---
Language: Cpp
Language: C
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
@@ -26,8 +26,8 @@ AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BinPackArguments: false
BinPackParameters: false
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
@@ -52,12 +52,12 @@ PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- BLUELIB_API
- FX_API
ForEachMacros:
- b_btree_foreach
- b_queue_foreach
MacroBlockBegin: "B_TYPE_.*_BEGIN"
MacroBlockEnd: "B_TYPE_.*_END"
- fx_btree_foreach
- fx_queue_foreach
MacroBlockBegin: "FX_(TYPE|ASSEMBLY)_.*_BEGIN"
MacroBlockEnd: "FX_(TYPE|ASSEMBLY)_.*_END"
---
Language: ObjC
DerivePointerAlignment: false
@@ -84,8 +84,8 @@ AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BinPackArguments: false
BinPackParameters: false
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
@@ -110,9 +110,67 @@ PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- BLUELIB_API
- FX_API
ForEachMacros:
- b_btree_foreach
- b_queue_foreach
MacroBlockBegin: "B_TYPE_.*_BEGIN"
MacroBlockEnd: "B_TYPE_.*_END"
- fx_btree_foreach
- fx_queue_foreach
MacroBlockBegin: "FX_(TYPE|ASSEMBLY)_.*_BEGIN"
MacroBlockEnd: "FX_(TYPE|ASSEMBLY)_.*_END"
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: Right
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
IncludeBlocks: Regroup
SortIncludes: true
IndentRequires: true
NamespaceIndentation: Inner
ReflowComments: true
SpacesBeforeTrailingComments: 3
TabWidth: 8
UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyExcessCharacter: 9999999
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- FX_API
ForEachMacros:
- fx_btree_foreach
- fx_queue_foreach
MacroBlockBegin: "FX_(TYPE|ASSEMBLY).*_BEGIN"
MacroBlockEnd: "FX_(TYPE|ASSEMBLY).*_END"
+34 -47
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(bluelib C)
project(fx C ASM)
include (TestBigEndian)
@@ -9,58 +9,45 @@ set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(b_modules core ds serial term cmd io compress)
set(fx_source_root ${CMAKE_CURRENT_SOURCE_DIR})
set(fx_build_root ${CMAKE_CURRENT_BINARY_DIR})
file(GLOB _all_assemblies assemblies/*
LIST_DIRECTORIES TRUE)
set(b_system_name ${CMAKE_SYSTEM_NAME})
string(TOLOWER ${b_system_name} b_system_name)
foreach (assembly_path ${_all_assemblies})
get_filename_component(assembly_name ${assembly_path} NAME)
set(fx_all_assemblies ${fx_all_assemblies} ${assembly_name})
endforeach (assembly_path)
message(STATUS "System name: ${b_system_name}")
if (NOT DEFINED fx_assemblies)
set(fx_assemblies ${fx_all_assemblies})
endif ()
if (NOT DEFINED fx_enable_floating_point)
set(fx_enable_floating_point 1)
endif ()
if (NOT DEFINED fx_enable_tests)
set(fx_enable_tests 1)
endif ()
message(STATUS "Floating point support: ${fx_enable_floating_point}")
set(fx_system_name ${CMAKE_SYSTEM_NAME})
string(TOLOWER ${fx_system_name} fx_system_name)
set(fx_system_arch ${CMAKE_SYSTEM_PROCESSOR})
string(TOLOWER ${fx_system_arch} fx_system_arch)
message(STATUS "Target system: ${fx_system_name}-${fx_system_arch}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
foreach (module ${b_modules})
add_subdirectory(${module})
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/${module})
message(STATUS "Building unit tests for module ${module}")
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Templates.cmake)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/${module}/${module}-units.c)
add_executable(blue-${module}-units
test/${module}/${module}-units.c
misc/AllTests.c
misc/CuTest.c
misc/CuTest.h)
target_link_libraries(blue-${module}-units blue-${module})
target_include_directories(blue-${module}-units PRIVATE misc/)
set_target_properties(blue-${module}-units PROPERTIES FOLDER "Tests/${module}")
foreach (assembly ${fx_assemblies})
add_subdirectory(assemblies/${assembly})
endforeach (assembly)
endif ()
file(GLOB test_sources test/${module}/*.c)
list(REMOVE_ITEM test_sources "${CMAKE_CURRENT_SOURCE_DIR}/test/${module}/${module}-units.c")
foreach (test_file ${test_sources})
get_filename_component(test_name ${test_file} NAME_WE)
add_executable(blue-${module}-${test_name} ${test_file})
set_target_properties(blue-${module}-${test_name} PROPERTIES FOLDER "Tests/${module}")
target_link_libraries(blue-${module}-${test_name} blue-${module})
endforeach (test_file)
endif ()
endforeach (module)
file(GLOB test_sources test/*.c)
list(REMOVE_ITEM test_sources "${CMAKE_CURRENT_SOURCE_DIR}/test/units.c")
foreach (test_file ${test_sources})
get_filename_component(test_name ${test_file} NAME_WE)
add_executable(blue-${test_name} ${test_file})
set_target_properties(blue-${test_name} PROPERTIES FOLDER "Tests")
foreach (module ${b_modules})
target_link_libraries(blue-${test_name} blue-${module})
endforeach (module)
endforeach (test_file)
add_subdirectory(test)
+7
View File
@@ -0,0 +1,7 @@
add_fx_assembly(
NAME fx.cmdline
NAMESPACES fx.cmdline
DEPENDENCIES
fx.runtime
fx.collections
fx.term)
+7
View File
@@ -0,0 +1,7 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.cmdline");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END()
+4
View File
@@ -0,0 +1,4 @@
add_fx_assembly(
NAME fx.collections
NAMESPACES fx.collections
DEPENDENCIES fx.runtime)
+14
View File
@@ -0,0 +1,14 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.collections");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "array", fx_array);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "bitbuffer", fx_bitbuffer);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "bitmap", fx_bitmap);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "dict", fx_dict);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "hashmap", fx_hashmap);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "list", fx_list);
FX_ASSEMBLY_EXPORT_TYPE("fx.collections", "tree", fx_tree);
FX_ASSEMBLY_END()
+4
View File
@@ -0,0 +1,4 @@
add_fx_assembly(
NAME fx.compression
NAMESPACES fx.compression
DEPENDENCIES fx.runtime)
+7
View File
@@ -0,0 +1,7 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.compression");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END()
+4
View File
@@ -0,0 +1,4 @@
add_fx_assembly(
NAME fx.io
NAMESPACES fx.io
DEPENDENCIES fx.runtime)
+7
View File
@@ -0,0 +1,7 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.io");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END()
+3
View File
@@ -0,0 +1,3 @@
add_fx_assembly(
NAME fx.runtime
NAMESPACES fx fx.reflection)
+12
View File
@@ -0,0 +1,12 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.runtime");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_EXPORT_TYPE("fx", "stream", fx_stream);
FX_ASSEMBLY_EXPORT_TYPE("fx", "string", fx_string);
FX_ASSEMBLY_EXPORT_TYPE("fx", "stringstream", fx_stringstream);
FX_ASSEMBLY_EXPORT_TYPE("fx", "iterator", fx_iterator);
FX_ASSEMBLY_EXPORT_TYPE("fx.reflection", "assembly", fx_assembly);
FX_ASSEMBLY_END()
+4
View File
@@ -0,0 +1,4 @@
add_fx_assembly(
NAME fx.serial
NAMESPACES fx.serial
DEPENDENCIES fx.runtime fx.collections)
+7
View File
@@ -0,0 +1,7 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.serial");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END()
+4
View File
@@ -0,0 +1,4 @@
add_fx_assembly(
NAME fx.term
NAMESPACES fx.term
DEPENDENCIES fx.runtime fx.collections)
+7
View File
@@ -0,0 +1,7 @@
#include <fx/macros.h>
#include <fx/reflection/assembly.h>
FX_ASSEMBLY_BEGIN()
FX_ASSEMBLY_NAME("fx.term");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END()
-189
View File
@@ -1,189 +0,0 @@
#[=======================================================================[.rst:
FindBluelib
------------
Find the Bluelib library and header directories
Imported Targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` target:
``Bluelib::Bluelib``
The Bluelib library, if found
Result Variables
^^^^^^^^^^^^^^^^
This module will set the following variables in your project:
``Bluelib_FOUND``
true if the Bluelib C headers and libraries were found
``Bluelib_INCLUDE_DIR``
directories containing the Bluelib C headers.
``Bluelib_LIBRARY``
the C library to link against
Hints
^^^^^
The user may set the environment variable ``Bluelib_PREFIX`` to the root
directory of a Bluelib library installation.
#]=======================================================================]
set (Bluelib_SEARCH_PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr/local/share
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
${Bluelib_PREFIX}
$ENV{Bluelib_PREFIX})
if (Bluelib_STATIC)
set(_lib_suffix "-s")
endif ()
set(supported_components Core Ds Term Cmd Io Serial Compress)
set(components ${Bluelib_FIND_COMPONENTS})
string(REPLACE ";" ", " supported_components_string_list "${supported_components}")
if (NOT components)
set(components ${supported_components})
endif ()
set(required_vars)
foreach (component ${components})
if (NOT "${component}" IN_LIST supported_components)
message(FATAL_ERROR "'${component}' is not a valid Bluelib module.\nSupported modules: ${supported_components_string_list}")
endif ()
string(TOLOWER ${component} header_name)
set(lib_name ${header_name}${_lib_suffix})
if (NOT Bluelib_${component}_INCLUDE_DIR)
find_path(Bluelib_${component}_INCLUDE_DIR
NAMES blue/${header_name}.h ${Bluelib_FIND_ARGS}
PATH_SUFFIXES include
PATHS ${Bluelib_SEARCH_PATHS})
endif ()
if (NOT Bluelib_${component}_LIBRARY)
find_library(Bluelib_${component}_LIBRARY
NAMES blue-${lib_name} ${Bluelib_FIND_ARGS}
PATH_SUFFIXES lib
PATHS ${Bluelib_SEARCH_PATHS})
else ()
# on Windows, ensure paths are in canonical format (forward slahes):
file(TO_CMAKE_PATH "${Bluelib_${component}_LIBRARY}" Bluelib_${component}_LIBRARY)
endif()
list(APPEND required_vars Bluelib_${component}_INCLUDE_DIR Bluelib_${component}_LIBRARY)
endforeach (component)
unset(Bluelib_FIND_ARGS)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Bluelib
REQUIRED_VARS ${required_vars})
if (Bluelib_FOUND)
set(created_targets)
foreach (component ${components})
string(TOLOWER ${component} header_name)
set(lib_name ${header_name}${_lib_suffix})
if(NOT TARGET Bluelib::${component})
add_library(Bluelib::${component} UNKNOWN IMPORTED)
set_target_properties(Bluelib::${component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Bluelib_${component}_INCLUDE_DIR}")
target_compile_definitions(Bluelib::${component} INTERFACE _CRT_SECURE_NO_WARNINGS=1)
if (Bluelib_STATIC)
target_compile_definitions(Bluelib::${component} INTERFACE BLUELIB_STATIC=1)
endif ()
set_target_properties(Bluelib::${component} PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${Bluelib_${component}_LIBRARY}")
set(created_targets ${created_targets} ${component})
endif ()
endforeach (component)
foreach (component ${created_targets})
if ("${component}" STREQUAL "Ds")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Ds' depends on 'Core', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Ds INTERFACE Bluelib::Core)
endif ()
if ("${component}" STREQUAL "Term")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Term' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Ds)
message(FATAL_ERROR "Bluelib: Module 'Term' depends on 'Ds', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Term INTERFACE Bluelib::Core Bluelib::Ds)
endif ()
if ("${component}" STREQUAL "Serial")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Serial' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Ds)
message(FATAL_ERROR "Bluelib: Module 'Serial' depends on 'Ds', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Serial INTERFACE Bluelib::Core Bluelib::Ds)
endif ()
if ("${component}" STREQUAL "Cmd")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Cmd' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Ds)
message(FATAL_ERROR "Bluelib: Module 'Cmd' depends on 'Ds', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Term)
message(FATAL_ERROR "Bluelib: Module 'Cmd' depends on 'Term', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Cmd INTERFACE Bluelib::Core Bluelib::Ds Bluelib::Term)
endif ()
if ("${component}" STREQUAL "Io")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Io' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET Bluelib::Ds)
message(FATAL_ERROR "Bluelib: Module 'Io' depends on 'Ds', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Io INTERFACE Bluelib::Core Bluelib::Ds)
endif ()
if ("${component}" STREQUAL "Compress")
if (NOT TARGET Bluelib::Core)
message(FATAL_ERROR "Bluelib: Module 'Compress' depends on 'Core', which was not specified in find_package()")
endif ()
target_link_libraries(Bluelib::Compress INTERFACE Bluelib::Core Bluelib::Ds)
endif ()
endforeach (component)
endif()
+189
View File
@@ -0,0 +1,189 @@
#[=======================================================================[.rst:
FindFX
------------
Find the FX library and header directories
Imported Targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` target:
``FX::FX``
The FX library, if found
Result Variables
^^^^^^^^^^^^^^^^
This module will set the following variables in your project:
``FX_FOUND``
true if the FX C headers and libraries were found
``FX_INCLUDE_DIR``
directories containing the FX C headers.
``FX_LIBRARY``
the C library to link against
Hints
^^^^^
The user may set the environment variable ``FX_PREFIX`` to the root
directory of a FX library installation.
#]=======================================================================]
set (FX_SEARCH_PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr/local/share
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
${FX_PREFIX}
$ENV{FX_PREFIX})
if (FX_STATIC)
set(_lib_suffix "-s")
endif ()
set(supported_components Core Ds Term Cmd Io Serial Compress)
set(components ${FX_FIND_COMPONENTS})
string(REPLACE ";" ", " supported_components_string_list "${supported_components}")
if (NOT components)
set(components ${supported_components})
endif ()
set(required_vars)
foreach (component ${components})
if (NOT "${component}" IN_LIST supported_components)
message(FATAL_ERROR "'${component}' is not a valid FX module.\nSupported modules: ${supported_components_string_list}")
endif ()
string(TOLOWER ${component} header_name)
set(lib_name ${header_name}${_lib_suffix})
if (NOT FX_${component}_INCLUDE_DIR)
find_path(FX_${component}_INCLUDE_DIR
NAMES fx/${header_name}.h ${FX_FIND_ARGS}
PATH_SUFFIXES include
PATHS ${FX_SEARCH_PATHS})
endif ()
if (NOT FX_${component}_LIBRARY)
find_library(FX_${component}_LIBRARY
NAMES fx-${lib_name} ${FX_FIND_ARGS}
PATH_SUFFIXES lib
PATHS ${FX_SEARCH_PATHS})
else ()
# on Windows, ensure paths are in canonical format (forward slahes):
file(TO_CMAKE_PATH "${FX_${component}_LIBRARY}" FX_${component}_LIBRARY)
endif()
list(APPEND required_vars FX_${component}_INCLUDE_DIR FX_${component}_LIBRARY)
endforeach (component)
unset(FX_FIND_ARGS)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FX
REQUIRED_VARS ${required_vars})
if (FX_FOUND)
set(created_targets)
foreach (component ${components})
string(TOLOWER ${component} header_name)
set(lib_name ${header_name}${_lib_suffix})
if(NOT TARGET FX::${component})
add_library(FX::${component} UNKNOWN IMPORTED)
set_target_properties(FX::${component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${FX_${component}_INCLUDE_DIR}")
target_compile_definitions(FX::${component} INTERFACE _CRT_SECURE_NO_WARNINGS=1)
if (FX_STATIC)
target_compile_definitions(FX::${component} INTERFACE FX_STATIC=1)
endif ()
set_target_properties(FX::${component} PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${FX_${component}_LIBRARY}")
set(created_targets ${created_targets} ${component})
endif ()
endforeach (component)
foreach (component ${created_targets})
if ("${component}" STREQUAL "Ds")
if (NOT TARGET FX::Core)
message(FATAL_ERROR "FX: Module 'Ds' depends on 'Core', which was not specified in find_package()")
endif ()
target_link_libraries(FX::Ds INTERFACE FX::Core)
endif ()
if ("${component}" STREQUAL "Term")
if (NOT TARGET FX::Core)
message(FATAL_ERROR "FX: Module 'Term' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET FX::Ds)
message(FATAL_ERROR "FX: Module 'Term' depends on 'Ds', which was not specified in find_package()")
endif ()
target_link_libraries(FX::Term INTERFACE FX::Core FX::Ds)
endif ()
if ("${component}" STREQUAL "Serial")
if (NOT TARGET FX::Core)
message(FATAL_ERROR "FX: Module 'Serial' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET FX::Ds)
message(FATAL_ERROR "FX: Module 'Serial' depends on 'Ds', which was not specified in find_package()")
endif ()
target_link_libraries(FX::Serial INTERFACE FX::Core FX::Ds)
endif ()
if ("${component}" STREQUAL "Cmd")
if (NOT TARGET FX::Core)
message(FATAL_ERROR "FX: Module 'Cmd' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET FX::Ds)
message(FATAL_ERROR "FX: Module 'Cmd' depends on 'Ds', which was not specified in find_package()")
endif ()
if (NOT TARGET FX::Term)
message(FATAL_ERROR "FX: Module 'Cmd' depends on 'Term', which was not specified in find_package()")
endif ()
target_link_libraries(FX::Cmd INTERFACE FX::Core FX::Ds FX::Term)
endif ()
if ("${component}" STREQUAL "Io")
if (NOT TARGET FX::Core)
message(FATAL_ERROR "FX: Module 'Io' depends on 'Core', which was not specified in find_package()")
endif ()
if (NOT TARGET FX::Ds)
message(FATAL_ERROR "FX: Module 'Io' depends on 'Ds', which was not specified in find_package()")
endif ()
target_link_libraries(FX::Io INTERFACE FX::Core FX::Ds)
endif ()
if ("${component}" STREQUAL "Compress")
if (NOT TARGET FX::Core)
message(FATAL_ERROR "FX: Module 'Compress' depends on 'Core', which was not specified in find_package()")
endif ()
target_link_libraries(FX::Compress INTERFACE FX::Core FX::Ds)
endif ()
endforeach (component)
endif()
+73 -77
View File
@@ -1,107 +1,103 @@
function(add_bluelib_module)
function(add_fx_assembly)
set(options)
set(one_value_args NAME)
set(multi_value_args
NAMESPACES
DEPENDENCIES
SUBDIRS
EXTRA_SOURCES
LIBS
INCLUDE_DIRS
DEFINES)
LIBS)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(module_name ${arg_NAME})
set(assembly_name ${arg_NAME})
string(REPLACE "." "/" assembly_path ${assembly_name})
set(assembly_target_name ${assembly_name})
string(REPLACE "." "_" assembly_token ${assembly_name})
string(TOUPPER ${assembly_token} assembly_token)
file(GLOB sources *.c *.h)
set(assembly_include_paths "")
set(assembly_sources ${CMAKE_CURRENT_SOURCE_DIR}/assembly.c)
foreach (dir ${arg_SUBDIRS})
file(GLOB dir_sources ${dir}/*.c ${dir}/*.h)
set(sources ${sources} ${dir_sources})
foreach (dir ${arg_NAMESPACES})
add_subdirectory(${fx_source_root}/${dir} ${fx_build_root}/namespaces/${dir})
set(assembly_sources ${assembly_sources} ${namespace_sources})
set(assembly_include_paths ${assembly_include_paths} ${namespace_include_paths})
endforeach (dir)
file(GLOB sys_sources sys/${b_system_name}/*.c sys/${b_system_name}/*.h)
set(root_header include/blue/${module_name}.h)
file(GLOB headers include/blue/${module_name}/*.h)
message(STATUS "Building assembly ${assembly_name}")
add_library(${assembly_target_name} SHARED
${assembly_sources})
string(REPLACE "-" "_" module_preproc_token ${module_name})
string(TOUPPER ${module_preproc_token} module_preproc_token)
set(module_preproc_token BLUELIB_${module_preproc_token})
target_include_directories(${assembly_target_name} PUBLIC ${assembly_include_paths})
message(STATUS "Building module ${module_name} (shared)")
add_library(blue-${module_name} SHARED
${sources}
${sys_sources}
${root_header}
${headers}
${arg_EXTRA_SOURCES})
message(STATUS "Building module ${module_name} (static)")
add_library(blue-${module_name}-s STATIC
${sources}
${sys_sources}
${root_header}
${headers}
${arg_EXTRA_SOURCES})
target_compile_definitions(${assembly_target_name} PUBLIC
FX_EXPORT=1
FX_ENABLE_FLOATING_POINT=${fx_enable_floating_point})
target_include_directories(blue-${module_name} PUBLIC include/)
target_include_directories(blue-${module_name}-s PUBLIC include/)
target_compile_definitions(blue-${module_name} PUBLIC
${module_preproc_token}
BLUELIB_EXPORT=1)
target_compile_definitions(blue-${module_name}-s PUBLIC
${module_preproc_token}
BLUELIB_EXPORT=1
BLUELIB_STATIC=1)
set_target_properties(blue-${module_name}
set_target_properties(${assembly_target_name}
PROPERTIES POSITION_INDEPENDENT_CODE ON)
foreach (dep ${arg_DEPENDENCIES})
target_link_libraries(blue-${module_name} blue-${dep})
target_link_libraries(blue-${module_name}-s blue-${dep}-s)
endforeach (dep)
foreach (lib ${arg_LIBS})
target_link_libraries(blue-${module_name} ${lib})
target_link_libraries(blue-${module_name}-s ${lib})
endforeach (lib)
foreach (dir ${arg_INCLUDE_DIRS})
target_include_directories(blue-${module_name} PRIVATE
${dir})
target_include_directories(blue-${module_name}-s PRIVATE
${dir})
endforeach (dir)
target_link_libraries(${assembly_target_name} ${internal_libs} ${arg_DEPENDENCIES})
target_include_directories(${assembly_target_name} PRIVATE ${internal_include_dirs})
foreach (def ${arg_DEFINES})
target_compile_definitions(blue-${module_name} PRIVATE
${def})
target_compile_definitions(blue-${module_name}-s PRIVATE
${def})
target_compile_definitions(${assembly_target_name} PRIVATE ${def})
endforeach (def)
set_target_properties(blue-${module_name} PROPERTIES
FOLDER "Shared/${module_name}")
set_target_properties(blue-${module_name}-s PROPERTIES
FOLDER "Static/${module_name}")
set_target_properties(${assembly_target_name} PROPERTIES
FOLDER "${assembly_name}")
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
target_compile_definitions(blue-${module_name} PRIVATE
BIG_ENDIAN)
target_compile_definitions(blue-${module_name}-s PRIVATE
target_compile_definitions(${assembly_target_name} PRIVATE
BIG_ENDIAN)
else()
target_compile_definitions(blue-${module_name} PRIVATE
LITTLE_ENDIAN)
target_compile_definitions(blue-${module_name}-s PRIVATE
target_compile_definitions(${assembly_target_name} PRIVATE
LITTLE_ENDIAN)
endif()
install(TARGETS blue-${module_name} blue-${module_name}-s)
install(FILES ${root_header} DESTINATION include/blue)
install(FILES ${headers} DESTINATION include/blue/${module_name})
endfunction(add_bluelib_module)
install(TARGETS ${assembly_target_name})
install(FILES ${headers} DESTINATION include/${assembly_path})
endfunction(add_fx_assembly)
macro(export_fx_namespace_details ns_name)
set(namespace_name ${ns_name})
string(REPLACE "." "/" namespace_path ${namespace_name})
set(namespace_target_name ${namespace_name})
set(namespace_include_paths ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
file(GLOB base_namespace_sources
*.c *.h
${CMAKE_CURRENT_SOURCE_DIR}/include/${namespace_path}/*.h)
foreach (dir ${source_dirs})
file(GLOB dir_sources ${dir}/*.c ${dir}/*.h)
set(dir_namespace_sources ${dir_namespace_sources} ${dir_sources})
endforeach (dir)
file(GLOB sys_sources
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.S)
file(GLOB headers include/${namespace_path}/*.h)
set(namespace_sources
${namespace_sources}
${base_namespace_sources}
${dir_namespace_sources}
${sys_sources}
${headers}
PARENT_SCOPE)
set(internal_include_dirs
${internal_include_dirs}
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/include
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/include
PARENT_SCOPE)
set(internal_libs ${internal_libs} PARENT_SCOPE)
set(internal_defines ${internal_defines} PARENT_SCOPE)
endmacro(export_fx_namespace_details)
-3
View File
@@ -1,3 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_module(NAME cmd DEPENDENCIES core ds term)
-174
View File
@@ -1,174 +0,0 @@
#include "command.h"
#include <blue/cmd.h>
#include <blue/ds/string.h>
#include <stdlib.h>
#include <string.h>
struct b_command_arg *b_command_arg_create(void)
{
struct b_command_arg *out = malloc(sizeof *out);
if (!out) {
return out;
}
memset(out, 0x0, sizeof *out);
return out;
}
void b_command_arg_destroy(struct b_command_arg *arg)
{
if (arg->arg_name) {
free(arg->arg_name);
}
if (arg->arg_description) {
free(arg->arg_description);
}
if (arg->arg_allowed_values) {
for (unsigned int i = 0; arg->arg_allowed_values[i]; i++) {
free(arg->arg_allowed_values[i]);
}
free(arg->arg_allowed_values);
}
free(arg);
}
b_status b_command_arg_set_name(struct b_command_arg *arg, const char *name)
{
char *n = b_strdup(name);
if (!n) {
return B_ERR_NO_MEMORY;
}
if (arg->arg_name) {
free(arg->arg_name);
arg->arg_name = NULL;
}
arg->arg_name = n;
return B_SUCCESS;
}
b_status b_command_arg_set_description(
struct b_command_arg *arg, const char *description)
{
char *desc = b_strdup(description);
if (!desc) {
return B_ERR_NO_MEMORY;
}
if (arg->arg_description) {
free(arg->arg_description);
arg->arg_description = NULL;
}
arg->arg_description = desc;
return B_SUCCESS;
}
b_status b_command_arg_set_nr_values(
struct b_command_arg *arg, enum b_command_arg_value_count nr_values)
{
arg->arg_nr_values = nr_values;
return B_SUCCESS;
}
b_status b_command_arg_set_allowed_values(
struct b_command_arg *arg, const char **allowed_values)
{
size_t count;
for (count = 0; allowed_values[count]; count++)
;
char **values = calloc(count + 1, sizeof *values);
if (!values) {
return B_ERR_NO_MEMORY;
}
for (size_t i = 0; i < count; i++) {
values[i] = b_strdup(allowed_values[i]);
if (!values[i]) {
/* TODO also free strings in `values` */
free(values);
return B_ERR_NO_MEMORY;
}
}
arg->arg_allowed_values = values;
return B_SUCCESS;
}
void z__b_get_arg_usage_string(struct b_command_arg *arg, bool colour, b_string *out)
{
bool optional = false, multi = false;
switch (arg->arg_nr_values) {
case B_ARG_0_OR_1_VALUES:
optional = true;
multi = false;
break;
case B_ARG_0_OR_MORE_VALUES:
optional = true;
multi = true;
break;
case B_ARG_1_OR_MORE_VALUES:
optional = false;
multi = true;
break;
default:
optional = false;
multi = false;
break;
}
if (optional) {
b_string_append_cstrf(
out, colour ? F_GREEN "[[%s]" : "[[%s]", arg->arg_name);
} else {
b_string_append_cstrf(
out, colour ? F_GREEN "<%s>" : "<%s>", arg->arg_name);
}
for (int i = 1; i < arg->arg_nr_values; i++) {
b_string_append_cstrf(out, " <%s>", arg->arg_name);
}
if (multi) {
b_string_append_cstr(out, "...");
}
if (colour) {
b_string_append_cstr(out, F_RESET);
}
}
void z__b_get_arg_description(struct b_command_arg *arg, b_string *out)
{
if (arg->arg_description) {
b_string_append_cstr(out, arg->arg_description);
}
if (!arg->arg_allowed_values) {
return;
}
if (arg->arg_description) {
b_string_append_cstr(out, " ");
}
b_string_append_cstr(out, "[[values:");
for (size_t i = 0; arg->arg_allowed_values[i]; i++) {
if (i > 0) {
b_string_append_cstr(out, ",");
}
b_string_append_cstrf(
out, " " F_GREEN "%s" F_RESET, arg->arg_allowed_values[i]);
}
b_string_append_cstr(out, "]");
}
-1050
View File
File diff suppressed because it is too large Load Diff
-1076
View File
File diff suppressed because it is too large Load Diff
-151
View File
@@ -1,151 +0,0 @@
#ifndef _B_COMMAND_H_
#define _B_COMMAND_H_
#include <blue/cmd.h>
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#include <blue/ds/string.h>
#define F_RED "[bright_red]"
#define F_GREEN "[bright_green]"
#define F_YELLOW "[bright_yellow]"
#define F_RED_BOLD "[bright_red,bold]"
#define F_GREEN_BOLD "[bright_green,bold]"
#define F_YELLOW_BOLD "[bright_yellow,bold]"
#define F_RESET "[reset]"
enum cmd_string_flags {
CMD_STR_COLOUR = 0x01u,
CMD_STR_DIRECT_USAGE = 0x02u,
};
enum b_command_usage_entry_type {
CMD_USAGE_NONE = 0,
CMD_USAGE_ARG,
CMD_USAGE_OPT,
CMD_USAGE_COMMAND,
};
struct b_command {
unsigned int b_id;
unsigned int b_parent_id;
struct b_command *b_parent;
enum b_command_flags b_flags;
char *b_name;
char *b_long_name;
char b_short_name;
char *b_description;
struct b_queue b_opt;
struct b_queue b_arg;
struct b_queue b_subcommands;
struct b_queue b_usage;
b_command_callback b_callback;
struct b_queue_entry b_entry;
struct b_btree_node b_node;
};
struct b_command_usage_entry {
struct b_queue_entry e_entry;
enum b_command_usage_entry_type e_type;
union {
struct b_command_option *e_opt;
struct b_command_arg *e_arg;
unsigned int e_cmd_id;
};
};
struct b_command_usage {
b_command_usage_flags u_flags;
struct b_queue_entry u_entry;
struct b_queue u_parts;
};
struct b_command_option {
unsigned int opt_id;
char *opt_long_name;
char opt_short_name;
char *opt_description;
// b_command_arg_value_count arg_nr_values;
// char **arg_allowed_values;
struct b_queue opt_args;
struct b_queue_entry opt_entry;
};
struct b_command_arg {
unsigned int arg_id;
char *arg_name;
char *arg_description;
b_command_arg_value_count arg_nr_values;
char **arg_allowed_values;
struct b_queue_entry arg_entry;
};
struct b_arglist_option {
unsigned int opt_id;
struct b_btree opt_values;
struct b_btree_node opt_node;
};
struct b_arglist {
size_t list_argc;
const char **list_argv;
unsigned int list_argv_last_command;
struct b_command *list_command;
struct b_btree list_options;
};
BLUE_API struct b_command *b_command_get_subcommand_with_name(
struct b_command *cmd, const char *name);
BLUE_API struct b_command *b_command_get_subcommand_with_long_name(
struct b_command *cmd, const char *long_name);
BLUE_API struct b_command *b_command_get_subcommand_with_short_name(
struct b_command *cmd, char short_name);
BLUE_API struct b_command_option *b_command_get_option_with_long_name(
struct b_command *cmd, const char *long_name);
BLUE_API struct b_command_option *b_command_get_option_with_short_name(
struct b_command *cmd, char short_name);
BLUE_API struct b_command_option *b_command_get_option_with_id(
struct b_command *cmd, unsigned int id);
BLUE_API struct b_command_arg *b_command_get_arg_with_id(
struct b_command *cmd, unsigned int id);
BLUE_API struct b_command_arg *b_command_option_get_arg_with_id(
struct b_command_option *opt, unsigned int id);
BLUE_API struct b_command_option *b_command_option_create(void);
BLUE_API void b_command_option_destroy(struct b_command_option *opt);
BLUE_API struct b_command_arg *b_command_arg_create(void);
BLUE_API void b_command_arg_destroy(struct b_command_arg *arg);
BLUE_API struct b_arglist *b_arglist_create(void);
BLUE_API b_status b_arglist_parse(
struct b_arglist *args, struct b_command **cmd, int argc,
const char **argv);
BLUE_API void b_arglist_destroy(struct b_arglist *args);
BLUE_API b_string *z__b_command_default_usage_string(
struct b_command *cmd, struct b_command_option *with_opt,
const struct b_arglist *args);
BLUE_API void z__b_get_arg_usage_string(
struct b_command_arg *arg, bool colour, b_string *out);
BLUE_API void z__b_get_arg_description(struct b_command_arg *arg, b_string *out);
BLUE_API void z__b_get_option_usage_string(
struct b_command_option *opt, enum cmd_string_flags flags, b_string *out);
BLUE_API void z__b_get_option_description(
struct b_command_option *opt, b_string *out);
#endif
-289
View File
@@ -1,289 +0,0 @@
#ifndef BLUE_CMD_H_
#define BLUE_CMD_H_
#include <blue/core/btree.h>
#include <blue/core/init.h>
#include <blue/core/iterator.h>
#include <blue/core/queue.h>
#include <blue/ds/array.h>
#include <stdbool.h>
#include <stdint.h>
#define b_arglist_foreach(it, q) \
for (int z__b_unique_name() = b_arglist_iterator_begin( \
q, B_COMMAND_INVALID_ID, B_COMMAND_INVALID_ID, (it)); \
b_arglist_iterator_is_valid(it); b_arglist_iterator_next(it))
#define b_arglist_foreach_filtered(it, q, opt_id, arg_id) \
for (int z__b_unique_name() \
= b_arglist_iterator_begin(q, opt_id, arg_id, (it)); \
b_arglist_iterator_is_valid(it); b_arglist_iterator_next(it))
#define b_arglist_option_foreach(it, q) \
for (int z__b_unique_name() \
= b_arglist_option_iterator_begin(q, B_COMMAND_INVALID_ID, (it)); \
b_arglist_option_iterator_is_valid(it); \
b_arglist_option_iterator_next(it))
#define b_arglist_option_foreach_filtered(it, q, opt_id) \
for (int z__b_unique_name() \
= b_arglist_option_iterator_begin(q, opt_id, (it)); \
b_arglist_option_iterator_is_valid(it); \
b_arglist_option_iterator_next(it))
#define B_COMMAND(id, parent_id) \
static b_command *command_##id = NULL; \
static void __init_##id( \
b_command *, b_command_option *, b_command_arg *, \
b_command_usage *); \
B_INIT(init_##id) \
{ \
command_##id = b_command_create(id); \
if ((parent_id) != B_COMMAND_INVALID_ID) { \
b_command_set_parent(command_##id, parent_id); \
} \
__init_##id(command_##id, NULL, NULL, NULL); \
b_command_register(command_##id); \
} \
static void __init_##id( \
b_command *this_cmd, b_command_option *this_opt, \
b_command_arg *this_arg, b_command_usage *this_usage)
#define B_COMMAND_NAME(name) b_command_set_name(this_cmd, (name))
#define B_COMMAND_LONG_NAME(name) b_command_set_long_name(this_cmd, (name))
#define B_COMMAND_SHORT_NAME(name) b_command_set_short_name(this_cmd, (name))
#define B_COMMAND_DESC(desc) b_command_set_description(this_cmd, (desc))
#define B_COMMAND_FLAGS(flags) b_command_set_flags(this_cmd, (flags))
#define B_COMMAND_FUNCTION(fn) b_command_set_callback(this_cmd, (fn))
#define B_COMMAND_OPTION(id) \
b_command_option *opt_##id = b_command_add_option(this_cmd, (id)); \
this_opt = opt_##id; \
if (this_opt)
#define B_COMMAND_OPTION_GEN(id) \
b_command_option *z__b_unique_name() \
= b_command_add_option(this_cmd, (id)); \
this_opt = z__b_unique_name(); \
if (this_opt)
#define B_COMMAND_HELP_OPTION() \
do { \
b_command_option *opt \
= b_command_add_option(this_cmd, B_COMMAND_OPTION_HELP); \
b_command_option_set_description(opt, "Show this help message"); \
b_command_option_set_short_name(opt, 'h'); \
b_command_option_set_long_name(opt, "help"); \
} while (0)
#define B_OPTION_LONG_NAME(name) \
b_command_option_set_long_name(this_opt, (name))
#define B_OPTION_SHORT_NAME(name) \
b_command_option_set_short_name(this_opt, (name))
#define B_OPTION_DESC(desc) b_command_option_set_description(this_opt, (desc))
#define B_OPTION_ARG(id) \
b_command_arg *arg_##id = b_command_option_add_arg(this_opt, (id)); \
this_arg = arg_##id; \
if (this_arg)
#define B_COMMAND_ARG(id) \
b_command_arg *arg_##id = b_command_add_arg(this_cmd, (id)); \
this_arg = arg_##id; \
if (this_arg)
#define B_ARG_NAME(name) b_command_arg_set_name(this_arg, (name))
#define B_ARG_DESC(desc) b_command_arg_set_description(this_arg, (desc))
#define B_ARG_NR_VALUES(nr_values) \
b_command_arg_set_nr_values(this_arg, (nr_values))
#define B_ARG_ALLOWED_VALUES(...) \
static const char *allowed_values[] = { \
__VA_ARGS__, \
NULL, \
}; \
b_command_arg_set_allowed_values(this_arg, allowed_values)
#define B_COMMAND_USAGE() \
b_command_usage *z__b_unique_name() = b_command_add_usage(this_cmd); \
this_usage = z__b_unique_name(); \
if (this_usage)
#define B_COMMAND_USAGE_COMMAND(cmd_id) \
b_command_usage_add_command(this_usage, cmd_id)
#define B_COMMAND_USAGE_COMMAND_PLACEHOLDER() \
b_command_usage_add_command(this_usage, B_COMMAND_INVALID_ID)
#define B_COMMAND_USAGE_OPT(opt_id) \
b_command_usage_add_option(this_usage, opt_##opt_id)
#define B_COMMAND_USAGE_OPT_PLACEHOLDER() \
b_command_usage_add_option(this_usage, NULL)
#define B_COMMAND_USAGE_ARG(opt_id) \
b_command_usage_add_arg(this_usage, arg_##opt_id)
#define B_COMMAND_USAGE_ARG_PLACEHOLDER() \
b_command_usage_add_arg(this_usage, NULL)
#define B_COMMAND_OPTION_HELP ((uintptr_t)0xF0000001)
#define B_COMMAND_INVALID_ID ((uintptr_t)0xFFFFFFFF)
typedef enum b_command_arg_value_count {
B_ARG_0_OR_1_VALUES = -1,
B_ARG_0_OR_MORE_VALUES = -2,
B_ARG_1_OR_MORE_VALUES = -3,
} b_command_arg_value_count;
typedef enum b_command_arg_type {
B_COMMAND_ARG_NONE = 0,
B_COMMAND_ARG_STRING,
B_COMMAND_ARG_SIGNED_INT,
B_COMMAND_ARG_UNSIGNED_INT,
B_COMMAND_ARG_INT = B_COMMAND_ARG_SIGNED_INT,
} b_command_arg_type;
typedef enum b_command_flags {
B_COMMAND_SHOW_HELP_BY_DEFAULT = 0x01u,
} b_command_flags;
typedef enum b_command_usage_flags {
B_COMMAND_USAGE_SHOW_OPTIONS = 0x01u,
} b_command_usage_flags;
typedef struct b_arglist_value {
unsigned int val_id;
b_command_arg_type val_type;
struct b_btree_node val_node;
union {
char *val_str;
long long val_int;
unsigned long long val_uint;
};
} b_arglist_value;
typedef struct b_arglist_iterator {
size_t i;
unsigned int opt_id;
struct b_arglist_value *value;
b_btree_node *_opt_it, *_arg_it;
unsigned int _opt_filter, _arg_filter;
} b_arglist_iterator;
typedef struct b_arglist_option_iterator {
size_t i;
unsigned int opt_id;
struct b_arglist_option *opt;
b_btree_node *_opt_it;
unsigned int _opt_filter;
} b_arglist_option_iterator;
typedef struct b_command b_command;
typedef struct b_command_option b_command_option;
typedef struct b_command_arg b_command_arg;
typedef struct b_command_usage b_command_usage;
typedef struct b_arglist b_arglist;
typedef struct b_arglist_option b_arglist_option;
typedef int (*b_command_callback)(
const b_command *, const b_arglist *, const b_array *);
BLUE_API b_command *b_command_create(unsigned int id);
BLUE_API void b_command_destroy(b_command *cmd);
BLUE_API b_status b_command_register(b_command *cmd);
BLUE_API int b_command_dispatch(unsigned int cmd_id, int argc, const char **argv);
BLUE_API b_status b_command_set_name(b_command *cmd, const char *name);
BLUE_API b_status b_command_set_long_name(b_command *cmd, const char *name);
BLUE_API b_status b_command_set_short_name(b_command *cmd, char name);
BLUE_API b_status b_command_set_flags(b_command *cmd, b_command_flags flags);
BLUE_API b_status b_command_set_description(b_command *cmd, const char *description);
BLUE_API b_status b_command_set_callback(
b_command *cmd, b_command_callback callback);
BLUE_API b_status b_command_set_parent(b_command *cmd, unsigned int parent_id);
BLUE_API b_command_option *b_command_add_option(b_command *cmd, int id);
BLUE_API b_command_arg *b_command_add_arg(b_command *cmd, int id);
BLUE_API b_command_usage *b_command_add_usage(b_command *cmd);
BLUE_API const b_command_option *b_command_get_option(const b_command *cmd, int id);
BLUE_API const char *b_command_option_get_long_name(const b_command_option *opt);
BLUE_API char b_command_option_get_short_name(const b_command_option *opt);
BLUE_API const char *b_command_option_get_description(b_command_option *opt);
BLUE_API b_status b_command_option_set_long_name(
b_command_option *opt, const char *name);
BLUE_API b_status b_command_option_set_short_name(b_command_option *opt, char name);
BLUE_API b_status b_command_option_set_description(
b_command_option *opt, const char *description);
BLUE_API b_command_arg *b_command_option_add_arg(b_command_option *opt, int id);
BLUE_API b_status b_command_arg_set_name(b_command_arg *arg, const char *name);
BLUE_API b_status b_command_arg_set_description(
b_command_arg *arg, const char *description);
BLUE_API b_status b_command_arg_set_nr_values(
b_command_arg *arg, b_command_arg_value_count nr_values);
BLUE_API b_status b_command_arg_set_allowed_values(
b_command_arg *arg, const char **allowed_values);
BLUE_API b_status b_command_usage_add_option(
b_command_usage *usage, b_command_option *opt);
BLUE_API b_status b_command_usage_add_arg(
b_command_usage *usage, b_command_arg *opt);
BLUE_API b_status b_command_usage_add_command(
b_command_usage *usage, unsigned int cmd_id);
BLUE_API b_status b_arglist_get_string(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
unsigned int index, const char **out);
BLUE_API b_status b_arglist_get_int(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
unsigned int index, long long *out);
BLUE_API b_status b_arglist_get_uint(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
unsigned int index, unsigned long long *out);
BLUE_API b_status b_arglist_get_option(
const b_arglist *args, unsigned int opt_id, unsigned int index,
b_arglist_option **out);
BLUE_API size_t b_arglist_get_count(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id);
BLUE_API b_status b_arglist_report_missing_option(
const b_arglist *args, unsigned int opt_id);
BLUE_API b_status b_arglist_report_unexpected_arg(
const b_arglist *args, const char *value);
BLUE_API b_status b_arglist_report_invalid_arg_value(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
const char *value);
BLUE_API b_status b_arglist_report_missing_args(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
size_t nr_supplied);
BLUE_API b_status b_arglist_option_get_value(
const b_arglist_option *opt, unsigned int arg_id, unsigned int index,
b_arglist_value **out);
BLUE_API int b_arglist_iterator_begin(
const b_arglist *args, unsigned int opt_filter, unsigned int arg_filter,
b_arglist_iterator *it);
BLUE_API bool b_arglist_iterator_next(b_arglist_iterator *it);
BLUE_API bool b_arglist_iterator_is_valid(const b_arglist_iterator *it);
BLUE_API int b_arglist_option_iterator_begin(
const b_arglist *args, unsigned int opt_filter,
b_arglist_option_iterator *it);
BLUE_API bool b_arglist_option_iterator_next(b_arglist_option_iterator *it);
BLUE_API bool b_arglist_option_iterator_is_valid(
const b_arglist_option_iterator *it);
#endif
-273
View File
@@ -1,273 +0,0 @@
#include "command.h"
#include <blue/cmd.h>
#include <blue/ds/string.h>
#include <stdlib.h>
#include <string.h>
struct b_command_option *b_command_option_create(void)
{
struct b_command_option *out = malloc(sizeof *out);
if (!out) {
return out;
}
memset(out, 0x0, sizeof *out);
return out;
}
void b_command_option_destroy(struct b_command_option *opt)
{
if (opt->opt_long_name) {
free(opt->opt_long_name);
}
if (opt->opt_description) {
free(opt->opt_description);
}
struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
while (entry) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, entry, arg_entry);
struct b_queue_entry *next = b_queue_next(entry);
b_queue_delete(&opt->opt_args, entry);
b_command_arg_destroy(arg);
entry = next;
}
free(opt);
}
const char *b_command_option_get_long_name(const struct b_command_option *opt)
{
return opt->opt_long_name;
}
char b_command_option_get_short_name(const struct b_command_option *opt)
{
return opt->opt_short_name;
}
const char *b_command_option_get_description(struct b_command_option *opt)
{
return opt->opt_description;
}
b_status b_command_option_set_long_name(
struct b_command_option *opt, const char *name)
{
char *n = b_strdup(name);
if (!n) {
return B_ERR_NO_MEMORY;
}
if (opt->opt_long_name) {
free(opt->opt_long_name);
opt->opt_long_name = NULL;
}
opt->opt_long_name = n;
return B_SUCCESS;
}
b_status b_command_option_set_short_name(struct b_command_option *opt, char name)
{
opt->opt_short_name = name;
return B_SUCCESS;
}
b_status b_command_option_set_description(
struct b_command_option *opt, const char *description)
{
char *desc = b_strdup(description);
if (!desc) {
return B_ERR_NO_MEMORY;
}
if (opt->opt_description) {
free(opt->opt_description);
opt->opt_description = NULL;
}
opt->opt_description = desc;
return B_SUCCESS;
}
struct b_command_arg *b_command_option_add_arg(struct b_command_option *opt, int id)
{
struct b_command_arg *arg = malloc(sizeof *arg);
if (!arg) {
return NULL;
}
memset(arg, 0x0, sizeof *arg);
arg->arg_id = id;
b_queue_push_back(&opt->opt_args, &arg->arg_entry);
return arg;
}
void z__b_get_option_description(struct b_command_option *opt, b_string *out)
{
if (opt->opt_description) {
b_string_append_cstr(out, opt->opt_description);
}
size_t nr_args = b_queue_length(&opt->opt_args);
bool close_bracket = false;
size_t i = 0;
struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
while (entry) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg || !arg->arg_allowed_values) {
goto skip;
}
if (i > 0) {
b_string_append_cstr(out, "; ");
} else {
b_string_append_cstr(out, " [[");
close_bracket = true;
}
if (nr_args > 1) {
b_string_append_cstrf(
out, "values for `%s`:", arg->arg_name);
} else {
b_string_append_cstr(out, "values:");
}
for (size_t i = 0; arg->arg_allowed_values[i]; i++) {
if (i > 0) {
b_string_append_cstr(out, ",");
}
b_string_append_cstrf(
out, " " F_GREEN "%s" F_RESET,
arg->arg_allowed_values[i]);
}
skip:
i++;
entry = b_queue_next(entry);
}
if (close_bracket) {
b_string_append_cstr(out, "]");
}
}
void z__b_get_option_usage_string(
struct b_command_option *opt, enum cmd_string_flags flags, b_string *out)
{
if (flags & CMD_STR_DIRECT_USAGE) {
b_string_append_cstr(out, "{");
}
if (opt->opt_short_name) {
b_string_append_cstrf(
out,
(flags & CMD_STR_COLOUR) ? F_GREEN "-%c" F_RESET : "-%c",
opt->opt_short_name);
}
if (opt->opt_short_name && opt->opt_long_name) {
b_string_append_cstr(
out, (flags & CMD_STR_DIRECT_USAGE) ? "|" : ", ");
}
if (opt->opt_long_name) {
b_string_append_cstrf(
out,
(flags & CMD_STR_COLOUR) ? F_GREEN "--%s" F_RESET : "--%s",
opt->opt_long_name);
}
if (flags & CMD_STR_DIRECT_USAGE) {
b_string_append_cstr(out, "}");
}
struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
while (entry) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, entry, arg_entry);
if (!arg) {
goto skip;
}
bool optional = false, multi = false;
switch (arg->arg_nr_values) {
case B_ARG_0_OR_1_VALUES:
optional = true;
multi = false;
break;
case B_ARG_0_OR_MORE_VALUES:
optional = true;
multi = true;
break;
case B_ARG_1_OR_MORE_VALUES:
optional = false;
multi = true;
break;
default:
optional = false;
multi = false;
break;
}
if (optional) {
b_string_append_cstrf(
out,
(flags & CMD_STR_COLOUR) ? " " F_GREEN "[%s]"
: " [%s]",
arg->arg_name);
} else {
b_string_append_cstrf(
out,
(flags & CMD_STR_COLOUR) ? " " F_GREEN "<%s>"
: " <%s>",
arg->arg_name);
}
for (int i = 1; i < arg->arg_nr_values; i++) {
b_string_append_cstrf(out, " <%s>", arg->arg_name);
}
if (multi) {
b_string_append_cstr(out, "...");
}
if (flags & CMD_STR_COLOUR) {
b_string_append_cstr(out, F_RESET);
}
skip:
entry = b_queue_next(entry);
}
}
struct b_command_arg *b_command_option_get_arg_with_id(
struct b_command_option *opt, unsigned int id)
{
struct b_queue_entry *entry = b_queue_first(&opt->opt_args);
while (entry) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, entry, arg_entry);
if (arg->arg_id == id) {
return arg;
}
entry = b_queue_next(entry);
}
return NULL;
}
-195
View File
@@ -1,195 +0,0 @@
#include "command.h"
#include <assert.h>
#include <blue/core/stringstream.h>
#include <blue/ds/string.h>
#include <blue/term/print.h>
#include <stdio.h>
enum b_status b_arglist_report_missing_option(
const b_arglist *args, unsigned int opt_id)
{
struct b_command_option *opt = NULL;
if (opt_id != B_COMMAND_INVALID_ID) {
opt = b_command_get_option_with_id(args->list_command, opt_id);
}
if (!opt) {
return B_ERR_INVALID_ARGUMENT;
}
b_string *opt_string = b_string_create();
z__b_get_option_usage_string(opt, 0, opt_string);
b_stringstream *opt_name = b_stringstream_create();
int opt_names = 0;
if (opt->opt_short_name) {
opt_names++;
}
if (opt->opt_long_name) {
opt_names++;
}
if (opt_names == 2) {
b_stream_write_fmt(
opt_name, NULL, "-%c / --%s", opt->opt_short_name,
opt->opt_long_name);
} else if (opt->opt_short_name) {
b_stream_write_fmt(opt_name, NULL, "-%c", opt->opt_short_name);
} else if (opt->opt_long_name) {
b_stream_write_fmt(opt_name, NULL, "--%s", opt->opt_long_name);
}
b_err("required option `" F_YELLOW "%s" F_RESET "` was not specified.",
b_stringstream_ptr(opt_name));
b_i("usage: %s", b_string_ptr(opt_string));
b_i("for more information, use `" F_YELLOW "--help" F_RESET "`");
b_string_unref(opt_string);
b_stringstream_unref(opt_name);
return B_SUCCESS;
}
enum b_status b_arglist_report_unexpected_arg(
const b_arglist *args, const char *value)
{
b_string *usage = z__b_command_default_usage_string(
args->list_command, NULL, args);
b_err("unexpected argument '" F_YELLOW "%s" F_RESET "' found.", value);
b_i("usage: %s", b_string_ptr(usage));
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
return B_SUCCESS;
}
enum b_status b_arglist_report_invalid_arg_value(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
const char *value)
{
struct b_command_option *opt = NULL;
struct b_command_arg *arg = NULL;
if (opt_id != B_COMMAND_INVALID_ID) {
opt = b_command_get_option_with_id(args->list_command, opt_id);
}
if (arg_id != B_COMMAND_INVALID_ID) {
arg = opt ? b_command_option_get_arg_with_id(opt, arg_id)
: b_command_get_arg_with_id(args->list_command, arg_id);
}
b_string *usage = z__b_command_default_usage_string(
args->list_command, opt, args);
b_string *opt_string = b_string_create();
if (opt) {
z__b_get_option_usage_string(opt, 0, opt_string);
} else {
z__b_get_arg_usage_string(arg, 0, opt_string);
}
b_err("invalid value '" F_YELLOW "%s" F_RESET "' for '" F_YELLOW
"%s" F_RESET "'.",
value, b_string_ptr(opt_string));
if (opt) {
b_i("'" F_YELLOW "%s" F_RESET
"' accepts the following values for '" F_YELLOW "%s" F_RESET
"':",
b_string_ptr(opt_string), arg->arg_name);
} else {
b_i("'" F_YELLOW "%s" F_RESET "' accepts the following values:",
b_string_ptr(opt_string));
}
for (int i = 0; arg->arg_allowed_values[i]; i++) {
b_printf(
" * " F_GREEN "%s" F_RESET "\n",
arg->arg_allowed_values[i]);
}
b_printf("\n");
b_i("usage: %s", b_string_ptr(usage));
b_i("for more information, use '" F_YELLOW "--help" F_RESET);
b_string_unref(usage);
b_string_unref(opt_string);
return B_SUCCESS;
}
enum b_status b_arglist_report_missing_args(
const b_arglist *args, unsigned int opt_id, unsigned int arg_id,
size_t args_supplied)
{
struct b_command_option *opt = NULL;
struct b_command_arg *arg = NULL;
if (opt_id != B_COMMAND_INVALID_ID) {
opt = b_command_get_option_with_id(args->list_command, opt_id);
assert(opt);
}
if (arg_id != B_COMMAND_INVALID_ID) {
arg = opt ? b_command_option_get_arg_with_id(opt, arg_id)
: b_command_get_arg_with_id(args->list_command, arg_id);
assert(arg);
}
b_string *usage = z__b_command_default_usage_string(
args->list_command, opt, args);
b_string *opt_string = b_string_create();
if (opt) {
z__b_get_option_usage_string(opt, 0, opt_string);
} else {
z__b_get_arg_usage_string(arg, 0, opt_string);
}
char supplied_arg_str[64];
if (args_supplied == 0) {
snprintf(
supplied_arg_str, sizeof supplied_arg_str,
F_RED_BOLD "none" F_RESET " were provided");
} else if (args_supplied == 1) {
snprintf(
supplied_arg_str, sizeof supplied_arg_str,
"only " F_YELLOW_BOLD "%zu" F_RESET " was provided",
args_supplied);
} else {
snprintf(
supplied_arg_str, sizeof supplied_arg_str,
"only " F_YELLOW_BOLD "%zu" F_RESET " were provided",
args_supplied);
}
char required_arg_count[64];
switch (arg->arg_nr_values) {
case B_ARG_1_OR_MORE_VALUES:
snprintf(
required_arg_count, sizeof required_arg_count,
"one or more");
break;
default:
snprintf(
required_arg_count, sizeof required_arg_count, "%d",
arg->arg_nr_values);
}
b_err("argument `" F_YELLOW "%s" F_RESET "` requires " F_GREEN_BOLD
"%s" F_RESET " `" F_YELLOW "%s" F_RESET "` value%s, but %s.",
b_string_ptr(opt_string), required_arg_count, arg->arg_name,
(arg->arg_nr_values == 1) ? "" : "s", supplied_arg_str);
b_i("usage: %s", b_string_ptr(usage));
b_i("for more information, use '" F_YELLOW "--help" F_RESET "'");
b_string_unref(usage);
b_string_unref(opt_string);
return B_SUCCESS;
}
-19
View File
@@ -1,19 +0,0 @@
include(../cmake/Templates.cmake)
find_package(ZSTD)
if (ZSTD_FOUND)
set(libs ${libs} ${ZSTD_LIBRARY})
set(include_dirs ${include_dirs} ${ZSTD_INCLUDE_DIR})
set(function_sources ${function_sources} ${CMAKE_CURRENT_SOURCE_DIR}/function/zstd.c)
set(defines ${defines} B_COMPRESSOR_SUPPORTED_ZSTD)
message(STATUS "Enabling ZSTD support in blue-compress")
endif ()
add_bluelib_module(
NAME compress
DEPENDENCIES core
EXTRA_SOURCES ${function_sources}
DEFINES ${defines}
LIBS ${libs}
INCLUDE_DIRS ${include_dirs})
-239
View File
@@ -1,239 +0,0 @@
#include <assert.h>
#include <blue/compress/compressor.h>
#include <blue/core/ringbuffer.h>
#include <stdlib.h>
#include <string.h>
#define COMPRESSOR_DISPATCH_STATIC(func, compressor, ...) \
do { \
struct compressor_data _compressor; \
enum b_status status \
= compressor_get_data(compressor, &_compressor); \
if (!B_OK(status)) { \
return status; \
} \
return func(&_compressor, __VA_ARGS__); \
} while (0)
#define COMPRESSOR_DISPATCH_STATIC_0(func, compressor) \
do { \
struct compressor_data _compressor; \
enum b_status status \
= compressor_get_data(compressor, &_compressor); \
if (!B_OK(status)) { \
return status; \
} \
return func(&_compressor); \
} while (0)
/*** PRIVATE DATA *************************************************************/
struct compressor_data {
b_compressor *c_obj;
b_compressor_class *c_ops;
b_compressor_data *c_data;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static enum b_status compressor_get_data(
b_compressor *compressor, struct compressor_data *out)
{
out->c_obj = compressor;
return b_object_get_data(
compressor, B_TYPE_COMPRESSOR, NULL, (void **)&out->c_data,
(void **)&out->c_ops);
}
static enum b_status compressor_get_mode(
struct compressor_data *p, enum b_compressor_mode *out)
{
if (out) {
*out = p->c_data->c_mode;
}
return B_SUCCESS;
}
static enum b_status compressor_set_mode(
struct compressor_data *p, enum b_compressor_mode mode)
{
if (!p->c_ops->c_set_mode) {
return B_ERR_NOT_SUPPORTED;
}
return p->c_ops->c_set_mode(p->c_obj, mode);
}
static enum b_status compressor_set_buffer(
struct compressor_data *p, b_ringbuffer *inbuf, b_ringbuffer *outbuf)
{
p->c_data->c_in = inbuf;
p->c_data->c_out = outbuf;
return B_SUCCESS;
}
static enum b_status compress(struct compressor_data *p)
{
if (p->c_data->c_mode != B_COMPRESSOR_MODE_COMPRESS) {
return B_ERR_BAD_STATE;
}
if (!p->c_ops->c_compress) {
return B_ERR_NOT_SUPPORTED;
}
return p->c_ops->c_compress(p->c_obj);
}
static enum b_status decompress(struct compressor_data *p)
{
if (p->c_data->c_mode != B_COMPRESSOR_MODE_DECOMPRESS) {
return B_ERR_BAD_STATE;
}
if (!p->c_ops->c_decompress) {
return B_ERR_NOT_SUPPORTED;
}
return p->c_ops->c_decompress(p->c_obj);
}
static enum b_status compressor_step(struct compressor_data *p)
{
switch (p->c_data->c_mode) {
case B_COMPRESSOR_MODE_COMPRESS:
return compress(p);
case B_COMPRESSOR_MODE_DECOMPRESS:
return decompress(p);
default:
return B_ERR_BAD_STATE;
}
}
static enum b_status compressor_end(struct compressor_data *p)
{
if (p->c_data->c_mode != B_COMPRESSOR_MODE_COMPRESS) {
return B_SUCCESS;
}
if (!p->c_ops->c_compress_end) {
return B_ERR_NOT_SUPPORTED;
}
while (b_ringbuffer_available_data_remaining(p->c_data->c_in)) {
if (!b_ringbuffer_write_capacity_remaining(p->c_data->c_out)) {
return B_ERR_NO_SPACE;
}
enum b_status status = compressor_step(p);
if (!B_OK(status)) {
return status;
}
}
return p->c_ops->c_compress_end(p->c_obj);
}
static enum b_status compressor_reset(struct compressor_data *p)
{
p->c_data->c_flags &= ~B_COMPRESSOR_EOF;
if (p->c_ops->c_reset) {
return p->c_ops->c_reset(p->c_obj);
}
return B_SUCCESS;
}
static bool compressor_eof(const struct compressor_data *p)
{
return (p->c_data->c_flags & B_COMPRESSOR_EOF) != 0;
}
/*** PUBLIC FUNCTIONS *********************************************************/
enum b_status b_compressor_get_buffer_size(
b_type type, b_compressor_mode mode, size_t *inbuf_size, size_t *outbuf_size)
{
b_class *c = b_class_get(type);
if (!c) {
return B_ERR_INVALID_ARGUMENT;
}
b_compressor_class *ops = b_class_get_interface(c, B_TYPE_COMPRESSOR);
if (!ops) {
return B_ERR_INVALID_ARGUMENT;
}
if (!ops->c_buffer_size) {
return B_ERR_NOT_SUPPORTED;
}
return ops->c_buffer_size(mode, inbuf_size, outbuf_size);
}
enum b_status b_compressor_get_mode(
const b_compressor *compressor, enum b_compressor_mode *out)
{
COMPRESSOR_DISPATCH_STATIC(
compressor_get_mode, (b_compressor *)compressor, out);
}
enum b_status b_compressor_set_mode(
b_compressor *compressor, enum b_compressor_mode mode)
{
COMPRESSOR_DISPATCH_STATIC(compressor_set_mode, compressor, mode);
}
enum b_status b_compressor_set_buffer(
b_compressor *compressor, b_ringbuffer *inbuf, b_ringbuffer *outbuf)
{
COMPRESSOR_DISPATCH_STATIC(compressor_set_buffer, compressor, inbuf, outbuf);
}
enum b_status b_compressor_step(b_compressor *compressor)
{
COMPRESSOR_DISPATCH_STATIC_0(compressor_step, compressor);
}
enum b_status b_compressor_end(b_compressor *compressor)
{
COMPRESSOR_DISPATCH_STATIC_0(compressor_end, compressor);
}
enum b_status b_compressor_reset(b_compressor *compressor)
{
COMPRESSOR_DISPATCH_STATIC_0(compressor_reset, compressor);
}
bool b_compressor_eof(const b_compressor *compressor)
{
COMPRESSOR_DISPATCH_STATIC_0(compressor_eof, (b_compressor *)compressor);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void compressor_init(b_object *obj, void *priv)
{
}
static void compressor_fini(b_object *obj, void *priv)
{
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_compressor)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_compressor)
B_TYPE_DEFINITION_BEGIN(b_compressor)
B_TYPE_ID(0x452ee0f9, 0xfe12, 0x48a1, 0xb596, 0xad5b7a3940e7);
B_TYPE_CLASS(b_compressor_class);
B_TYPE_INSTANCE_PROTECTED(b_compressor_data);
B_TYPE_INSTANCE_INIT(compressor_init);
B_TYPE_INSTANCE_FINI(compressor_fini);
B_TYPE_DEFINITION_END(b_compressor)
-890
View File
@@ -1,890 +0,0 @@
#include <blue/compress/compressor.h>
#include <blue/compress/cstream.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
enum cstream_flags {
CSTREAM_CURSOR_MOVED = 0x01u,
};
struct b_cstream_p {
enum cstream_flags s_flags;
b_stream *s_endpoint;
b_compressor *s_compressor;
/* s_in is the input buffer, and s_out is the output buffer.
*
* the input buffer holds data that will be provided to the
* (de)compression function. in compression mode, this data is provided
* by the code using the cstream (via b_cstream_write). in decompression
* mode, this data is read from s_endpoint.
*
* the output buffer holds data produced by the (de)compression
* function. in compression mode, this data will be written to
* s_endpoint. in decompression mode, this data will be returned to the
* code using the cstream (via b_cstream_read)
*
* heavy usage of cstream's compressed sections facility can result
* in the input buffer holding uncompressed data while the stream is in
* decompression mode. this is handled by the uncompressed read code path.
*/
b_ringbuffer *s_in, *s_out;
b_compressor_mode s_mode;
unsigned int s_compression_depth;
/* tracks the number of bytes read from or written to the endpoint.
* this counter is not reset at the beginning/end of each section.
*
* during compressed sections, this counter is incremented by the number
* of compressed bytes written/consumed.
*
* during uncompressed sections, this counter is incremented by the
* number of uncompressed bytes written/returned.
*
* this does not include bytes read/written while the cursor is moved.
*/
size_t s_tx_bytes;
/* tracks the number of compressed bytes that have passed through this
* stream in the current section.
*
* in compression mode, this tracks the number of post-compression bytes
* that have been written to the endpoint within the current section,
* including any bytes written during end_compression_section()
*
* in decompression mode, this tracks the number of compressed bytes
* that were decompressed while reading the current section. it does not
* include any uncompressed bytes that may have been read from the
* endpoint while reading a compressed section due to cstream's
* read-ahead caching behaviour.
*/
size_t s_tx_bytes_compressed;
/* tracks the number of uncompressed bytes that have passed through this
* stream in the current section.
*
* in compression mode, this tracks the number of bytes given to
* b_cstream_write
*
* in decompression mode, this tracks the number of bytes returned by
* b_cstream_read
*/
size_t s_tx_bytes_uncompressed;
/* when the endpoint cursor is moved, the previous cursor position is
* saved here so it can be restored later */
size_t s_cursor;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static enum b_status read_cursor(
struct b_cstream_p *stream, void *buf, size_t count, size_t *out_nr_read)
{
return b_stream_read_bytes(stream->s_endpoint, buf, count, out_nr_read);
}
static enum b_status read_uncompressed(
struct b_cstream_p *stream, void *buf, size_t count, size_t *out_nr_read)
{
size_t remaining = count;
unsigned char *dest = buf;
size_t nr_read_from_buf = 0;
size_t nr_read_from_endpoint = 0;
enum b_status status = B_SUCCESS;
/* liberal usage of begin_compressed_section and end_compressed_section
* can result in uncompressed data getting stuck in the input buffer.
* return any data remaining in the input buffer before reading more
* from the endpoint */
while (remaining > 0) {
const void *data;
size_t available;
status = b_ringbuffer_open_read_buffer(
stream->s_in, &data, &available);
if (!B_OK(status)) {
break;
}
size_t to_copy = remaining;
if (to_copy > available) {
to_copy = available;
}
memcpy(dest, data, to_copy);
b_ringbuffer_close_read_buffer(stream->s_in, &data, to_copy);
stream->s_tx_bytes_uncompressed += to_copy;
stream->s_tx_bytes += to_copy;
dest += to_copy;
remaining -= to_copy;
nr_read_from_buf += to_copy;
}
if (remaining == 0) {
*out_nr_read = nr_read_from_buf;
return B_SUCCESS;
}
status = b_stream_read_bytes(
stream->s_endpoint, dest, remaining, &nr_read_from_endpoint);
stream->s_tx_bytes_uncompressed += nr_read_from_endpoint;
stream->s_tx_bytes += nr_read_from_endpoint;
*out_nr_read = nr_read_from_endpoint + nr_read_from_buf;
return status;
}
/* read compressed data from the endpoint and store it in the input buffer.
* note that uncompressed data that is trailing the compressed blob may
* also be read by this function, but this will be handled by read_uncompressed.
*/
static enum b_status refill_input_buffer(struct b_cstream_p *stream)
{
enum b_status status = B_SUCCESS;
size_t nr_read = 0;
while (1) {
void *data;
size_t capacity;
status = b_ringbuffer_open_write_buffer(
stream->s_in, &data, &capacity);
if (!B_OK(status)) {
break;
}
size_t r = 0;
status = b_stream_read_bytes(
stream->s_endpoint, data, capacity, &r);
b_ringbuffer_close_write_buffer(stream->s_in, &data, r);
nr_read += r;
if (r < capacity) {
break;
}
if (!B_OK(status)) {
break;
}
}
if (status == B_ERR_NO_SPACE && nr_read > 0) {
status = B_SUCCESS;
}
return status;
}
/* push compressed data out of the input buffer, through the (de)compressor,
* and store the resulting uncompressed data in the output buffer */
static enum b_status refill_output_buffer(struct b_cstream_p *stream)
{
enum b_status status = B_SUCCESS;
if (b_compressor_eof(stream->s_compressor)) {
return B_ERR_NO_DATA;
}
if (!b_ringbuffer_available_data_remaining(stream->s_in)) {
status = refill_input_buffer(stream);
}
if (!B_OK(status)) {
return status;
}
size_t bytes_before = b_ringbuffer_available_data_remaining(stream->s_in);
status = b_compressor_step(stream->s_compressor);
size_t bytes_after = b_ringbuffer_available_data_remaining(stream->s_in);
stream->s_tx_bytes_compressed += (bytes_before - bytes_after);
stream->s_tx_bytes += (bytes_before - bytes_after);
return status;
}
static enum b_status cstream_read(
struct b_cstream_p *stream, void *buf, size_t count, size_t *out_nr_read)
{
if (stream->s_mode != B_COMPRESSOR_MODE_DECOMPRESS) {
return B_ERR_BAD_STATE;
}
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return read_cursor(stream, buf, count, out_nr_read);
}
if (stream->s_compression_depth == 0) {
return read_uncompressed(stream, buf, count, out_nr_read);
}
unsigned char *dest = buf;
size_t nr_read = 0;
size_t remaining = count;
enum b_status status = B_SUCCESS;
while (remaining > 0) {
if (!b_ringbuffer_available_data_remaining(stream->s_out)) {
status = refill_output_buffer(stream);
}
if (!B_OK(status)) {
break;
}
const void *data;
size_t available;
status = b_ringbuffer_open_read_buffer(
stream->s_out, &data, &available);
if (!B_OK(status)) {
break;
}
size_t to_copy = remaining;
if (to_copy > available) {
to_copy = available;
}
memcpy(dest, data, to_copy);
b_ringbuffer_close_read_buffer(stream->s_out, &data, to_copy);
stream->s_tx_bytes_uncompressed += to_copy;
dest += to_copy;
nr_read += to_copy;
remaining -= to_copy;
}
if (status == B_ERR_NO_DATA) {
status = B_SUCCESS;
}
*out_nr_read = nr_read;
return status;
}
static enum b_status write_cursor(
struct b_cstream_p *stream, const void *buf, size_t count, size_t *nr_written)
{
return b_stream_write_bytes(stream->s_endpoint, buf, count, nr_written);
}
static enum b_status write_uncompressed(
struct b_cstream_p *stream, const void *buf, size_t count, size_t *nr_written)
{
size_t w = 0;
enum b_status status
= b_stream_write_bytes(stream->s_endpoint, buf, count, &w);
stream->s_tx_bytes_uncompressed += w;
stream->s_tx_bytes += w;
*nr_written = w;
return status;
}
/* push uncompressed data out of the input buffer, through the compressor,
* and store the resulting compressed data in the output buffer */
static enum b_status flush_input_buffer(struct b_cstream_p *stream)
{
if (!b_ringbuffer_available_data_remaining(stream->s_in)) {
return B_ERR_NO_DATA;
}
return b_compressor_step(stream->s_compressor);
}
/* push compressed data from the output buffer into the endpoint */
static enum b_status flush_output_buffer(struct b_cstream_p *stream)
{
enum b_status status = B_SUCCESS;
size_t nr_written = 0;
while (1) {
const void *data;
size_t capacity;
status = b_ringbuffer_open_read_buffer(
stream->s_out, &data, &capacity);
if (!B_OK(status)) {
break;
}
size_t w = 0;
status = b_stream_write_bytes(
stream->s_endpoint, data, capacity, &w);
b_ringbuffer_close_read_buffer(stream->s_out, &data, w);
nr_written += w;
stream->s_tx_bytes_compressed += w;
stream->s_tx_bytes += w;
if (w < capacity) {
break;
}
if (!B_OK(status)) {
break;
}
}
if (status == B_ERR_NO_DATA && nr_written > 0) {
status = B_SUCCESS;
}
return status;
}
static enum b_status cstream_write(
struct b_cstream_p *stream, const void *buf, size_t count,
size_t *out_nr_written)
{
if (stream->s_mode != B_COMPRESSOR_MODE_COMPRESS) {
return B_ERR_BAD_STATE;
}
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return write_cursor(stream, buf, count, out_nr_written);
}
if (stream->s_compression_depth == 0) {
return write_uncompressed(stream, buf, count, out_nr_written);
}
const unsigned char *src = buf;
size_t nr_written = 0;
size_t remaining = count;
enum b_status status = B_SUCCESS;
while (remaining > 0) {
if (!b_ringbuffer_write_capacity_remaining(stream->s_out)) {
status = flush_output_buffer(stream);
}
if (!b_ringbuffer_write_capacity_remaining(stream->s_in)) {
status = flush_input_buffer(stream);
}
if (!B_OK(status)) {
break;
}
void *data;
size_t available;
status = b_ringbuffer_open_write_buffer(
stream->s_in, &data, &available);
if (!B_OK(status)) {
break;
}
size_t to_copy = remaining;
if (to_copy > available) {
to_copy = available;
}
memcpy(data, src, to_copy);
b_ringbuffer_close_write_buffer(stream->s_in, &data, to_copy);
stream->s_tx_bytes_uncompressed += to_copy;
src += to_copy;
nr_written += to_copy;
remaining -= to_copy;
}
if (status == B_ERR_NO_DATA) {
status = B_SUCCESS;
}
*out_nr_written = nr_written;
return status;
}
static enum b_status skip_uncompressed(
struct b_cstream_p *stream, size_t count, size_t *out_nr_skipped)
{
size_t remaining = count;
size_t nr_read_from_buf = 0;
size_t nr_read_from_endpoint = 0;
enum b_status status = B_SUCCESS;
/* liberal usage of begin_compressed_section and end_compressed_section
* can result in uncompressed data getting stuck in the input buffer.
* return any data remaining in the input buffer before reading more
* from the endpoint */
while (remaining > 0) {
const void *data;
size_t available;
status = b_ringbuffer_open_read_buffer(
stream->s_in, &data, &available);
if (!B_OK(status)) {
break;
}
size_t to_copy = remaining;
if (to_copy > available) {
to_copy = available;
}
b_ringbuffer_close_read_buffer(stream->s_in, &data, to_copy);
stream->s_tx_bytes_uncompressed += to_copy;
stream->s_tx_bytes += to_copy;
remaining -= to_copy;
nr_read_from_buf += to_copy;
}
if (remaining == 0) {
if (out_nr_skipped) {
*out_nr_skipped = nr_read_from_buf;
}
return B_SUCCESS;
}
size_t cursor = b_stream_cursor(stream->s_endpoint);
status = b_stream_seek(stream->s_endpoint, remaining, B_STREAM_SEEK_CURRENT);
nr_read_from_endpoint = b_stream_cursor(stream->s_endpoint) - cursor;
stream->s_tx_bytes_uncompressed += nr_read_from_endpoint;
stream->s_tx_bytes += nr_read_from_endpoint;
if (out_nr_skipped) {
*out_nr_skipped = nr_read_from_endpoint + nr_read_from_buf;
}
return status;
}
static enum b_status cstream_skip(
struct b_cstream_p *stream, size_t count, size_t *out_nr_skipped)
{
if (stream->s_mode != B_COMPRESSOR_MODE_DECOMPRESS) {
return B_ERR_BAD_STATE;
}
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return B_ERR_BAD_STATE;
}
if (stream->s_compression_depth == 0) {
return skip_uncompressed(stream, count, out_nr_skipped);
}
if (b_compressor_eof(stream->s_compressor)
&& !b_ringbuffer_available_data_remaining(stream->s_out)) {
if (out_nr_skipped) {
*out_nr_skipped = 0;
}
return B_SUCCESS;
}
size_t nr_read = 0;
size_t remaining = count;
enum b_status status = B_SUCCESS;
while (remaining > 0) {
if (!b_ringbuffer_available_data_remaining(stream->s_out)) {
status = refill_output_buffer(stream);
}
if (!B_OK(status)) {
break;
}
const void *data;
size_t available;
status = b_ringbuffer_open_read_buffer(
stream->s_out, &data, &available);
if (!B_OK(status)) {
break;
}
size_t to_copy = remaining;
if (to_copy > available) {
to_copy = available;
}
b_ringbuffer_close_read_buffer(stream->s_out, &data, to_copy);
stream->s_tx_bytes_uncompressed += to_copy;
nr_read += to_copy;
remaining -= to_copy;
}
if (status == B_ERR_NO_DATA) {
status = B_SUCCESS;
}
if (out_nr_skipped) {
*out_nr_skipped = nr_read;
}
return status;
}
static enum b_status cstream_reset(struct b_cstream_p *stream)
{
if (stream->s_mode != B_COMPRESSOR_MODE_DECOMPRESS) {
return B_ERR_BAD_STATE;
}
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return B_ERR_BAD_STATE;
}
stream->s_flags = 0;
b_stream_seek(stream->s_endpoint, 0, B_STREAM_SEEK_START);
b_ringbuffer_clear(stream->s_in);
b_ringbuffer_clear(stream->s_out);
b_compressor_reset(stream->s_compressor);
stream->s_compression_depth = 0;
stream->s_tx_bytes = 0;
stream->s_tx_bytes_uncompressed = 0;
stream->s_tx_bytes_compressed = 0;
stream->s_cursor = 0;
return B_SUCCESS;
}
static enum b_status cstream_begin_compressed_section(
struct b_cstream_p *stream, size_t *tx_uncompressed_bytes)
{
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return B_ERR_BAD_STATE;
}
if (tx_uncompressed_bytes) {
*tx_uncompressed_bytes = stream->s_tx_bytes_uncompressed;
}
if (stream->s_compression_depth > 0) {
stream->s_compression_depth++;
return B_SUCCESS;
}
stream->s_compression_depth = 1;
stream->s_tx_bytes_uncompressed = 0;
stream->s_tx_bytes_compressed = 0;
b_compressor_reset(stream->s_compressor);
return B_SUCCESS;
}
static enum b_status cstream_end_compressed_section(
struct b_cstream_p *stream, size_t *tx_compressed_bytes,
size_t *tx_uncompressed_bytes)
{
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return B_ERR_BAD_STATE;
}
tx_compressed_bytes
&& (*tx_compressed_bytes = stream->s_tx_bytes_compressed);
tx_uncompressed_bytes
&& (*tx_uncompressed_bytes = stream->s_tx_bytes_uncompressed);
if (stream->s_compression_depth > 1) {
stream->s_compression_depth--;
return B_SUCCESS;
}
stream->s_compression_depth = 0;
if (stream->s_mode == B_COMPRESSOR_MODE_DECOMPRESS) {
stream->s_tx_bytes_compressed = 0;
stream->s_tx_bytes_uncompressed = 0;
return B_SUCCESS;
}
enum b_status status = B_SUCCESS;
while (1) {
status = b_compressor_end(stream->s_compressor);
if (!B_OK(status) && status != B_ERR_NO_SPACE) {
break;
}
status = flush_output_buffer(stream);
if (!B_OK(status)) {
break;
}
if (b_compressor_eof(stream->s_compressor)) {
status = B_SUCCESS;
break;
}
}
/* refresh these output variables to account for any data
* written by b_compressor_end */
tx_compressed_bytes
&& (*tx_compressed_bytes = stream->s_tx_bytes_compressed);
tx_uncompressed_bytes
&& (*tx_uncompressed_bytes = stream->s_tx_bytes_uncompressed);
if (!B_OK(status)) {
return status;
}
stream->s_tx_bytes_compressed = 0;
stream->s_tx_bytes_uncompressed = 0;
return flush_output_buffer(stream);
}
static bool cstream_in_compressed_section(const struct b_cstream_p *stream)
{
return stream->s_compression_depth > 0;
}
static enum b_status cstream_tx_bytes(const struct b_cstream_p *stream, size_t *out)
{
*out = stream->s_tx_bytes;
return B_SUCCESS;
}
static enum b_status cstream_tx_bytes_compressed(
const struct b_cstream_p *stream, size_t *out)
{
*out = stream->s_tx_bytes_compressed;
return B_SUCCESS;
}
static enum b_status cstream_tx_bytes_uncompressed(
const struct b_cstream_p *stream, size_t *out)
{
*out = stream->s_tx_bytes_uncompressed;
return B_SUCCESS;
}
static enum b_status cstream_set_cursor_position(
struct b_cstream_p *stream, size_t pos)
{
if (stream->s_compression_depth > 0) {
return B_ERR_BAD_STATE;
}
if (stream->s_flags & CSTREAM_CURSOR_MOVED) {
return B_ERR_BAD_STATE;
}
stream->s_cursor = b_stream_cursor(stream->s_endpoint);
enum b_status status
= b_stream_seek(stream->s_endpoint, pos, B_STREAM_SEEK_START);
if (!B_OK(status)) {
stream->s_cursor = 0;
return status;
}
stream->s_flags |= CSTREAM_CURSOR_MOVED;
return B_SUCCESS;
}
static enum b_status cstream_restore_cursor_position(struct b_cstream_p *stream)
{
if (!(stream->s_flags & CSTREAM_CURSOR_MOVED)) {
return B_ERR_BAD_STATE;
}
enum b_status status = b_stream_seek(
stream->s_endpoint, stream->s_cursor, B_STREAM_SEEK_START);
stream->s_cursor = 0;
if (!B_OK(status)) {
return status;
}
stream->s_flags &= ~CSTREAM_CURSOR_MOVED;
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
enum b_status b_cstream_open(
b_stream *endpoint, b_type compressor_type, b_compressor_mode mode,
b_cstream **out)
{
size_t inbuf_size = 0, outbuf_size = 0;
enum b_status status = b_compressor_get_buffer_size(
compressor_type, mode, &inbuf_size, &outbuf_size);
if (!B_OK(status)) {
return status;
}
b_cstream *stream = b_object_create(B_TYPE_CSTREAM);
if (!stream) {
return B_ERR_NO_MEMORY;
}
struct b_cstream_p *p = b_object_get_private(stream, B_TYPE_CSTREAM);
b_stream_cfg *cfg = b_object_get_protected(stream, B_TYPE_STREAM);
p->s_mode = mode;
p->s_endpoint = endpoint;
cfg->s_mode = (mode == B_COMPRESSOR_MODE_COMPRESS) ? B_STREAM_WRITE
: B_STREAM_READ;
p->s_in = b_ringbuffer_create(inbuf_size + 1);
if (!B_OK(status)) {
free(stream);
return status;
}
p->s_out = b_ringbuffer_create(outbuf_size + 1);
if (!B_OK(status)) {
b_cstream_unref(stream);
return status;
}
p->s_compressor = b_object_create(compressor_type);
if (!p->s_compressor) {
b_cstream_unref(stream);
return B_ERR_INVALID_ARGUMENT;
}
b_compressor_set_buffer(p->s_compressor, p->s_in, p->s_out);
b_compressor_set_mode(p->s_compressor, mode);
*out = stream;
return B_SUCCESS;
}
enum b_status b_cstream_read(
b_cstream *stream, void *buf, size_t count, size_t *out_nr_read)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_read, stream, buf, count, out_nr_read);
}
enum b_status b_cstream_write(
b_cstream *stream, const void *buf, size_t count, size_t *out_nr_written)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_write, stream, buf, count, out_nr_written);
}
enum b_status b_cstream_skip(b_cstream *stream, size_t count, size_t *out_nr_skipped)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_skip, stream, count, out_nr_skipped);
}
enum b_status b_cstream_reset(b_cstream *stream)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_CSTREAM, cstream_reset, stream);
}
enum b_status b_cstream_begin_compressed_section(
b_cstream *stream, size_t *tx_uncompressed_bytes)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_begin_compressed_section, stream,
tx_uncompressed_bytes);
}
enum b_status b_cstream_end_compressed_section(
b_cstream *stream, size_t *tx_compressed_bytes, size_t *tx_uncompressed_bytes)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_end_compressed_section, stream,
tx_compressed_bytes, tx_uncompressed_bytes);
}
bool b_cstream_in_compressed_section(const b_cstream *stream)
{
B_CLASS_DISPATCH_STATIC_0(
B_TYPE_CSTREAM, cstream_in_compressed_section, stream);
}
enum b_status b_cstream_tx_bytes(const b_cstream *stream, size_t *out)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_CSTREAM, cstream_tx_bytes, stream, out);
}
enum b_status b_cstream_tx_bytes_compressed(const b_cstream *stream, size_t *out)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_tx_bytes_compressed, stream, out);
}
enum b_status b_cstream_tx_bytes_uncompressed(const b_cstream *stream, size_t *out)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_tx_bytes_uncompressed, stream, out);
}
enum b_status b_cstream_set_cursor_position(b_cstream *stream, size_t pos)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_CSTREAM, cstream_set_cursor_position, stream, pos);
}
enum b_status b_cstream_restore_cursor_position(b_cstream *stream)
{
B_CLASS_DISPATCH_STATIC_0(
B_TYPE_CSTREAM, cstream_restore_cursor_position, stream);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void cstream_init(b_object *obj, void *priv)
{
}
static void cstream_fini(b_object *obj, void *priv)
{
struct b_cstream_p *stream = priv;
if (stream->s_compressor) {
b_compressor_unref(stream->s_compressor);
}
if (stream->s_in) {
b_ringbuffer_unref(stream->s_in);
}
if (stream->s_out) {
b_ringbuffer_unref(stream->s_out);
}
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_cstream)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_stream, B_TYPE_STREAM)
B_INTERFACE_ENTRY(s_close) = NULL;
B_INTERFACE_ENTRY(s_seek) = NULL;
B_INTERFACE_ENTRY(s_tell) = NULL;
B_INTERFACE_ENTRY(s_getc) = NULL;
B_INTERFACE_ENTRY(s_read) = b_cstream_read;
B_INTERFACE_ENTRY(s_write) = b_cstream_write;
B_INTERFACE_ENTRY(s_reserve) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)
B_TYPE_CLASS_DEFINITION_END(b_cstream)
B_TYPE_DEFINITION_BEGIN(b_cstream)
B_TYPE_ID(0xe1e899b5, 0x6a3c, 0x4f9c, 0xafd0, 0xaab3f156615c);
B_TYPE_EXTENDS(B_TYPE_STREAM);
B_TYPE_CLASS(b_cstream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_cstream_p);
B_TYPE_INSTANCE_INIT(cstream_init);
B_TYPE_INSTANCE_FINI(cstream_fini);
B_TYPE_DEFINITION_END(b_cstream)
-362
View File
@@ -1,362 +0,0 @@
#include <blue/compress/zstd.h>
#include <blue/core/ringbuffer.h>
#include <zstd.h>
/*** PRIVATE DATA *************************************************************/
struct b_zstd_compressor_p {
union {
ZSTD_CCtx *zstd_c;
ZSTD_DCtx *zstd_d;
};
};
/*** PUBLIC FUNCTIONS *********************************************************/
b_status b_zstd_compressor_get_buffer_size(
b_compressor_mode mode, size_t *inbuf_size, size_t *outbuf_size)
{
switch (mode) {
case B_COMPRESSOR_MODE_COMPRESS:
*inbuf_size = ZSTD_CStreamInSize();
*outbuf_size = ZSTD_CStreamOutSize();
break;
case B_COMPRESSOR_MODE_DECOMPRESS:
*inbuf_size = ZSTD_DStreamInSize();
*outbuf_size = ZSTD_DStreamOutSize();
break;
default:
return B_ERR_INVALID_ARGUMENT;
}
return B_SUCCESS;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void zstd_compressor_init(b_object *obj, void *priv)
{
}
static void zstd_compressor_fini(b_object *obj, void *priv)
{
b_compressor_data *c = b_object_get_protected(obj, B_TYPE_COMPRESSOR);
struct b_zstd_compressor_p *ctx = priv;
switch (c->c_mode) {
case B_COMPRESSOR_MODE_COMPRESS:
ZSTD_freeCCtx(ctx->zstd_c);
break;
case B_COMPRESSOR_MODE_DECOMPRESS:
ZSTD_freeDCtx(ctx->zstd_d);
break;
default:
break;
}
}
static enum b_status reset(b_compressor *compressor)
{
struct b_zstd_compressor_p *ctx
= b_object_get_private(compressor, B_TYPE_ZSTD_COMPRESSOR);
b_compressor_data *data
= b_object_get_protected(compressor, B_TYPE_COMPRESSOR);
if (!ctx || !data) {
return B_ERR_INVALID_ARGUMENT;
}
switch (data->c_mode) {
case B_COMPRESSOR_MODE_COMPRESS:
ZSTD_CCtx_reset(ctx->zstd_c, ZSTD_reset_session_only);
break;
case B_COMPRESSOR_MODE_DECOMPRESS:
ZSTD_DCtx_reset(ctx->zstd_d, ZSTD_reset_session_only);
break;
default:
return B_ERR_BAD_STATE;
}
return B_SUCCESS;
}
static enum b_status compress(b_compressor *compressor)
{
enum b_status status = B_SUCCESS;
struct b_zstd_compressor_p *ctx
= b_object_get_private(compressor, B_TYPE_ZSTD_COMPRESSOR);
b_compressor_data *data
= b_object_get_protected(compressor, B_TYPE_COMPRESSOR);
if (!ctx || !data) {
return B_ERR_INVALID_ARGUMENT;
}
b_ringbuffer *in = data->c_in;
b_ringbuffer *out = data->c_out;
if (b_ringbuffer_available_data_remaining(in) == 0) {
return B_ERR_NO_DATA;
}
if (b_ringbuffer_write_capacity_remaining(out) == 0) {
return B_ERR_NO_SPACE;
}
size_t nr_consumed = 0;
while (1) {
size_t in_available = 0, out_capacity = 0;
const void *in_buf = NULL;
void *out_buf = NULL;
status = b_ringbuffer_open_read_buffer(in, &in_buf, &in_available);
if (!B_OK(status)) {
break;
}
status = b_ringbuffer_open_write_buffer(
out, &out_buf, &out_capacity);
if (!B_OK(status)) {
b_ringbuffer_close_read_buffer(in, &in_buf, 0);
break;
}
ZSTD_inBuffer z_in = {
.src = in_buf,
.pos = 0,
.size = in_available,
};
ZSTD_outBuffer z_out = {
.dst = out_buf,
.pos = 0,
.size = out_capacity,
};
do {
size_t ret = ZSTD_compressStream2(
ctx->zstd_c, &z_out, &z_in, ZSTD_e_continue);
if (ZSTD_isError(ret)) {
status = B_ERR_COMPRESSION_FAILURE;
break;
}
} while (z_in.pos < z_in.size && z_out.pos < z_out.size);
nr_consumed += z_in.pos;
b_ringbuffer_close_read_buffer(in, &in_buf, z_in.pos);
b_ringbuffer_close_write_buffer(out, &out_buf, z_out.pos);
}
if ((status == B_ERR_NO_SPACE || status == B_ERR_NO_DATA)
&& nr_consumed > 0) {
status = B_SUCCESS;
}
return status;
}
static enum b_status compress_end(b_compressor *compressor)
{
enum b_status status = B_SUCCESS;
struct b_zstd_compressor_p *ctx
= b_object_get_private(compressor, B_TYPE_ZSTD_COMPRESSOR);
b_compressor_data *data
= b_object_get_protected(compressor, B_TYPE_COMPRESSOR);
if (!ctx || !data) {
return B_ERR_INVALID_ARGUMENT;
}
b_ringbuffer *out = data->c_out;
if (b_ringbuffer_write_capacity_remaining(out) == 0) {
return B_ERR_NO_SPACE;
}
bool finished = false;
do {
void *out_buf = NULL;
size_t out_capacity = 0;
status = b_ringbuffer_open_write_buffer(
out, &out_buf, &out_capacity);
if (!B_OK(status)) {
break;
}
ZSTD_inBuffer z_in = {0};
ZSTD_outBuffer z_out = {
.dst = out_buf,
.pos = 0,
.size = out_capacity,
};
do {
size_t ret = ZSTD_compressStream2(
ctx->zstd_c, &z_out, &z_in, ZSTD_e_end);
if (ZSTD_isError(ret)) {
status = B_ERR_COMPRESSION_FAILURE;
finished = true;
}
if (ret == 0) {
data->c_flags |= B_COMPRESSOR_EOF;
finished = true;
}
} while (!finished && z_out.pos < z_out.size);
b_ringbuffer_close_write_buffer(out, &out_buf, z_out.pos);
} while (!finished);
return status;
}
static enum b_status decompress(b_compressor *compressor)
{
enum b_status status = B_SUCCESS;
struct b_zstd_compressor_p *ctx
= b_object_get_private(compressor, B_TYPE_ZSTD_COMPRESSOR);
b_compressor_data *data
= b_object_get_protected(compressor, B_TYPE_COMPRESSOR);
if (!ctx || !data) {
return B_ERR_INVALID_ARGUMENT;
}
b_ringbuffer *in = data->c_in;
b_ringbuffer *out = data->c_out;
if (b_ringbuffer_available_data_remaining(in) == 0) {
return B_ERR_NO_DATA;
}
if (b_ringbuffer_write_capacity_remaining(out) == 0) {
return B_ERR_NO_SPACE;
}
size_t nr_consumed = 0;
while (!(data->c_flags & B_COMPRESSOR_EOF)) {
size_t in_available = 0, out_capacity = 0;
const void *in_buf = NULL;
void *out_buf = NULL;
status = b_ringbuffer_open_read_buffer(in, &in_buf, &in_available);
if (!B_OK(status)) {
break;
}
status = b_ringbuffer_open_write_buffer(
out, &out_buf, &out_capacity);
if (!B_OK(status)) {
b_ringbuffer_close_read_buffer(in, &in_buf, 0);
break;
}
ZSTD_inBuffer z_in = {
.src = in_buf,
.pos = 0,
.size = in_available,
};
ZSTD_outBuffer z_out = {
.dst = out_buf,
.pos = 0,
.size = out_capacity,
};
do {
size_t ret = ZSTD_decompressStream(
ctx->zstd_d, &z_out, &z_in);
if (ZSTD_isError(ret)) {
status = B_ERR_COMPRESSION_FAILURE;
break;
}
if (ret == 0) {
data->c_flags |= B_COMPRESSOR_EOF;
break;
}
} while (z_in.pos < z_in.size && z_out.pos < z_out.size);
nr_consumed += z_in.pos;
b_ringbuffer_close_read_buffer(in, &in_buf, z_in.pos);
b_ringbuffer_close_write_buffer(out, &out_buf, z_out.pos);
}
if ((status == B_ERR_NO_SPACE || status == B_ERR_NO_DATA)
&& nr_consumed > 0) {
status = B_SUCCESS;
}
return status;
}
static enum b_status set_mode(b_compressor *compressor, b_compressor_mode mode)
{
struct b_zstd_compressor_p *ctx
= b_object_get_private(compressor, B_TYPE_ZSTD_COMPRESSOR);
b_compressor_data *data
= b_object_get_protected(compressor, B_TYPE_COMPRESSOR);
if (!ctx || !data) {
return B_ERR_INVALID_ARGUMENT;
}
if (mode == data->c_mode) {
return B_SUCCESS;
}
switch (data->c_mode) {
case B_COMPRESSOR_MODE_COMPRESS:
ZSTD_freeCCtx(ctx->zstd_c);
break;
case B_COMPRESSOR_MODE_DECOMPRESS:
ZSTD_freeDCtx(ctx->zstd_d);
break;
default:
break;
}
data->c_mode = mode;
switch (data->c_mode) {
case B_COMPRESSOR_MODE_COMPRESS:
ctx->zstd_c = ZSTD_createCCtx();
break;
case B_COMPRESSOR_MODE_DECOMPRESS:
ctx->zstd_d = ZSTD_createDCtx();
break;
default:
return B_ERR_INVALID_ARGUMENT;
}
return B_SUCCESS;
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_zstd_compressor)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_compressor, B_TYPE_COMPRESSOR)
B_INTERFACE_ENTRY(c_buffer_size)
= b_zstd_compressor_get_buffer_size;
B_INTERFACE_ENTRY(c_compress) = compress;
B_INTERFACE_ENTRY(c_compress_end) = compress_end;
B_INTERFACE_ENTRY(c_decompress) = decompress;
B_INTERFACE_ENTRY(c_reset) = reset;
B_INTERFACE_ENTRY(c_set_mode) = set_mode;
B_TYPE_CLASS_INTERFACE_END(b_compressor, B_TYPE_COMPRESSOR)
B_TYPE_CLASS_DEFINITION_END(b_zstd_compressor)
B_TYPE_DEFINITION_BEGIN(b_zstd_compressor)
B_TYPE_ID(0x51d437fc, 0xe789, 0x4105, 0xbac7, 0xe6b3f45df198);
B_TYPE_EXTENDS(B_TYPE_COMPRESSOR);
B_TYPE_CLASS(b_zstd_compressor_class);
B_TYPE_INSTANCE_PRIVATE(struct b_zstd_compressor_p);
B_TYPE_INSTANCE_INIT(zstd_compressor_init);
B_TYPE_INSTANCE_FINI(zstd_compressor_fini);
B_TYPE_DEFINITION_END(b_zstd_compressor)
@@ -1,67 +0,0 @@
#ifndef BLUE_COMPRESS_COMPRESSOR_H_
#define BLUE_COMPRESS_COMPRESSOR_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/ringbuffer.h>
#include <blue/core/status.h>
#include <stdbool.h>
B_DECLS_BEGIN;
typedef enum b_compressor_mode {
B_COMPRESSOR_MODE_NONE = 0,
B_COMPRESSOR_MODE_COMPRESS,
B_COMPRESSOR_MODE_DECOMPRESS,
} b_compressor_mode;
typedef enum b_compressor_flags {
B_COMPRESSOR_EOF = 0x01u,
} b_compressor_flags;
#define B_TYPE_COMPRESSOR (b_compressor_get_type())
B_DECLARE_TYPE(b_compressor);
B_TYPE_CLASS_DECLARATION_BEGIN(b_compressor)
b_status (*c_buffer_size)(b_compressor_mode, size_t *, size_t *);
b_status (*c_set_mode)(b_compressor *, b_compressor_mode);
b_status (*c_compress)(b_compressor *);
b_status (*c_compress_end)(b_compressor *);
b_status (*c_decompress)(b_compressor *);
b_status (*c_reset)(b_compressor *);
B_TYPE_CLASS_DECLARATION_END(b_compressor)
typedef struct b_compressor_data {
b_compressor_flags c_flags;
b_compressor_mode c_mode;
b_ringbuffer *c_in, *c_out;
} b_compressor_data;
BLUE_API b_type b_compressor_get_type(void);
#if 0
BLUE_API b_status b_compressor_create(
const struct b_compression_function *func, enum b_compression_mode mode,
struct b_ringbuffer *inbuf, struct b_ringbuffer *outbuf,
b_compressor **out);
#endif
BLUE_API b_status b_compressor_get_buffer_size(
b_type type, b_compressor_mode mode, size_t *inbuf_size,
size_t *outbuf_size);
BLUE_API b_status b_compressor_get_mode(
const b_compressor *compressor, b_compressor_mode *out);
BLUE_API b_status b_compressor_set_mode(
b_compressor *compressor, b_compressor_mode mode);
BLUE_API b_status b_compressor_set_buffer(
b_compressor *compressor, b_ringbuffer *inbuf, b_ringbuffer *outbuf);
BLUE_API b_status b_compressor_step(b_compressor *compressor);
BLUE_API b_status b_compressor_end(b_compressor *compressor);
BLUE_API b_status b_compressor_reset(b_compressor *compressor);
BLUE_API bool b_compressor_eof(const b_compressor *compressor);
B_DECLS_END;
#endif
-50
View File
@@ -1,50 +0,0 @@
#ifndef BLUE_COMPRESS_CSTREAM_H_
#define BLUE_COMPRESS_CSTREAM_H_
#include <blue/core/macros.h>
#include <blue/core/stream.h>
#include <stdbool.h>
B_DECLS_BEGIN;
enum b_compressor_mode;
#define B_TYPE_CSTREAM (b_cstream_get_type())
B_DECLARE_TYPE(b_cstream);
B_TYPE_CLASS_DECLARATION_BEGIN(b_cstream)
B_TYPE_CLASS_DECLARATION_END(b_cstream)
BLUE_API b_type b_cstream_get_type(void);
BLUE_API b_status b_cstream_open(
b_stream *endpoint, b_type compressor_type, enum b_compressor_mode mode,
b_cstream **out);
BLUE_API b_status b_cstream_read(
b_cstream *stream, void *buf, size_t count, size_t *nr_read);
BLUE_API b_status b_cstream_write(
b_cstream *stream, const void *buf, size_t count, size_t *nr_written);
BLUE_API b_status b_cstream_skip(
b_cstream *stream, size_t count, size_t *nr_skipped);
BLUE_API b_status b_cstream_reset(b_cstream *stream);
BLUE_API b_status b_cstream_begin_compressed_section(
b_cstream *stream, size_t *tx_uncompressed_bytes);
BLUE_API b_status b_cstream_end_compressed_section(
b_cstream *stream, size_t *tx_compressed_bytes,
size_t *tx_uncompressed_bytes);
BLUE_API bool b_cstream_in_compressed_section(const b_cstream *stream);
BLUE_API b_status b_cstream_tx_bytes(const b_cstream *stream, size_t *out);
BLUE_API b_status b_cstream_tx_bytes_compressed(
const b_cstream *stream, size_t *out);
BLUE_API b_status b_cstream_tx_bytes_uncompressed(
const b_cstream *stream, size_t *out);
BLUE_API b_status b_cstream_set_cursor_position(b_cstream *stream, size_t pos);
BLUE_API b_status b_cstream_restore_cursor_position(b_cstream *stream);
B_DECLS_END;
#endif
-28
View File
@@ -1,28 +0,0 @@
#ifndef BLUE_COMPRESS_ZSTD_H_
#define BLUE_COMPRESS_ZSTD_H_
#include <blue/compress/compressor.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdbool.h>
B_DECLS_BEGIN;
#define B_TYPE_ZSTD_COMPRESSOR (b_zstd_compressor_get_type())
B_DECLARE_TYPE(b_zstd_compressor);
B_TYPE_CLASS_DECLARATION_BEGIN(b_zstd_compressor)
B_TYPE_CLASS_DECLARATION_END(b_compressor)
BLUE_API b_type b_zstd_compressor_get_type(void);
BLUE_API b_status b_zstd_compressor_get_buffer_size(
b_compressor_mode mode, size_t *inbuf_size, size_t *outbuf_size);
B_TYPE_DEFAULT_CONSTRUCTOR(b_zstd_compressor, B_TYPE_ZSTD_COMPRESSOR);
B_DECLS_END;
#endif
-5
View File
@@ -1,5 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_module(
NAME core
SUBDIRS hash)
-79
View File
@@ -1,79 +0,0 @@
#include "class.h"
#include "type.h"
#include <assert.h>
#include <blue/core/class.h>
#include <stdlib.h>
#include <string.h>
void *b_class_get(b_type id)
{
struct b_type_registration *r = b_type_get_registration(id);
if (!r) {
return NULL;
}
return r->r_class;
}
const char *b_class_get_name(const struct _b_class *c)
{
if (!c) {
return NULL;
}
assert(c->c_magic == B_CLASS_MAGIC);
return c->c_type->r_info->t_name;
}
void *b_class_get_interface(const struct _b_class *c, const union b_type *id)
{
if (!c) {
return NULL;
}
assert(c->c_magic == B_CLASS_MAGIC);
const struct b_type_registration *type_reg = c->c_type;
struct b_type_component *comp
= b_type_get_component(&type_reg->r_components, id);
if (!comp) {
return NULL;
}
return (char *)c + comp->c_class_data_offset;
}
b_result b_class_instantiate(
struct b_type_registration *type, struct _b_class **out_class)
{
struct _b_class *out = malloc(type->r_class_size);
if (!out) {
return B_RESULT_ERR(NO_MEMORY);
}
memset(out, 0x0, type->r_class_size);
out->c_magic = B_CLASS_MAGIC;
out->c_type = type;
struct b_queue_entry *entry = b_queue_first(&type->r_class_hierarchy);
while (entry) {
struct b_type_component *comp
= b_unbox(struct b_type_component, entry, c_entry);
const struct b_type_info *class_info = comp->c_type->r_info;
void *class_data = (char *)out + comp->c_class_data_offset;
if (class_info->t_class_init) {
class_info->t_class_init(out, class_data);
}
entry = b_queue_next(entry);
}
*out_class = out;
return B_RESULT_SUCCESS;
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef _CLASS_H_
#define _CLASS_H_
#include <blue/core/error.h>
#include <blue/core/misc.h>
#include <stdint.h>
struct b_type_registration;
struct _b_class {
uint64_t c_magic;
const struct b_type_registration *c_type;
};
extern b_result b_class_instantiate(
struct b_type_registration *type, struct _b_class **out);
#endif
-1059
View File
File diff suppressed because it is too large Load Diff
-37
View File
@@ -1,37 +0,0 @@
#ifndef _BLUELIB_ERROR_H_
#define _BLUELIB_ERROR_H_
#include <blue/core/error.h>
#include <blue/core/queue.h>
struct b_error_stack_frame {
b_queue_entry f_entry;
const char *f_file;
unsigned int f_line_number;
const char *f_function;
};
struct b_error_submsg {
b_queue_entry msg_entry;
b_error_submsg_type msg_type;
char *msg_content;
const struct b_error_msg *msg_msg;
struct b_error_template_parameter msg_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
};
struct b_error {
const struct b_error_vendor *err_vendor;
b_error_status_code err_code;
const struct b_error_definition *err_def;
const struct b_error_msg *err_msg;
char *err_description;
struct b_error_template_parameter err_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
struct b_queue err_submsg;
struct b_queue err_stack;
b_queue_entry err_entry;
struct b_error *err_caused_by;
};
#endif
-178
View File
@@ -1,178 +0,0 @@
#include "hash.h"
#include <blue/core/hash.h>
#include <blue/core/rope.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define FNV1_OFFSET_BASIS 0xcbf29ce484222325
#define FNV1_PRIME 0x100000001b3
extern struct b_hash_function_ops z__b_md4_ops;
extern struct b_hash_function_ops z__b_md5_ops;
extern struct b_hash_function_ops z__b_sha1_ops;
extern struct b_hash_function_ops z__b_sha2_224_ops;
extern struct b_hash_function_ops z__b_sha2_256_ops;
extern struct b_hash_function_ops z__b_sha2_384_ops;
extern struct b_hash_function_ops z__b_sha2_512_ops;
extern struct b_hash_function_ops z__b_sha3_224_ops;
extern struct b_hash_function_ops z__b_sha3_256_ops;
extern struct b_hash_function_ops z__b_sha3_384_ops;
extern struct b_hash_function_ops z__b_sha3_512_ops;
extern struct b_hash_function_ops z__b_shake128_ops;
extern struct b_hash_function_ops z__b_shake256_ops;
static const struct b_hash_function_ops *hash_functions[] = {
[B_HASH_NONE] = NULL,
[B_HASH_MD4] = &z__b_md4_ops,
[B_HASH_MD5] = &z__b_md5_ops,
[B_HASH_SHA1] = &z__b_sha1_ops,
[B_HASH_SHA2_224] = &z__b_sha2_224_ops,
[B_HASH_SHA2_256] = &z__b_sha2_256_ops,
[B_HASH_SHA2_384] = &z__b_sha2_384_ops,
[B_HASH_SHA2_512] = &z__b_sha2_512_ops,
[B_HASH_SHA3_224] = &z__b_sha3_224_ops,
[B_HASH_SHA3_256] = &z__b_sha3_256_ops,
[B_HASH_SHA3_384] = &z__b_sha3_384_ops,
[B_HASH_SHA3_512] = &z__b_sha3_512_ops,
[B_HASH_SHAKE128] = &z__b_shake128_ops,
[B_HASH_SHAKE256] = &z__b_shake256_ops,
};
static const size_t nr_hash_functions
= sizeof hash_functions / sizeof hash_functions[0];
uint64_t b_hash_cstr(const char *s)
{
size_t x = 0;
return b_hash_cstr_ex(s, &x);
}
uint64_t b_hash_cstr_ex(const char *s, size_t *len)
{
uint64_t hash = FNV1_OFFSET_BASIS;
size_t i = 0;
for (i = 0; s[i]; i++) {
hash ^= s[i];
hash *= FNV1_PRIME;
}
if (len) {
*len = i;
}
return hash;
}
enum b_status b_hash_ctx_init(struct b_hash_ctx *ctx, enum b_hash_function func)
{
if (func < 0 || func >= nr_hash_functions) {
return B_ERR_NOT_SUPPORTED;
}
const struct b_hash_function_ops *hash_function = hash_functions[func];
if (!hash_function) {
return B_ERR_NOT_SUPPORTED;
}
memset(ctx, 0x0, sizeof *ctx);
ctx->ctx_func = func;
ctx->ctx_ops = hash_function;
if (hash_function->hash_init) {
hash_function->hash_init(ctx);
}
return B_SUCCESS;
}
enum b_status b_hash_ctx_reset(struct b_hash_ctx *ctx)
{
if (ctx->ctx_func == B_HASH_NONE || !ctx->ctx_ops) {
return B_ERR_BAD_STATE;
}
memset(&ctx->ctx_state, 0x0, sizeof ctx->ctx_state);
if (ctx->ctx_ops->hash_init) {
ctx->ctx_ops->hash_init(ctx);
}
return B_SUCCESS;
}
enum b_status b_hash_ctx_update(struct b_hash_ctx *ctx, const void *p, size_t len)
{
if (!ctx->ctx_ops) {
return B_ERR_BAD_STATE;
}
if (!ctx->ctx_ops->hash_update) {
return B_ERR_NOT_SUPPORTED;
}
ctx->ctx_ops->hash_update(ctx, p, len);
return B_SUCCESS;
}
static void update_rope(const b_rope *rope, void *arg)
{
struct b_hash_ctx *ctx = arg;
unsigned int type = B_ROPE_TYPE(rope->r_flags);
char tmp[64];
size_t len = 0;
switch (type) {
case B_ROPE_F_CHAR:
b_hash_ctx_update(ctx, &rope->r_v.v_char, sizeof rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
b_hash_ctx_update(
ctx, rope->r_v.v_cstr.s, strlen(rope->r_v.v_cstr.s));
break;
case B_ROPE_F_INT:
len = snprintf(tmp, sizeof tmp, "%" PRIdPTR, rope->r_v.v_int);
b_hash_ctx_update(ctx, tmp, len);
break;
case B_ROPE_F_UINT:
len = snprintf(tmp, sizeof tmp, "%" PRIuPTR, rope->r_v.v_uint);
b_hash_ctx_update(ctx, tmp, len);
break;
default:
break;
}
}
enum b_status b_hash_ctx_update_rope(
struct b_hash_ctx *ctx, const struct b_rope *rope)
{
b_rope_iterate(rope, update_rope, ctx);
return B_SUCCESS;
}
enum b_status b_hash_ctx_finish(
struct b_hash_ctx *ctx, void *out_digest, size_t out_max)
{
if (!ctx->ctx_ops) {
return B_ERR_BAD_STATE;
}
if (!ctx->ctx_ops->hash_finish) {
return B_ERR_NOT_SUPPORTED;
}
ctx->ctx_ops->hash_finish(ctx, out_digest, out_max);
memset(&ctx->ctx_state, 0x0, sizeof ctx->ctx_state);
if (ctx->ctx_ops->hash_init) {
ctx->ctx_ops->hash_init(ctx);
}
return B_SUCCESS;
}
-14
View File
@@ -1,14 +0,0 @@
#ifndef _HASH_H_
#define _HASH_H_
#include <stddef.h>
struct b_hash_ctx;
struct b_hash_function_ops {
void (*hash_init)(struct b_hash_ctx *);
void (*hash_update)(struct b_hash_ctx *, const void *, size_t);
void (*hash_finish)(struct b_hash_ctx *, void *, size_t);
};
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef BLUELIB_CORE_BITOP_H_
#define BLUELIB_CORE_BITOP_H_
#include <blue/core/misc.h>
BLUE_API int b_popcountl(long v);
BLUE_API int b_ctzl(long v);
BLUE_API int b_clzl(long v);
#if defined(__GNUC__) || defined(__clang__)
#define b_cmpxchg(v, expected_val, new_val) \
__atomic_compare_exchange_n( \
v, expected_val, new_val, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED)
#elif defined(_MSC_VER)
/* TODO add MSVC support */
#error MSVC intrinsics not yet supported
#else
#error Unsupported compiler
#endif
#endif
-71
View File
@@ -1,71 +0,0 @@
#ifndef BLUE_CORE_BSTR_H_
#define BLUE_CORE_BSTR_H_
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdarg.h>
#include <stddef.h>
#define B_BSTR_MAGIC 0x5005500550055005ULL
struct b_rope;
enum b_bstr_flags {
B_BSTR_F_NONE = 0x00u,
B_BSTR_F_ALLOC = 0x01u,
};
typedef struct b_bstr {
uint64_t bstr_magic;
enum b_bstr_flags bstr_flags;
char *bstr_buf;
/* total number of characters in bstr_buf, not including null terminator */
size_t bstr_len;
/* number of bytes allocated for bstr_buf (includes space for the null
* terminator) */
size_t bstr_capacity;
int *bstr_istack;
int bstr_add_indent;
size_t bstr_istack_ptr, bstr_istack_size;
} b_bstr;
BLUE_API void b_bstr_begin(b_bstr *strv, char *buf, size_t max);
BLUE_API void b_bstr_begin_dynamic(b_bstr *strv);
BLUE_API char *b_bstr_end(b_bstr *strv);
BLUE_API b_status b_bstr_reserve(b_bstr *strv, size_t len);
static inline size_t b_bstr_get_size(const b_bstr *str)
{
return str->bstr_len;
}
static inline size_t b_bstr_get_capacity(const b_bstr *str)
{
return str->bstr_capacity;
}
BLUE_API b_status b_bstr_push_indent(b_bstr *strv, int indent);
BLUE_API b_status b_bstr_pop_indent(b_bstr *strv);
BLUE_API b_status b_bstr_write_char(b_bstr *strv, char c);
BLUE_API b_status b_bstr_write_chars(
b_bstr *strv, const char *cs, size_t len, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr(
b_bstr *strv, const char *str, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr_list(
b_bstr *strv, const char **strs, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr_array(
b_bstr *strv, const char **strs, size_t count, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr_varg(b_bstr *strv, size_t *nr_written, ...);
BLUE_API b_status b_bstr_write_rope(
b_bstr *strv, const struct b_rope *rope, size_t *nr_written);
BLUE_API b_status b_bstr_write_fmt(
b_bstr *strv, size_t *nr_written, const char *format, ...);
BLUE_API b_status b_bstr_write_vfmt(
b_bstr *strv, size_t *nr_written, const char *format, va_list arg);
BLUE_API char *b_bstr_rope(const struct b_rope *rope, size_t *nr_written);
BLUE_API char *b_bstr_fmt(size_t *nr_written, const char *format, ...);
BLUE_API char *b_bstr_vfmt(size_t *nr_written, const char *format, va_list arg);
#endif
-359
View File
@@ -1,359 +0,0 @@
#ifndef BLUELIB_CORE_BTREE_H_
#define BLUELIB_CORE_BTREE_H_
#include <blue/core/iterator.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
B_DECLS_BEGIN;
#define B_BTREE_INIT {0}
#define B_TYPE_BTREE_ITERATOR (b_btree_iterator_get_type())
B_DECLARE_TYPE(b_btree_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_btree_iterator)
B_TYPE_CLASS_DECLARATION_END(b_btree_iterator)
/* defines a simple node insertion function.
this function assumes that your nodes have simple integer keys that can be
compared with the usual operators.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
int key;
b_btree_node base;
}
You would use the following call to generate an insert function for a tree
with this node type:
BTREE_DEFINE_SIMPLE_INSERT(
struct my_tree_node,
base,
key,
my_tree_node_insert);
Which would emit a function defined like:
static void my_tree_node_insert(b_btree *tree, struct my_tree_node *node);
@param node_type your custom tree node type. usually a structure that
contains a b_btree_node member.
@param container_node_member the name of the b_btree_node member variable
within your custom type.
@param container_key_member the name of the key member variable within your
custom type.
@param function_name the name of the function to generate.
*/
#define B_BTREE_DEFINE_SIMPLE_INSERT( \
node_type, container_node_member, container_key_member, function_name) \
void function_name(b_btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
b_btree_insert_fixup(tree, &node->container_node_member); \
return; \
} \
\
b_btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = b_unbox( \
node_type, cur, container_node_member); \
b_btree_node *next = NULL; \
\
if (node->container_key_member \
>= cur_node->container_key_member) { \
next = b_btree_right(cur); \
\
if (!next) { \
b_btree_put_right( \
cur, \
&node->container_node_member); \
break; \
} \
} else if ( \
node->container_key_member \
< cur_node->container_key_member) { \
next = b_btree_left(cur); \
\
if (!next) { \
b_btree_put_left( \
cur, \
&node->container_node_member); \
break; \
} \
} \
\
cur = next; \
} \
\
b_btree_insert_fixup(tree, &node->container_node_member); \
}
/* defines a node insertion function.
this function should be used for trees with complex node keys that cannot be
directly compared. a comparator for your keys must be supplied.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
complex_key_t key;
b_btree_node base;
}
You would need to define a comparator function or macro with the following
signature:
int my_comparator(struct my_tree_node *a, struct my_tree_node *b);
Which implements the following:
return -1 if a < b
return 0 if a == b
return 1 if a > b
You would use the following call to generate an insert function for a tree
with this node type:
BTREE_DEFINE_INSERT(struct my_tree_node, base, key, my_tree_node_insert,
my_comparator);
Which would emit a function defined like:
static void my_tree_node_insert(b_btree *tree, struct my_tree_node *node);
@param node_type your custom tree node type. usually a structure that
contains a b_btree_node member.
@param container_node_member the name of the b_btree_node member variable
within your custom type.
@param container_key_member the name of the key member variable within your
custom type.
@param function_name the name of the function to generate.
@param comparator the name of a comparator function or functional-macro that
conforms to the requirements listed above.
*/
#define B_BTREE_DEFINE_INSERT( \
node_type, container_node_member, container_key_member, function_name, \
comparator) \
void function_name(b_btree *tree, node_type *node) \
{ \
if (!tree->b_root) { \
tree->b_root = &node->container_node_member; \
b_btree_insert_fixup(tree, &node->container_node_member); \
return; \
} \
\
b_btree_node *cur = tree->b_root; \
while (1) { \
node_type *cur_node = b_unbox( \
node_type, cur, container_node_member); \
b_btree_node *next = NULL; \
int cmp = comparator(node, cur_node); \
\
if (cmp >= 0) { \
next = b_btree_right(cur); \
\
if (!next) { \
b_btree_put_right( \
cur, \
&node->container_node_member); \
break; \
} \
} else if (cmp < 0) { \
next = b_btree_left(cur); \
\
if (!next) { \
b_btree_put_left( \
cur, \
&node->container_node_member); \
break; \
} \
} else { \
return; \
} \
\
cur = next; \
} \
\
b_btree_insert_fixup(tree, &node->container_node_member); \
}
/* defines a simple tree search function.
this function assumes that your nodes have simple integer keys that can be
compared with the usual operators.
EXAMPLE:
if you have a tree node type like this:
struct my_tree_node {
int key;
b_btree_node base;
}
You would use the following call to generate a search function for a tree
with this node type:
BTREE_DEFINE_SIMPLE_GET(struct my_tree_node, int, base, key,
my_tree_node_get);
Which would emit a function defined like:
static struct my_tree_node *my_tree_node_get(b_btree *tree, int key);
@param node_type your custom tree node type. usually a structure that
contains a b_btree_node member.
@param key_type the type name of the key embedded in your custom tree node
type. this type must be compatible with the builtin comparison operators.
@param container_node_member the name of the b_btree_node member variable
within your custom type.
@param container_key_member the name of the key member variable within your
custom type.
@param function_name the name of the function to generate.
*/
#define B_BTREE_DEFINE_SIMPLE_GET( \
node_type, key_type, container_node_member, container_key_member, \
function_name) \
node_type *function_name(const b_btree *tree, key_type key) \
{ \
b_btree_node *cur = tree->b_root; \
while (cur) { \
node_type *cur_node = b_unbox( \
node_type, cur, container_node_member); \
if (key > cur_node->container_key_member) { \
cur = b_btree_right(cur); \
} else if (key < cur_node->container_key_member) { \
cur = b_btree_left(cur); \
} else { \
return cur_node; \
} \
} \
\
return NULL; \
}
#define b_btree_foreach(it, btree) \
for (int z__b_unique_name() = b_btree_iterator_begin(btree, it); \
(it)->node != NULL; b_btree_iterator_next(it))
/* binary tree nodes. this *cannot* be used directly. you need to define a
custom node type that contains a member variable of type b_btree_node.
you would then use the supplied macros to define functions to manipulate your
custom binary tree.
*/
typedef struct b_btree_node {
struct b_btree_node *b_parent, *b_left, *b_right;
unsigned short b_height;
} b_btree_node;
/* binary tree. unlike b_btree_node, you can define variables of type b_btree.
*/
typedef struct b_btree {
b_btree_node *b_root;
} b_btree;
BLUE_API b_type b_btree_iterator_get_type(void);
/* re-balance a binary tree after an insertion operation.
NOTE that, if you define an insertion function using BTREE_DEFINE_INSERT or
similar, this function will automatically called for you.
@param tree the tree to re-balance.
@param node the node that was just inserted into the tree.
*/
BLUE_API void b_btree_insert_fixup(b_btree *tree, b_btree_node *node);
/* delete a node from a binary tree and re-balance the tree afterwards.
@param tree the tree to delete from
@param node the node to delete.
*/
BLUE_API void b_btree_delete(b_btree *tree, b_btree_node *node);
/* get the first node in a binary tree.
this will be the node with the smallest key (i.e. the node that is
furthest-left from the root)
*/
BLUE_API b_btree_node *b_btree_first(const b_btree *tree);
/* get the last node in a binary tree.
this will be the node with the largest key (i.e. the node that is
furthest-right from the root)
*/
BLUE_API b_btree_node *b_btree_last(const b_btree *tree);
/* for any binary tree node, this function returns the node with the
* next-largest key value */
BLUE_API b_btree_node *b_btree_next(const b_btree_node *node);
/* for any binary tree node, this function returns the node with the
* next-smallest key value */
BLUE_API b_btree_node *b_btree_prev(const b_btree_node *node);
/* return true if the btree is empty, false otherwise */
static inline bool b_btree_empty(const b_btree *tree)
{
return tree->b_root == NULL;
}
/* sets `child` as the immediate left-child of `parent` */
static inline void b_btree_put_left(b_btree_node *parent, b_btree_node *child)
{
parent->b_left = child;
child->b_parent = parent;
}
/* sets `child` as the immediate right-child of `parent` */
static inline void b_btree_put_right(b_btree_node *parent, b_btree_node *child)
{
parent->b_right = child;
child->b_parent = parent;
}
/* get the immediate left-child of `node` */
static inline b_btree_node *b_btree_left(b_btree_node *node)
{
return node->b_left;
}
/* get the immediate right-child of `node` */
static inline b_btree_node *b_btree_right(b_btree_node *node)
{
return node->b_right;
}
/* get the immediate parent of `node` */
static inline b_btree_node *b_btree_parent(b_btree_node *node)
{
return node->b_parent;
}
BLUE_API void b_btree_move(b_btree *tree, b_btree_node *dest, b_btree_node *src);
/* get the height of `node`.
the height of a node is defined as the length of the longest path
between the node and a leaf node.
this count includes the node itself, so the height of a leaf node will be 1.
*/
static inline unsigned short b_btree_height(b_btree_node *node)
{
return node->b_height;
}
BLUE_API b_iterator *b_btree_begin(b_btree *tree);
BLUE_API const b_iterator *b_btree_cbegin(const b_btree *tree);
#ifdef __cplusplus
}
#endif
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef BLUE_OBJECT_CLASS_H_
#define BLUE_OBJECT_CLASS_H_
#include <blue/core/type.h>
#define B_CLASS_MAGIC 0xDEADFACEDCAFEBEDULL
#define B_CLASS(p) ((b_class *)(p))
typedef struct _b_class b_class;
BLUE_API void *b_class_get(b_type id);
BLUE_API const char *b_class_get_name(const b_class *c);
BLUE_API void *b_class_get_interface(const b_class *c, b_type id);
#endif
-41
View File
@@ -1,41 +0,0 @@
#ifndef BLUE_CORE_ENCODING_H_
#define BLUE_CORE_ENCODING_H_
#include <blue/core/misc.h>
#include <stdbool.h>
#include <stdint.h>
#define B_WCHAR_INVALID ((b_wchar) - 1)
typedef int32_t b_wchar;
BLUE_API bool b_wchar_is_alpha(b_wchar c);
BLUE_API bool b_wchar_is_number(b_wchar c);
static inline bool b_wchar_is_bin_digit(b_wchar c)
{
return c >= '0' && c <= '1';
}
static inline bool b_wchar_is_oct_digit(b_wchar c)
{
return c >= '0' && c <= '7';
}
BLUE_API bool b_wchar_is_hex_digit(b_wchar c);
BLUE_API bool b_wchar_is_space(b_wchar c);
static inline bool b_wchar_is_alnum(b_wchar c)
{
return b_wchar_is_alpha(c) || b_wchar_is_number(c);
}
BLUE_API bool b_wchar_is_punct(b_wchar c);
BLUE_API bool b_wchar_utf8_is_valid_scalar(b_wchar c);
BLUE_API unsigned int b_wchar_utf8_header_decode(char c);
BLUE_API unsigned int b_wchar_utf8_codepoint_size(b_wchar c);
BLUE_API b_wchar b_wchar_utf8_codepoint_decode(const char *s);
BLUE_API unsigned int b_wchar_utf8_codepoint_encode(b_wchar c, char s[4]);
BLUE_API unsigned int b_wchar_utf8_codepoint_stride(const char *s);
BLUE_API size_t b_wchar_utf8_codepoint_count(const char *s, size_t nr_bytes);
BLUE_API size_t b_wchar_utf8_string_encoded_size(
const b_wchar *s, size_t nr_codepoints);
#endif
-49
View File
@@ -1,49 +0,0 @@
#ifndef BLUELIB_CORE_ENDIAN_H_
#define BLUELIB_CORE_ENDIAN_H_
#include <blue/core/misc.h>
#include <stdint.h>
typedef struct {
union {
unsigned char i_bytes[sizeof(uint16_t)];
int16_t i_val;
uint16_t i_uval;
};
} b_i16;
typedef struct {
union {
unsigned char i_bytes[sizeof(uint32_t)];
int32_t i_val;
uint32_t i_uval;
};
} b_i32;
typedef struct {
union {
unsigned char i_bytes[sizeof(uint64_t)];
int64_t i_val;
uint64_t i_uval;
};
} b_i64;
BLUE_API b_i16 b_i16_htob(uint16_t v);
BLUE_API b_i16 b_i16_htos(uint16_t v);
BLUE_API uint16_t b_i16_btoh(b_i16 v);
BLUE_API uint16_t b_i16_stoh(b_i16 v);
BLUE_API b_i32 b_i32_htob(uint32_t v);
BLUE_API b_i32 b_i32_htos(uint32_t v);
BLUE_API uint32_t b_i32_btoh(b_i32 v);
BLUE_API uint32_t b_i32_stoh(b_i32 v);
BLUE_API b_i64 b_i64_htob(uint64_t v);
BLUE_API b_i64 b_i64_htos(uint64_t v);
BLUE_API uint64_t b_i64_btoh(b_i64 v);
BLUE_API uint64_t b_i64_stoh(b_i64 v);
#endif
-418
View File
@@ -1,418 +0,0 @@
#ifndef BLUE_CORE_ERROR_H_
#define BLUE_CORE_ERROR_H_
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdarg.h>
#include <stdbool.h>
#define B_ERROR_TEMPLATE_PARAMETER_MAX 4
#define B_ERROR_MSG_ID_INVALID ((unsigned long)-1)
#define B_CATCH(err, expr) ((err = (expr)) != NULL)
#define b_result_is_error(result) ((result) != NULL)
#define b_result_is_success(result) ((result) == NULL)
#define B_RESULT_SUCCESS ((b_result)NULL)
#define B_RESULT_ERR(err_name) \
b_error_with_code(b_error_vendor_get_builtin(), B_ERR_##err_name)
#define B_RESULT_ERR_WITH_STRING(err_name, ...) \
b_error_with_string( \
b_error_vendor_get_builtin(), B_ERR_##err_name, __VA_ARGS__)
#define B_RESULT_STATUS(code) \
((code) == B_SUCCESS \
? B_RESULT_SUCCESS \
: (b_error_with_code(b_error_vendor_get_builtin(), code)))
#define B_RESULT_STATUS_WITH_STRING(code, ...) \
((code) == B_SUCCESS \
? B_RESULT_SUCCESS \
: (b_error_with_string( \
b_error_vendor_get_builtin(), code, __VA_ARGS__)))
#define B_ERRORS_BUILTIN (b_error_vendor_get_builtin())
#define B_ERRORS_ERRNO (b_error_vendor_get_errno())
#define B_ERROR_PARAM(name, value) \
(b_error_template_parameter) \
{ \
.param_name = (name), .param_value = (uintptr_t)(value), \
}
#define B_ERROR_TEMPLATE_PARAM(name, type, format) \
(b_error_template_parameter_definition) \
{ \
.param_name = (name), .param_type = (type), \
.param_format = (format), \
}
#define B_ERROR_DEFINITION(code, name, msg) \
[code] = (b_error_definition) \
{ \
.err_name = (name), .err_message = (msg), \
}
#define B_ERROR_DEFINITION_TEMPLATE(code, name, msg, ...) \
[code] = (b_error_definition) \
{ \
.err_name = (name), .err_message = (msg), \
.err_params = __VA_ARGS__, \
}
#define B_ERROR_MSG(id, content) \
[id] = (b_error_msg) \
{ \
.msg_message = (content), \
}
#define B_ERROR_MSG_TEMPLATE(id, content, ...) \
[id] = (b_error_msg) \
{ \
.msg_message = (content), .msg_params = __VA_ARGS__, \
}
#define z__b_error_create_status(status_code) \
(z__b_error_create( \
b_error_vendor_get_builtin(), status_code, NULL, NULL, 0, \
NULL, NULL))
/* Error creation macros */
#define b_error_with_code(vendor, code) \
(z__b_error_create( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_caused_by_error(vendor, code, cause_error) \
(z__b_error_create( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_caused_by_status(vendor, code, cause_status) \
(z__b_error_create( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_caused_by_code(vendor, code, cause_vendor, cause_code) \
(z__b_error_create( \
vendor, code, b_error_with_code(cause_vendor, cause_code), \
__FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_with_string(vendor, code, ...) \
(z__b_error_create( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__))
#define b_error_with_string_caused_by_error(vendor, code, cause_error, ...) \
(z__b_error_create( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
__VA_ARGS__))
#define b_error_with_string_caused_by_status(vendor, code, cause_status, ...) \
(z__b_error_create( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__))
#define b_error_with_msg(vendor, code, msg_id) \
(z__b_error_create_msg( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {{}}))
#define b_error_with_msg_caused_by_error(vendor, code, cause_error, msg_id) \
(z__b_error_create_msg( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
msg_id, (b_error_template_parameter[]) {{}}))
#define b_error_with_msg_caused_by_status(vendor, code, cause_status, msg_id) \
(z__b_error_create_msg( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {{}}))
#define b_error_with_msg_template(vendor, code, msg_id, ...) \
(z__b_error_create_msg( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_msg_template_caused_by_error( \
vendor, code, cause_error, msg_id, ...) \
(z__b_error_create_msg( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
msg_id, (b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_msg_template_caused_by_status( \
vendor, code, cause_status, msg_id, ...) \
(z__b_error_create_msg( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_template(vendor, code, ...) \
(z__b_error_create_template( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_template_caused_by_error(vendor, code, cause_error, ...) \
(z__b_error_create_template( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_template_caused_by_status(vendor, code, cause_status, ...) \
(z__b_error_create_template( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
/* Error propagation macros */
#define b_result_propagate(err) \
(z__b_error_propagate(err, __FILE__, __LINE__, __FUNCTION__))
#define b_error_caused_by(err, caused_by) (z__b_error_caused_by(err, caused_by))
#define b_error_caused_by_b_status(err, status) \
(z__b_error_caused_by_b_status(err, status))
#define b_error_replace(err, caused_by) \
(z__b_error_propagate(err, __FILE__, __LINE__, __FUNCTION__))
/* Error throw macros */
#define z__b_throw(err) (z__b_error_throw(err, NULL, 0, NULL))
#define b_throw(err) (z__b_error_throw(err, __FILE__, __LINE__, __FUNCTION__))
#define b_throw_status(status) \
(z__b_error_throw( \
z__b_error_create( \
b_error_vendor_get_builtin(), status, NULL, NULL, 0, \
NULL, NULL), \
__FILE__, __LINE__, __FUNCTION__))
#define b_throw_status_string(status, ...) \
(z__b_error_throw( \
z__b_error_create( \
b_error_vendor_get_builtin(), status, NULL, NULL, 0, \
NULL, __VA_ARGS__), \
__FILE__, __LINE__, __FUNCTION__))
#define b_throw_error_code(vendor, code) \
z__b_throw(b_error_with_code(vendor, code))
#define b_throw_error_caused_by_error(vendor, code, cause) \
z__b_throw(b_error_caused_by_error(vendor, code, cause))
#define b_throw_error_caused_by_status(vendor, code, cause) \
z__b_throw(b_error_caused_by_status(vendor, code, cause))
#define b_throw_error_with_string(vendor, code, ...) \
z__b_throw(b_error_with_string(vendor, code, __VA_ARGS__))
#define b_throw_error_with_string_caused_by_error(vendor, code, cause, ...) \
z__b_throw(b_error_with_string_caused_by_error( \
vendor, code, cause, __VA_ARGS__))
#define b_throw_error_with_string_caused_by_status(vendor, code, cause, ...) \
z__b_throw(b_error_with_string_caused_by_status( \
vendor, code, cause, __VA_ARGS__))
#define b_throw_error_with_msg(vendor, code, msg_id) \
z__b_throw(b_error_with_msg(vendor, code, msg_id))
#define b_throw_error_with_msg_caused_by_error(vendor, code, cause, msg_id) \
z__b_throw(b_error_with_msg_caused_by_error(vendor, code, cause, msg_id))
#define b_throw_error_with_msg_caused_by_status(vendor, code, cause, msg_id) \
z__b_throw(b_error_with_msg_caused_by_status(vendor, code, cause, msg_id))
#define b_throw_error_with_msg_template(vendor, code, msg_id, ...) \
z__b_throw(b_error_with_msg_template(vendor, code, msg_id, __VA_ARGS__))
#define b_throw_error_with_msg_template_caused_by_error( \
vendor, code, cause, msg_id, ...) \
z__b_throw(b_error_with_msg_template_caused_by_error( \
vendor, code, cause, msg_id, __VA_ARGS__))
#define b_throw_error_with_msg_template_caused_by_status( \
vendor, code, cause, msg_id, ...) \
z__b_throw(b_error_with_msg_template_caused_by_status( \
vendor, code, cause, msg_id, __VA_ARGS__))
#define b_throw_error_with_template(vendor, code, ...) \
z__b_throw(b_error_with_template(vendor, code, __VA_ARGS__))
#define b_throw_error_with_template_caused_by_error(vendor, code, cause, ...) \
z__b_throw(b_error_with_template_caused_by_error( \
vendor, code, cause, __VA_ARGS__))
#define b_throw_error_with_template_caused_by_status(vendor, code, cause, ...) \
z__b_throw(b_error_with_template_caused_by_status( \
vendor, code, cause, __VA_ARGS__))
#define B_ERR_MSG(s) \
{ \
.msg_type = B_ERROR_MESSAGE_ERROR, \
.msg_content = (s), \
}
#define B_ERR_MSG_WARN(s) \
{ \
.msg_type = B_ERROR_MESSAGE_WARN, \
.msg_content = (s), \
}
#define B_ERR_MSG_INFO(s) \
{ \
.msg_type = B_ERROR_MESSAGE_INFO, \
.msg_content = (s), \
}
#define B_ERR_MSG_END(s) \
{ \
.msg_type = B_ERROR_MESSAGE_NONE, \
.msg_content = NULL, \
}
typedef enum b_error_submsg_type {
B_ERROR_SUBMSG_NONE = 0,
B_ERROR_SUBMSG_ERROR,
B_ERROR_SUBMSG_WARNING,
B_ERROR_SUBMSG_INFO,
} b_error_submsg_type;
typedef enum b_error_report_flags {
B_ERROR_REPORT_NONE = 0,
B_ERROR_REPORT_STATUS = 0x01u,
B_ERROR_REPORT_DESCRIPTION = 0x02u,
B_ERROR_REPORT_SUBMSG = 0x04u,
B_ERROR_REPORT_STACK_TRACE = 0x08u,
B_ERROR_REPORT_CAUSE = 0x10u,
B_ERROR_REPORT_MINIMAL = B_ERROR_REPORT_STATUS | B_ERROR_REPORT_DESCRIPTION,
B_ERROR_REPORT_DEFAULT = B_ERROR_REPORT_MINIMAL | B_ERROR_REPORT_SUBMSG
| B_ERROR_REPORT_CAUSE,
B_ERROR_REPORT_ALL = B_ERROR_REPORT_DEFAULT | B_ERROR_REPORT_STACK_TRACE,
} b_error_report_flags;
typedef enum b_error_template_parameter_type {
B_ERROR_TEMPLATE_PARAM_NONE = 0,
B_ERROR_TEMPLATE_PARAM_STRING,
B_ERROR_TEMPLATE_PARAM_CHAR,
B_ERROR_TEMPLATE_PARAM_INT,
B_ERROR_TEMPLATE_PARAM_UINT,
B_ERROR_TEMPLATE_PARAM_LONG,
B_ERROR_TEMPLATE_PARAM_ULONG,
B_ERROR_TEMPLATE_PARAM_LONGLONG,
B_ERROR_TEMPLATE_PARAM_ULONGLONG,
B_ERROR_TEMPLATE_PARAM_SIZE_T,
B_ERROR_TEMPLATE_PARAM_INTPTR,
B_ERROR_TEMPLATE_PARAM_UINTPTR,
B_ERROR_TEMPLATE_PARAM_PTR,
} b_error_template_parameter_type;
typedef struct b_error_template_parameter_definition {
const char *param_name;
b_error_template_parameter_type param_type;
const char *param_format;
} b_error_template_parameter_definition;
typedef struct b_error_template_parameter {
const char *param_name;
uintptr_t param_value;
const struct b_error_template_parameter_definition *__param_def;
} b_error_template_parameter;
struct b_error_vendor;
typedef struct b_error b_error;
typedef struct b_error *b_result;
typedef struct b_error_submsg b_error_submsg;
typedef struct b_error_stack_frame b_error_stack_frame;
typedef long b_error_status_code;
typedef unsigned long b_error_msg_id;
typedef struct b_error_definition {
const char *err_name;
const char *err_message;
const b_error_template_parameter_definition err_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
} b_error_definition;
typedef struct b_error_msg {
const char *msg_message;
const b_error_template_parameter_definition msg_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
} b_error_msg;
typedef const b_error_definition *(*b_error_status_code_get_definition)(
const struct b_error_vendor *, b_error_status_code);
typedef const b_error_msg *(*b_error_msg_get_definition)(
const struct b_error_vendor *, b_error_msg_id);
typedef void (*b_error_report_function)(
const struct b_error *, b_error_report_flags);
typedef struct b_error_vendor {
const char *v_name;
b_error_status_code_get_definition v_status_get_definition;
b_error_msg_get_definition v_msg_get_definition;
const b_error_definition *v_error_definitions;
size_t v_error_definitions_length;
const b_error_msg *v_msg;
size_t v_msg_length;
} b_error_vendor;
BLUE_API b_error *z__b_error_create_template(
const b_error_vendor *, b_error_status_code, b_error *, const char *,
unsigned int, const char *, const b_error_template_parameter[]);
BLUE_API b_error *z__b_error_create_string(
const b_error_vendor *, b_error_status_code, b_error *, const char *,
unsigned int, const char *, const char *, va_list);
BLUE_API b_error *z__b_error_create_msg(
const b_error_vendor *, b_error_status_code, b_error *, const char *,
unsigned int, const char *, b_error_msg_id,
const b_error_template_parameter[]);
BLUE_API b_error *z__b_error_propagate(
b_error *, const char *, unsigned int, const char *);
BLUE_API b_error *z__b_error_caused_by(b_error *, b_error *);
BLUE_API b_error *z__b_error_caused_by_b_status(b_error *, b_status);
BLUE_API void z__b_error_throw(b_error *, const char *, unsigned int, const char *);
BLUE_API bool b_result_is(
b_result result, const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const b_error_vendor *b_error_vendor_get_builtin(void);
BLUE_API const b_error_vendor *b_error_vendor_get_errno(void);
BLUE_API const b_error_definition *b_error_vendor_get_error_definition(
const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const char *b_error_vendor_get_status_code_name(
const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const char *b_error_vendor_get_status_code_description(
const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const b_error_msg *b_error_vendor_get_msg(
const b_error_vendor *vendor, b_error_msg_id msg_id);
static inline b_error *z__b_error_create(
const b_error_vendor *v, b_error_status_code c, b_error *c2,
const char *f0, unsigned int l, const char *f1, const char *d, ...)
{
va_list arg;
va_start(arg, d);
b_error *err = z__b_error_create_string(v, c, c2, f0, l, f1, d, arg);
va_end(arg);
return err;
}
BLUE_API enum b_status b_error_add_submsg_string(
b_error *error, b_error_submsg_type type, const char *msg, ...);
BLUE_API enum b_status z__b_error_add_submsg_template(
b_error *error, b_error_submsg_type type, b_error_msg_id msg_id,
b_error_template_parameter param[]);
#define b_error_add_submsg(error, type, msg_id) \
(z__b_error_add_submsg_template( \
error, type, msg_id, (b_error_template_parameter[]) {{}}))
#define b_error_add_submsg_template(error, type, msg_id, ...) \
(z__b_error_add_submsg_template( \
error, type, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
BLUE_API void b_error_discard(b_error *error);
BLUE_API b_error_status_code b_error_get_status_code(const b_error *error);
BLUE_API const b_error_vendor *b_error_get_vendor(const b_error *error);
BLUE_API const b_error_definition *b_error_get_definition(const b_error *error);
BLUE_API const b_error_template_parameter *b_error_get_template_parameter(
const b_error *error, const char *param_name);
BLUE_API const b_error_template_parameter *b_error_get_template_parameters(
const b_error *error);
BLUE_API const char *b_error_get_description(const b_error *error);
BLUE_API const b_error_msg *b_error_get_msg(const b_error *error);
BLUE_API const b_error_submsg *b_error_get_first_submsg(const b_error *error);
BLUE_API const b_error_submsg *b_error_get_next_submsg(
const b_error *error, const b_error_submsg *msg);
BLUE_API const b_error_stack_frame *b_error_get_first_stack_frame(
const b_error *error);
BLUE_API const b_error_stack_frame *b_error_get_next_stack_frame(
const b_error *error, const b_error_stack_frame *frame);
BLUE_API const b_error *b_error_get_caused_by(const b_error *error);
BLUE_API b_error_submsg_type b_error_submsg_get_type(const b_error_submsg *msg);
BLUE_API const char *b_error_submsg_get_content(const b_error_submsg *msg);
BLUE_API const b_error_msg *b_error_submsg_get_msg(const b_error_submsg *msg);
BLUE_API const b_error_template_parameter *b_error_submsg_get_template_parameters(
const b_error_submsg *msg);
BLUE_API const char *b_error_stack_frame_get_filepath(
const b_error_stack_frame *frame);
BLUE_API unsigned int b_error_stack_frame_get_line_number(
const b_error_stack_frame *frame);
BLUE_API const char *b_error_stack_frame_get_function_name(
const b_error_stack_frame *frame);
BLUE_API const b_error_template_parameter_definition *b_error_definition_get_template_parameter(
const b_error_definition *error_def, const char *param_name);
BLUE_API const char *b_error_msg_get_content(const b_error_msg *msg);
BLUE_API const b_error_template_parameter_definition *b_error_msg_get_template_parameter(
const b_error_msg *msg, const char *param_name);
BLUE_API void b_set_error_report_function(
b_error_report_function func, b_error_report_flags flags);
#endif
-111
View File
@@ -1,111 +0,0 @@
#ifndef BLUELIB_CORE_HASH_H_
#define BLUELIB_CORE_HASH_H_
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stddef.h>
#include <stdint.h>
#define B_DIGEST_LENGTH_128 16
#define B_DIGEST_LENGTH_160 20
#define B_DIGEST_LENGTH_192 24
#define B_DIGEST_LENGTH_224 28
#define B_DIGEST_LENGTH_256 32
#define B_DIGEST_LENGTH_384 48
#define B_DIGEST_LENGTH_512 64
#define B_DIGEST_LENGTH_MD4 B_DIGEST_LENGTH_128
#define B_DIGEST_LENGTH_MD5 B_DIGEST_LENGTH_128
#define B_DIGEST_LENGTH_SHA1 B_DIGEST_LENGTH_160
#define B_DIGEST_LENGTH_SHA2_224 B_DIGEST_LENGTH_224
#define B_DIGEST_LENGTH_SHA2_256 B_DIGEST_LENGTH_256
#define B_DIGEST_LENGTH_SHA2_384 B_DIGEST_LENGTH_384
#define B_DIGEST_LENGTH_SHA2_512 B_DIGEST_LENGTH_512
#define B_DIGEST_LENGTH_SHA3_224 B_DIGEST_LENGTH_224
#define B_DIGEST_LENGTH_SHA3_256 B_DIGEST_LENGTH_256
#define B_DIGEST_LENGTH_SHA3_384 B_DIGEST_LENGTH_384
#define B_DIGEST_LENGTH_SHA3_512 B_DIGEST_LENGTH_512
#define B_DIGEST_LENGTH_SHAKE128 B_DIGEST_LENGTH_128
#define B_DIGEST_LENGTH_SHAKE256 B_DIGEST_LENGTH_256
struct b_hash_function_ops;
struct b_rope;
typedef enum b_hash_function {
B_HASH_NONE = 0,
B_HASH_MD4,
B_HASH_MD5,
B_HASH_SHA1,
B_HASH_SHA2_224,
B_HASH_SHA2_256,
B_HASH_SHA2_384,
B_HASH_SHA2_512,
B_HASH_SHA3_224,
B_HASH_SHA3_256,
B_HASH_SHA3_384,
B_HASH_SHA3_512,
B_HASH_SHAKE128,
B_HASH_SHAKE256,
} b_hash_function;
typedef struct b_hash_ctx {
b_hash_function ctx_func;
const struct b_hash_function_ops *ctx_ops;
union {
struct {
uint32_t lo, hi;
uint32_t a, b, c, d;
uint32_t block[16];
unsigned char buffer[64];
} md4;
struct {
unsigned int count[2];
unsigned int a, b, c, d;
unsigned int block[16];
unsigned char input[64];
} md5;
struct {
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} sha1;
struct {
uint64_t curlen;
uint64_t length;
unsigned char buf[128];
uint32_t state[8];
} sha2_256;
struct {
uint64_t curlen;
uint64_t length;
unsigned char block[256];
uint64_t state[8];
} sha2_512;
struct {
union {
uint8_t b[200];
uint64_t q[25];
} st;
int pt, rsiz, mdlen;
} sha3;
} ctx_state;
} b_hash_ctx;
BLUE_API uint64_t b_hash_cstr(const char *s);
BLUE_API uint64_t b_hash_cstr_ex(const char *s, size_t *len);
BLUE_API b_status b_hash_ctx_init(b_hash_ctx *ctx, b_hash_function func);
BLUE_API b_status b_hash_ctx_reset(b_hash_ctx *ctx);
BLUE_API b_status b_hash_ctx_update(b_hash_ctx *ctx, const void *p, size_t len);
BLUE_API b_status b_hash_ctx_update_rope(b_hash_ctx *ctx, const struct b_rope *rope);
BLUE_API b_status b_hash_ctx_finish(
b_hash_ctx *ctx, void *out_digest, size_t out_max);
#endif
-93
View File
@@ -1,93 +0,0 @@
#ifndef BLUE_CORE_ITERATOR_H_
#define BLUE_CORE_ITERATOR_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdbool.h>
B_DECLS_BEGIN;
#define b_foreach(type, var, iterator) \
for (type var = (type)b_iterator_get_value(iterator).v_int; \
B_OK(b_iterator_get_status(iterator)); \
b_iterator_move_next(iterator), \
var = (type)b_iterator_get_value(iterator).v_int)
#define b_foreach_ptr(type, var, iterator) \
for (type *var = (type *)b_iterator_get_value(iterator).v_ptr; \
B_OK(b_iterator_get_status(iterator)); \
b_iterator_move_next(iterator), \
var = (type *)b_iterator_get_value(iterator).v_ptr)
#define b_foreach_c(type, var, iterator) \
for (type var = (type)b_iterator_get_cvalue(iterator).v_int; \
B_OK(b_iterator_get_status(iterator)); \
b_iterator_move_next(iterator), \
var = (type)b_iterator_get_cvalue(iterator).v_int)
#define b_foreach_cptr(type, var, iterator) \
for (const type *var \
= (const type *)b_iterator_get_cvalue(iterator).v_cptr; \
B_OK(b_iterator_get_status(iterator)); \
b_iterator_move_next(iterator), \
var = (const type *)b_iterator_get_cvalue(iterator).v_cptr)
#define B_ITERATOR_VALUE_INT(v) ((b_iterator_value) {.v_int = (v)})
#define B_ITERATOR_VALUE_PTR(v) ((b_iterator_value) {.v_ptr = (v)})
#define B_ITERATOR_VALUE_CPTR(v) ((const b_iterator_value) {.v_cptr = (v)})
#define B_ITERATOR_VALUE_NULL ((b_iterator_value) {})
#define B_ITERATOR_VALUE_IS_NULL(v) ((v)->v_ptr == NULL)
#define B_TYPE_ITERATOR (b_iterator_get_type())
#define B_TYPE_ITERABLE (b_iterable_get_type())
typedef union b_iterator_value {
uintptr_t v_int;
void *v_ptr;
const void *v_cptr;
} b_iterator_value;
__B_DECLARE_TYPE(b_iterator);
B_DECLARE_TYPE(b_iterable);
B_TYPE_CLASS_DECLARATION_BEGIN(b_iterator)
b_status (*it_move_next)(const b_iterator *);
b_status (*it_erase)(b_iterator *);
b_iterator_value (*it_get_value)(b_iterator *);
const b_iterator_value (*it_get_cvalue)(const b_iterator *);
B_TYPE_CLASS_DECLARATION_END(b_iterator)
B_TYPE_CLASS_DECLARATION_BEGIN(b_iterable)
b_iterator *(*it_begin)(b_iterable *);
const b_iterator *(*it_cbegin)(const b_iterable *);
B_TYPE_CLASS_DECLARATION_END(b_iterable)
BLUE_API b_type b_iterator_get_type(void);
BLUE_API b_type b_iterable_get_type(void);
static inline const b_iterator *b_iterator_ref(const b_iterator *p)
{
return b_object_ref((b_object *)p);
}
static inline void b_iterator_unref(const b_iterator *p)
{
b_object_unref((b_object *)p);
}
BLUE_API b_iterator *b_iterator_begin(b_iterable *it);
BLUE_API const b_iterator *b_iterator_cbegin(const b_iterable *it);
BLUE_API b_status b_iterator_get_status(const b_iterator *it);
BLUE_API b_status b_iterator_set_status(const b_iterator *it, b_status status);
BLUE_API b_status b_iterator_move_next(const b_iterator *it);
BLUE_API b_iterator_value b_iterator_get_value(b_iterator *it);
BLUE_API const b_iterator_value b_iterator_get_cvalue(const b_iterator *it);
BLUE_API b_status b_iterator_erase(b_iterator *it);
static inline bool b_iterator_is_valid(const b_iterator *it)
{
return B_OK(b_iterator_get_status(it));
}
B_DECLS_END;
#endif
-197
View File
@@ -1,197 +0,0 @@
#ifndef BLUE_CORE_MACROS_H_
#define BLUE_CORE_MACROS_H_
#include <blue/core/class.h>
#include <blue/core/object.h>
#include <blue/core/thread.h>
#include <blue/core/type.h>
#include <stdlib.h>
#define __B_IFACE_I0(p, x) p##x
#define __B_IFACE_I1(p, x) __B_IFACE_I0(p, x)
/* Type definitions macros (for use in .c source file) */
#define B_TYPE_CLASS_DEFINITION_BEGIN(type_name) \
static void type_name##_class_init(b_class *p, void *d) \
{
#define B_TYPE_CLASS_DEFINITION_END(type_name) }
#define B_TYPE_CLASS_INTERFACE_BEGIN(interface_name, interface_id) \
interface_name##_class *__B_IFACE_I1(iface, __LINE__) \
= b_class_get_interface(p, interface_id); \
if (!__B_IFACE_I1(iface, __LINE__)) { \
b_throw_error_with_msg_template( \
B_ERRORS_BUILTIN, B_ERR_CLASS_INIT_FAILURE, \
B_MSG_CLASS_SPECIFIES_UNKNOWN_INTERFACE, \
B_ERROR_PARAM("class_name", b_class_get_name(p)), \
B_ERROR_PARAM("interface_name", #interface_name)); \
exit(-1); \
} else { \
interface_name##_class *iface = __B_IFACE_I1(iface, __LINE__);
#define B_TYPE_CLASS_INTERFACE_END(interface_name, interface_id) }
#define B_INTERFACE_ENTRY(slot) iface->slot
#define B_TYPE_DEFINITION_BEGIN(name) \
static b_type_info name##_type_info = {0}; \
static void name##_class_init(b_class *, void *); \
static void name##_type_init(void) \
{ \
b_type_info *type_info = &name##_type_info; \
unsigned int nr_vtables = 0; \
type_info->t_name = #name; \
type_info->t_class_init = name##_class_init;
#define B_TYPE_DEFINITION_END(name) \
b_result result = b_type_register(type_info); \
if (b_result_is_error(result)) { \
b_throw_error_caused_by_error( \
B_ERRORS_BUILTIN, B_ERR_TYPE_REGISTRATION_FAILURE, \
result); \
abort(); \
} \
} \
b_type name##_get_type(void) \
{ \
static b_once static_type_init = B_ONCE_INIT; \
\
if (b_init_once(&static_type_init)) { \
name##_type_init(); \
} \
\
return &name##_type_info.t_id; \
}
#define B_TYPE_ID(a, b, c, d, e) b_type_id_init(&type_info->t_id, a, b, c, d, e)
#define B_TYPE_EXTENDS(parent_id) \
b_type_id_copy(parent_id, &type_info->t_parent_id)
#define B_TYPE_IMPLEMENTS(interface_id) \
b_type_id_copy( \
interface_id, \
&type_info->t_interfaces[type_info->t_nr_interfaces++])
#define B_TYPE_CLASS(class_struct) \
type_info->t_class_size = sizeof(class_struct)
#define B_TYPE_FLAGS(flags) type_info->t_flags = (flags)
#define B_TYPE_INSTANCE_INIT(func) type_info->t_instance_init = (func)
#define B_TYPE_INSTANCE_FINI(func) type_info->t_instance_fini = (func)
#if 0
#define B_TYPE_VTABLE_BEGIN(vtable_struct, interface_id) \
vtable_struct __B_IFACE_I1(iface, __LINE__) = {0}; \
{ \
vtable_struct *iface = &__B_IFACE_I1(iface, __LINE__); \
type_info->t_vtables[nr_vtables].v_vtable = iface; \
type_info->t_vtables[nr_vtables].v_interface_id = interface_id; \
nr_vtables++;
#define B_TYPE_VTABLE_END(vtable_struct, interface_id) }
#endif
#define B_TYPE_INSTANCE_PRIVATE(instance_struct) \
type_info->t_instance_private_size = sizeof(instance_struct)
#define B_TYPE_INSTANCE_PROTECTED(instance_struct) \
type_info->t_instance_protected_size = sizeof(instance_struct)
/* Type declaration macros (for use in .h header file) */
#define __B_DECLARE_TYPE(name) \
typedef B_TYPE_FWDREF(name) name; \
typedef struct _##name##_class name##_class;
#define B_DECLARE_TYPE(name) \
__B_DECLARE_TYPE(name); \
static inline name *name##_ref(name *p) \
{ \
return b_object_ref(p); \
} \
static inline void name##_unref(name *p) \
{ \
b_object_unref(p); \
}
#define B_TYPE_CLASS_DECLARATION_BEGIN(name) struct _##name##_class {
#define B_TYPE_CLASS_DECLARATION_END(name) \
} \
;
#define B_TYPE_VIRTUAL_METHOD(return_type, method_name) \
return_type(*method_name)
#define B_TYPE_DEFAULT_CONSTRUCTOR(type_name, type_id) \
static inline type_name *type_name##_create(void) \
{ \
return b_object_create(type_id); \
}
/* Other macros */
#define B_CLASS_DISPATCH_VIRTUAL( \
type_name, type_id, default_value, func, object, ...) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
return iface->func(object, __VA_ARGS__); \
} else { \
return default_value; \
} \
} while (0)
#define B_CLASS_DISPATCH_VIRTUAL_0(type_name, type_id, default_value, func, object) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
return iface->func(object); \
} else { \
return default_value; \
} \
} while (0)
#define B_CLASS_DISPATCH_VIRTUAL_V(type_name, type_id, func, object, ...) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
iface->func(object, __VA_ARGS__); \
return; \
} \
} while (0)
#define B_CLASS_DISPATCH_VIRTUAL_V0(type_name, type_id, func, object) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
iface->func(object); \
return; \
} \
} while (0)
#define B_CLASS_DISPATCH_STATIC(type_id, func_name, obj, ...) \
do { \
void *priv = b_object_get_private(obj, type_id); \
return func_name(priv, __VA_ARGS__); \
} while (0)
#define B_CLASS_DISPATCH_STATIC_V(type_id, func_name, obj, ...) \
do { \
void *priv = b_object_get_private(obj, type_id); \
func_name(priv, __VA_ARGS__); \
} while (0)
#define B_CLASS_DISPATCH_STATIC_0(type_id, func_name, obj) \
do { \
void *priv = b_object_get_private(obj, type_id); \
return func_name(priv); \
} while (0)
#define B_CLASS_DISPATCH_STATIC_V0(type_id, func_name, obj) \
do { \
void *priv = b_object_get_private(obj, type_id); \
func_name(priv); \
} while (0)
#ifdef __cplusplus
#define B_DECLS_BEGIN extern "C" {
#define B_DECLS_END }
#else
#define B_DECLS_BEGIN
#define B_DECLS_END
#endif
#endif
-118
View File
@@ -1,118 +0,0 @@
#ifndef BLUE_CORE_MISC_H_
#define BLUE_CORE_MISC_H_
#include <stddef.h>
#include <stdint.h>
#ifndef _Nonnull
#define _Nonnull
#endif
#define B_NPOS ((size_t)-1)
#define b_min(type, x, y) (z__b_min_##type(x, y))
#define b_max(type, x, y) (z__b_max_##type(x, y))
#define b_unbox(type, box, member) \
((type *_Nonnull)((box) ? (uintptr_t)(box) - (offsetof(type, member)) : 0))
#define z__b_merge_(a, b) a##b
#define z__b_label_(a) z__b_merge_(__unique_name_, a)
#define z__b_unique_name() z__b_label_(__LINE__)
#define z__b_numargs(arg_type, ...) \
(sizeof((arg_type[]) {__VA_ARGS__}) / sizeof(arg_type))
#ifdef _MSC_VER
#ifdef BLUELIB_STATIC
#define BLUE_API extern
#else
#ifdef BLUELIB_EXPORT
#define BLUE_API extern __declspec(dllexport)
#else
#define BLUE_API extern __declspec(dllimport)
#endif
#endif
#else
#define BLUE_API extern
#endif
static inline char z__b_min_char(char x, char y)
{
return x < y ? x : y;
}
static inline unsigned char z__b_min_uchar(unsigned char x, unsigned char y)
{
return x < y ? x : y;
}
static inline int z__b_min_int(int x, int y)
{
return x < y ? x : y;
}
static inline unsigned int z__b_min_uint(unsigned int x, unsigned int y)
{
return x < y ? x : y;
}
static inline long z__b_min_long(long x, long y)
{
return x < y ? x : y;
}
static inline unsigned int z__b_min_ulong(unsigned long x, unsigned long y)
{
return x < y ? x : y;
}
static inline long long z__b_min_longlong(long long x, long long y)
{
return x < y ? x : y;
}
static inline unsigned long long z__b_min_ulonglong(
unsigned long long x, unsigned long long y)
{
return x < y ? x : y;
}
static inline size_t z__b_min_size_t(size_t x, size_t y)
{
return x < y ? x : y;
}
static inline char z__b_max_char(char x, char y)
{
return x > y ? x : y;
}
static inline unsigned char z__b_max_uchar(unsigned char x, unsigned char y)
{
return x > y ? x : y;
}
static inline int z__b_max_int(int x, int y)
{
return x > y ? x : y;
}
static inline unsigned int z__b_max_uint(unsigned int x, unsigned int y)
{
return x > y ? x : y;
}
static inline long z__b_max_long(long x, long y)
{
return x > y ? x : y;
}
static inline unsigned int z__b_max_ulong(unsigned long x, unsigned long y)
{
return x > y ? x : y;
}
static inline long long z__b_max_longlong(long long x, long long y)
{
return x > y ? x : y;
}
static inline unsigned long long z__b_max_ulonglong(
unsigned long long x, unsigned long long y)
{
return x > y ? x : y;
}
static inline size_t z__b_max_size_t(size_t x, size_t y)
{
return x > y ? x : y;
}
BLUE_API size_t b_int_length(intptr_t v);
BLUE_API size_t b_uint_length(uintptr_t v);
#endif // BLUE_CORE_MISC_H_
-39
View File
@@ -1,39 +0,0 @@
#ifndef BLUE_CORE_OBJECT_H_
#define BLUE_CORE_OBJECT_H_
#include <blue/core/misc.h>
#include <blue/core/type.h>
#define B_OBJECT_MAGIC 0xDECAFC0C0ABEEF13ULL
#define B_OBJECT(p) ((b_object *)(p))
#define B_TYPE_OBJECT (b_object_get_type())
#define B_TYPE_FWDREF(name) struct _b_object
#define B_RV(p) (b_object_make_rvalue(p))
typedef B_TYPE_FWDREF(b_object) b_object;
typedef struct _b_object_class {
void (*to_string)(const b_object *, B_TYPE_FWDREF(b_stream) *);
} b_object_class;
BLUE_API b_type b_object_get_type(void);
BLUE_API void *b_object_get_private(const b_object *object, b_type type);
BLUE_API void *b_object_get_protected(const b_object *object, b_type type);
BLUE_API void *b_object_get_interface(const b_object *object, b_type type);
BLUE_API b_status b_object_get_data(
const b_object *object, b_type type, void **priv, void **prot,
void **iface);
BLUE_API b_object *b_object_ref(b_object *p);
BLUE_API void b_object_unref(b_object *p);
BLUE_API b_object *b_object_make_rvalue(b_object *p);
BLUE_API b_object *b_object_create(b_type type);
BLUE_API void b_object_to_string(const b_object *p, B_TYPE_FWDREF(b_stream) * out);
BLUE_API bool b_object_is_type(const b_object *p, b_type type);
#endif
-82
View File
@@ -1,82 +0,0 @@
#ifndef BLUE_CORE_QUEUE_H_
#define BLUE_CORE_QUEUE_H_
#include <blue/core/iterator.h>
#include <blue/core/macros.h>
#include <blue/core/status.h>
#include <stdbool.h>
#include <string.h>
B_DECLS_BEGIN;
#define B_TYPE_QUEUE_ITERATOR (b_queue_iterator_get_type())
B_DECLARE_TYPE(b_queue_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_queue_iterator)
B_TYPE_CLASS_DECLARATION_END(b_queue_iterator)
#define B_QUEUE_INIT ((b_queue) {.q_first = NULL, .q_last = NULL})
#define B_QUEUE_ENTRY_INIT ((b_queue_entry) {.qe_next = NULL, .qe_prev = NULL})
typedef struct b_queue_entry {
struct b_queue_entry *qe_next;
struct b_queue_entry *qe_prev;
} b_queue_entry;
typedef struct b_queue {
b_queue_entry *q_first;
b_queue_entry *q_last;
} b_queue;
static inline void b_queue_init(b_queue *q)
{
memset(q, 0x00, sizeof *q);
}
static inline bool b_queue_empty(const b_queue *q)
{
return q ? (q->q_first == NULL) : true;
}
static inline b_queue_entry *b_queue_first(const b_queue *q)
{
return q ? q->q_first : NULL;
}
static inline b_queue_entry *b_queue_last(const b_queue *q)
{
return q ? q->q_last : NULL;
}
static inline b_queue_entry *b_queue_next(const b_queue_entry *entry)
{
return entry ? entry->qe_next : NULL;
}
static inline b_queue_entry *b_queue_prev(const b_queue_entry *entry)
{
return entry ? entry->qe_prev : NULL;
}
BLUE_API b_type b_queue_iterator_get_type(void);
BLUE_API size_t b_queue_length(const b_queue *q);
BLUE_API void b_queue_insert_before(
b_queue *q, b_queue_entry *entry, b_queue_entry *before);
BLUE_API void b_queue_insert_after(
b_queue *q, b_queue_entry *entry, b_queue_entry *after);
BLUE_API void b_queue_push_front(b_queue *q, b_queue_entry *entry);
BLUE_API void b_queue_push_back(b_queue *q, b_queue_entry *entry);
BLUE_API b_queue_entry *b_queue_pop_front(b_queue *q);
BLUE_API b_queue_entry *b_queue_pop_back(b_queue *q);
BLUE_API void b_queue_move(b_queue *q, b_queue_entry *dest, b_queue_entry *src);
BLUE_API void b_queue_delete(b_queue *q, b_queue_entry *entry);
BLUE_API void b_queue_delete_all(b_queue *q);
BLUE_API b_iterator *b_queue_begin(b_queue *q);
BLUE_API b_iterator *b_queue_cbegin(const b_queue *q);
B_DECLS_END;
#endif
-37
View File
@@ -1,37 +0,0 @@
#ifndef BLUELIB_RANDOM_H_
#define BLUELIB_RANDOM_H_
#include <blue/core/status.h>
#include <stddef.h>
struct b_random_algorithm;
typedef enum b_random_flags {
/* algorithm selection */
B_RANDOM_MT19937 = 0x01u,
/* generation flags */
B_RANDOM_SECURE = 0x100u,
} b_random_flags;
typedef struct b_random_ctx {
b_random_flags __f;
struct b_random_algorithm *__a;
union {
struct {
unsigned long long mt[312];
size_t mti;
} __mt19937;
};
} b_random_ctx;
BLUE_API b_random_ctx *b_random_global_ctx(void);
BLUE_API b_status b_random_init(b_random_ctx *ctx, b_random_flags flags);
BLUE_API unsigned long long b_random_next_int64(b_random_ctx *ctx);
BLUE_API double b_random_next_double(b_random_ctx *ctx);
BLUE_API void b_random_next_bytes(
b_random_ctx *ctx, unsigned char *out, size_t nbytes);
#endif
-47
View File
@@ -1,47 +0,0 @@
#ifndef BLUE_CORE_RINGBUFFER_H_
#define BLUE_CORE_RINGBUFFER_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
B_DECLS_BEGIN;
#define B_TYPE_RINGBUFFER (b_ringbuffer_get_type())
B_DECLARE_TYPE(b_ringbuffer);
B_TYPE_CLASS_DECLARATION_BEGIN(b_ringbuffer)
B_TYPE_CLASS_DECLARATION_END(b_ringbuffer)
BLUE_API b_type b_ringbuffer_get_type(void);
BLUE_API b_ringbuffer *b_ringbuffer_create(size_t capacity);
BLUE_API b_ringbuffer *b_ringbuffer_create_with_buffer(void *ptr, size_t capacity);
BLUE_API b_status b_ringbuffer_clear(b_ringbuffer *buf);
BLUE_API b_status b_ringbuffer_read(
b_ringbuffer *buf, void *p, size_t count, size_t *nr_read);
BLUE_API b_status b_ringbuffer_write(
b_ringbuffer *buf, const void *p, size_t count, size_t *nr_written);
BLUE_API int b_ringbuffer_getc(b_ringbuffer *buf);
BLUE_API b_status b_ringbuffer_putc(b_ringbuffer *buf, int c);
BLUE_API size_t b_ringbuffer_write_capacity_remaining(const b_ringbuffer *buf);
BLUE_API size_t b_ringbuffer_available_data_remaining(const b_ringbuffer *buf);
BLUE_API b_status b_ringbuffer_open_read_buffer(
b_ringbuffer *buf, const void **ptr, size_t *length);
BLUE_API b_status b_ringbuffer_close_read_buffer(
b_ringbuffer *buf, const void **ptr, size_t nr_read);
BLUE_API b_status b_ringbuffer_open_write_buffer(
b_ringbuffer *buf, void **ptr, size_t *capacity);
BLUE_API b_status b_ringbuffer_close_write_buffer(
b_ringbuffer *buf, void **ptr, size_t nr_written);
B_DECLS_END;
#endif
-109
View File
@@ -1,109 +0,0 @@
#ifndef BLUE_CORE_ROPE_H_
#define BLUE_CORE_ROPE_H_
#include <blue/core/hash.h>
#include <blue/core/misc.h>
#include <blue/core/stream.h>
#include <stdint.h>
#include <string.h>
struct b_string;
struct b_bstr;
#define B_ROPE_TYPE(f) ((f) & 0xFF)
#define B_ROPE_CHAR(c) \
\
{ \
.r_flags = B_ROPE_F_CHAR, .r_len_total = 1, \
.r_v = {.v_char = (c) } \
}
#define B_ROPE_CSTR(str) \
{ \
.r_flags = B_ROPE_F_CSTR_BORROWED, \
.r_len_total = strlen(str), \
.r_v = { \
.v_cstr = { \
.s = (str), \
.hash = b_hash_cstr(str), \
}, \
}, \
}
#define B_ROPE_CSTR_STATIC(str) \
{ \
.r_flags = B_ROPE_F_CSTR_STATIC, \
.r_len_total = strlen(str), \
.r_v = { \
.v_cstr = { \
.s = (str), \
.hash = b_hash_cstr(str), \
}, \
}, \
}
#define B_ROPE_INT(v) \
\
{ \
.r_flags = B_ROPE_F_INT, .r_len_total = b_int_length(v), \
.r_v = {.v_int = (v) } \
}
#define B_ROPE_UINT(v) \
\
{ \
.r_flags = B_ROPE_F_UINT, .r_len_total = b_uint_length(v), \
.r_v = {.v_uint = (v) } \
}
typedef enum b_rope_flags {
B_ROPE_F_NONE = 0x0000u,
B_ROPE_F_CHAR = 0x0001u,
B_ROPE_F_CSTR = 0x0002u,
B_ROPE_F_CSTR_BORROWED = 0x0003u,
B_ROPE_F_CSTR_STATIC = 0x0004u,
B_ROPE_F_INT = 0x0005u,
B_ROPE_F_UINT = 0x0006u,
B_ROPE_F_COMPOSITE = 0x0007u,
B_ROPE_F_MALLOC = 0x0100u,
} b_rope_flags;
typedef struct b_rope {
b_rope_flags r_flags;
unsigned long r_len_left, r_len_total;
union {
char v_char;
intptr_t v_int;
uintptr_t v_uint;
struct {
const char *s;
uint64_t hash;
} v_cstr;
struct {
const struct b_rope *r_left, *r_right;
} v_composite;
} r_v;
} b_rope;
BLUE_API void b_rope_init_char(b_rope *rope, char c);
BLUE_API void b_rope_init_cstr(b_rope *rope, const char *s);
BLUE_API void b_rope_init_cstr_borrowed(b_rope *rope, const char *s);
BLUE_API void b_rope_init_cstr_static(b_rope *rope, const char *s);
BLUE_API void b_rope_init_int(b_rope *rope, intptr_t v);
BLUE_API void b_rope_init_uint(b_rope *rope, uintptr_t v);
BLUE_API void b_rope_destroy(b_rope *rope);
BLUE_API void b_rope_iterate(
const b_rope *rope, void (*func)(const b_rope *, void *), void *arg);
BLUE_API size_t b_rope_get_size(const b_rope *rope);
BLUE_API void b_rope_concat(b_rope *result, const b_rope *left, const b_rope *right);
BLUE_API void b_rope_join(b_rope *result, const b_rope **ropes, size_t nr_ropes);
BLUE_API b_status b_rope_to_cstr(const b_rope *rope, char *out, size_t max);
BLUE_API b_status b_rope_to_bstr(const b_rope *rope, struct b_bstr *str);
BLUE_API b_status b_rope_to_string(const b_rope *rope, b_stream *out);
#endif
-48
View File
@@ -1,48 +0,0 @@
#ifndef BLUELIB_CORE_STATUS_H_
#define BLUELIB_CORE_STATUS_H_
#include <blue/core/misc.h>
#define B_OK(status) ((enum b_status)((uintptr_t)(status)) == B_SUCCESS)
#define B_ERR(status) ((status) != B_SUCCESS)
typedef enum b_status {
B_SUCCESS = 0x00u,
B_ERR_NO_MEMORY,
B_ERR_OUT_OF_BOUNDS,
B_ERR_INVALID_ARGUMENT,
B_ERR_NAME_EXISTS,
B_ERR_NOT_SUPPORTED,
B_ERR_BAD_STATE,
B_ERR_NO_ENTRY,
B_ERR_NO_DATA,
B_ERR_NO_SPACE,
B_ERR_UNKNOWN_FUNCTION,
B_ERR_BAD_FORMAT,
B_ERR_IO_FAILURE,
B_ERR_IS_DIRECTORY,
B_ERR_NOT_DIRECTORY,
B_ERR_PERMISSION_DENIED,
B_ERR_BUSY,
/* blue-compress specific code */
B_ERR_COMPRESSION_FAILURE,
/* blue-object specific code */
B_ERR_TYPE_REGISTRATION_FAILURE,
B_ERR_CLASS_INIT_FAILURE,
} b_status;
typedef enum b_status_msg {
B_MSG_SUCCESS = 0,
/* blue-object specific messages */
B_MSG_TYPE_REGISTRATION_FAILURE,
B_MSG_CLASS_INIT_FAILURE,
B_MSG_CLASS_SPECIFIES_UNKNOWN_INTERFACE,
} b_status_msg;
BLUE_API const char *b_status_to_string(b_status status);
BLUE_API const char *b_status_description(b_status status);
#endif
-100
View File
@@ -1,100 +0,0 @@
#ifndef BLUE_CORE_STREAM_H_
#define BLUE_CORE_STREAM_H_
#include <blue/core/encoding.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdarg.h>
#include <stdio.h>
B_DECLS_BEGIN;
#define b_stdin (z__b_stream_get_stdin())
#define b_stdout (z__b_stream_get_stdout())
#define b_stderr (z__b_stream_get_stderr())
#define B_TYPE_STREAM (b_stream_get_type())
#define B_TYPE_STREAM_BUFFER (b_stream_buffer_get_type())
B_DECLARE_TYPE(b_stream);
B_DECLARE_TYPE(b_stream_buffer);
typedef enum b_stream_mode {
B_STREAM_READ = 0x01u,
B_STREAM_WRITE = 0x02u,
B_STREAM_BINARY = 0x10u,
Z__B_STREAM_STATIC = 0x80u,
} b_stream_mode;
typedef enum b_stream_seek_origin {
B_STREAM_SEEK_START = 0x01u,
B_STREAM_SEEK_CURRENT = 0x02u,
B_STREAM_SEEK_END = 0x03u,
} b_stream_seek_origin;
typedef struct b_stream_cfg {
b_stream_mode s_mode;
} b_stream_cfg;
B_TYPE_CLASS_DECLARATION_BEGIN(b_stream)
b_status (*s_close)(b_stream *);
b_status (*s_seek)(b_stream *, long long, b_stream_seek_origin);
b_status (*s_tell)(const b_stream *, size_t *);
b_status (*s_getc)(b_stream *, b_wchar *);
b_status (*s_read)(b_stream *, void *, size_t, size_t *);
b_status (*s_write)(b_stream *, const void *, size_t, size_t *);
b_status (*s_reserve)(b_stream *, size_t);
B_TYPE_CLASS_DECLARATION_END(b_stream)
B_TYPE_CLASS_DECLARATION_BEGIN(b_stream_buffer)
B_TYPE_CLASS_DECLARATION_END(b_stream_buffer)
BLUE_API b_type b_stream_get_type();
BLUE_API b_type b_stream_buffer_get_type();
BLUE_API b_stream *z__b_stream_get_stdin(void);
BLUE_API b_stream *z__b_stream_get_stdout(void);
BLUE_API b_stream *z__b_stream_get_stderr(void);
BLUE_API b_stream_buffer *b_stream_buffer_create(void *p, size_t len);
BLUE_API b_stream_buffer *b_stream_buffer_create_dynamic(size_t buffer_size);
BLUE_API b_stream *b_stream_open_fp(FILE *fp);
BLUE_API b_status b_stream_reserve(b_stream *stream, size_t len);
BLUE_API b_status b_stream_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin);
BLUE_API size_t b_stream_cursor(const b_stream *stream);
BLUE_API b_status b_stream_push_indent(b_stream *stream, int indent);
BLUE_API b_status b_stream_pop_indent(b_stream *stream);
BLUE_API b_status b_stream_read_char(b_stream *stream, b_wchar *c);
BLUE_API b_status b_stream_read_bytes(
b_stream *stream, void *buf, size_t count, size_t *nr_read);
BLUE_API b_status b_stream_read_line(b_stream *stream, char *s, size_t max);
BLUE_API b_status b_stream_read_line_s(b_stream *src, b_stream *dest);
BLUE_API b_status b_stream_read_all_bytes(
b_stream *stream, void *p, size_t max, size_t *nr_read);
BLUE_API b_status b_stream_read_all_bytes_s(
b_stream *src, b_stream *dest, b_stream_buffer *buffer, size_t *nr_read);
BLUE_API b_status b_stream_write_char(b_stream *stream, b_wchar c);
BLUE_API b_status b_stream_write_string(
b_stream *stream, const char *s, size_t *nr_written);
BLUE_API b_status b_stream_write_bytes(
b_stream *stream, const void *buf, size_t count, size_t *nr_written);
BLUE_API b_status b_stream_write_fmt(
b_stream *stream, size_t *nr_written, const char *format, ...);
BLUE_API b_status b_stream_write_vfmt(
b_stream *stream, size_t *nr_written, const char *format, va_list arg);
B_DECLS_END;
#endif
-35
View File
@@ -1,35 +0,0 @@
#ifndef BLUE_CORE_STRINGSTREAM_H_
#define BLUE_CORE_STRINGSTREAM_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <blue/core/stream.h>
#include <stddef.h>
B_DECLS_BEGIN;
#define B_TYPE_STRINGSTREAM (b_stringstream_get_type())
B_DECLARE_TYPE(b_stringstream);
B_TYPE_CLASS_DECLARATION_BEGIN(b_stringstream)
B_TYPE_CLASS_DECLARATION_END(b_stringstream)
BLUE_API b_type b_stringstream_get_type(void);
BLUE_API b_stringstream *b_stringstream_create(void);
BLUE_API b_stringstream *b_stringstream_create_with_buffer(char *buf, size_t max);
BLUE_API b_status b_stringstream_reset(b_stringstream *strv);
BLUE_API b_status b_stringstream_reset_with_buffer(
b_stringstream *strv, char *buf, size_t max);
BLUE_API const char *b_stringstream_ptr(const b_stringstream *strv);
BLUE_API char *b_stringstream_steal(b_stringstream *strv);
BLUE_API size_t b_stringstream_get_length(const b_stringstream *strv);
B_DECLS_END;
#endif
-36
View File
@@ -1,36 +0,0 @@
#ifndef BLUELIB_CORE_THREAD_H_
#define BLUELIB_CORE_THREAD_H_
#include <blue/core/bitop.h>
#include <blue/core/misc.h>
#include <stdbool.h>
#if defined(__APPLE__) || defined(__linux__)
#include <pthread.h>
#define B_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t b_mutex;
#else
#error Unsupported compiler/system
#endif
#define B_ONCE_INIT ((b_once)0)
typedef struct b_thread b_thread;
typedef int b_once;
static inline bool b_init_once(b_once *once)
{
int x = 0;
return b_cmpxchg(once, &x, 1);
}
BLUE_API b_thread *b_thread_self(void);
BLUE_API bool b_mutex_lock(b_mutex *mut);
BLUE_API bool b_mutex_trylock(b_mutex *mut);
BLUE_API bool b_mutex_unlock(b_mutex *mut);
#endif
-66
View File
@@ -1,66 +0,0 @@
#ifndef BLUE_CORE_TYPE_H_
#define BLUE_CORE_TYPE_H_
#include <blue/core/error.h>
#include <blue/core/misc.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define B_TYPE_MAX_INTERFACES 64
struct _b_class;
struct _b_object;
typedef void (*b_class_init_function)(struct _b_class *, void *);
typedef void (*b_instance_init_function)(struct _b_object *, void *);
typedef void (*b_instance_fini_function)(struct _b_object *, void *);
typedef const union b_type {
struct {
uint64_t p00, p01;
} a;
unsigned char b[16];
} *b_type;
typedef enum b_type_flags {
B_TYPE_F_ABSTRACT = 0x01u,
} b_type_flags;
typedef struct b_type_info {
union b_type t_id;
union b_type t_parent_id;
const char *t_name;
b_type_flags t_flags;
union b_type t_interfaces[B_TYPE_MAX_INTERFACES];
size_t t_nr_interfaces;
size_t t_class_size;
b_class_init_function t_class_init;
size_t t_instance_private_size;
size_t t_instance_protected_size;
b_instance_init_function t_instance_init;
b_instance_fini_function t_instance_fini;
} b_type_info;
BLUE_API void b_type_id_init(
union b_type *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
uint64_t e);
static inline void b_type_id_copy(b_type src, union b_type *dest)
{
dest->a.p00 = src->a.p00;
dest->a.p01 = src->a.p01;
}
static inline int b_type_id_compare(b_type a, b_type b)
{
if (a == b) {
return 0;
}
return memcmp(a, b, sizeof(union b_type));
}
BLUE_API b_result b_type_register(b_type_info *info);
#endif
-115
View File
@@ -1,115 +0,0 @@
#include <blue/core/iterator.h>
/*** PRIVATE DATA *************************************************************/
struct b_iterator_p {
enum b_status it_status;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static enum b_status iterator_get_status(const struct b_iterator_p *it)
{
return it->it_status;
}
static enum b_status iterator_set_status(struct b_iterator_p *it, b_status status)
{
it->it_status = status;
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_iterator *b_iterator_begin(b_iterable *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(b_iterable, B_TYPE_ITERABLE, NULL, it_begin, it);
}
const b_iterator *b_iterator_cbegin(const b_iterable *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(b_iterable, B_TYPE_ITERABLE, NULL, it_cbegin, it);
}
enum b_status b_iterator_get_status(const b_iterator *it)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ITERATOR, iterator_get_status, it);
}
enum b_status b_iterator_set_status(const b_iterator *it, b_status status)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ITERATOR, iterator_set_status, it, status);
}
enum b_status b_iterator_move_next(const b_iterator *it)
{
enum b_status status = B_ERR_NOT_SUPPORTED;
b_iterator_class *iface = b_object_get_interface(it, B_TYPE_ITERATOR);
if (iface && iface->it_move_next) {
status = iface->it_move_next(it);
}
struct b_iterator_p *p = b_object_get_private(it, B_TYPE_ITERATOR);
p->it_status = status;
return status;
}
b_iterator_value b_iterator_get_value(b_iterator *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(
b_iterator, B_TYPE_ITERATOR, B_ITERATOR_VALUE_NULL,
it_get_value, it);
}
const b_iterator_value b_iterator_get_cvalue(const b_iterator *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(
b_iterator, B_TYPE_ITERATOR, B_ITERATOR_VALUE_NULL,
it_get_cvalue, it);
}
b_status b_iterator_erase(b_iterator *it)
{
enum b_status status = B_ERR_NOT_SUPPORTED;
b_iterator_class *iface = b_object_get_interface(it, B_TYPE_ITERATOR);
if (iface && iface->it_erase) {
status = iface->it_erase(it);
}
struct b_iterator_p *p = b_object_get_private(it, B_TYPE_ITERATOR);
p->it_status = status;
return status;
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_iterator)
B_TYPE_DEFINITION_BEGIN(b_iterator)
B_TYPE_FLAGS(B_TYPE_F_ABSTRACT);
B_TYPE_ID(0xfd40b67f, 0x7087, 0x40a9, 0x8fd8, 0x8ae27bd58c9e);
B_TYPE_CLASS(b_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_iterator_p);
B_TYPE_DEFINITION_END(b_iterator)
// ---- b_iterable DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_iterable)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_iterable)
B_TYPE_DEFINITION_BEGIN(b_iterable)
B_TYPE_FLAGS(B_TYPE_F_ABSTRACT);
B_TYPE_ID(0x4bbabf2d, 0xfc5d, 0x40cc, 0x89fc, 0x164085e47f73);
B_TYPE_CLASS(b_iterable_class);
B_TYPE_DEFINITION_END(b_iterable)
-219
View File
@@ -1,219 +0,0 @@
#include "object.h"
#include "type.h"
#include <assert.h>
#include <blue/core/class.h>
#include <blue/core/macros.h>
#include <blue/core/object.h>
#include <blue/core/stream.h>
#include <blue/core/thread.h>
B_TYPE_CLASS_DEFINITION_BEGIN(b_object)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_object)
B_TYPE_DEFINITION_BEGIN(b_object)
B_TYPE_ID(0x45f15a2c, 0x6831, 0x4bef, 0xb350, 0x15c650679211);
B_TYPE_CLASS(b_object_class);
B_TYPE_DEFINITION_END(b_object)
b_result b_object_instantiate(
struct b_type_registration *type, struct _b_object **out_object)
{
struct _b_object *out = malloc(type->r_instance_size);
if (!out) {
return B_RESULT_ERR(NO_MEMORY);
}
memset(out, 0x0, type->r_instance_size);
out->obj_magic = B_OBJECT_MAGIC;
out->obj_type = type;
out->obj_ref = 1;
struct b_queue_entry *entry = b_queue_first(&type->r_class_hierarchy);
while (entry) {
struct b_type_component *comp
= b_unbox(struct b_type_component, entry, c_entry);
const struct b_type_info *class_info = comp->c_type->r_info;
void *private_data
= (char *)out + comp->c_instance_private_data_offset;
if (class_info->t_instance_init) {
class_info->t_instance_init(out, private_data);
}
if (comp->c_type == type) {
out->obj_main_priv_offset
= comp->c_instance_private_data_offset;
}
entry = b_queue_next(entry);
}
*out_object = out;
return B_RESULT_SUCCESS;
}
struct _b_object *b_object_create(b_type type)
{
struct b_type_registration *type_reg = b_type_get_registration(type);
if (!type_reg) {
return NULL;
}
struct _b_object *out = NULL;
b_result result = b_object_instantiate(type_reg, &out);
if (b_result_is_error(result)) {
b_error_discard(result);
return NULL;
}
return out;
}
void b_object_to_string(const struct _b_object *p, b_stream *out)
{
B_CLASS_DISPATCH_VIRTUAL_V(b_object, B_TYPE_OBJECT, to_string, p, out);
b_stream_write_fmt(out, NULL, "<%s@%p>", p->obj_type->r_info->t_name, p);
}
bool b_object_is_type(const struct _b_object *p, b_type type)
{
if (b_type_id_compare(&p->obj_type->r_info->t_id, type) == 0) {
return true;
}
struct b_type_component *comp
= b_type_get_component(&p->obj_type->r_components, type);
return comp != NULL;
}
void *b_object_get_private(const struct _b_object *object, b_type type)
{
if (!object) {
return NULL;
}
assert(object->obj_magic == B_OBJECT_MAGIC);
if (b_type_id_compare(&object->obj_type->r_info->t_id, type) == 0) {
return (char *)object + object->obj_main_priv_offset;
}
struct b_type_component *comp
= b_type_get_component(&object->obj_type->r_components, type);
if (!comp) {
return NULL;
}
return (char *)object + comp->c_instance_private_data_offset;
}
void *b_object_get_protected(const struct _b_object *object, b_type type)
{
if (!object) {
return NULL;
}
assert(object->obj_magic == B_OBJECT_MAGIC);
struct b_type_component *comp
= b_type_get_component(&object->obj_type->r_components, type);
if (!comp) {
return NULL;
}
return (char *)object + comp->c_instance_protected_data_offset;
}
void *b_object_get_interface(const struct _b_object *object, b_type type)
{
if (!object) {
return NULL;
}
assert(object->obj_magic == B_OBJECT_MAGIC);
return b_class_get_interface(object->obj_type->r_class, type);
}
enum b_status b_object_get_data(
const struct _b_object *object, b_type type, void **priv, void **prot,
void **iface)
{
if (!object) {
return B_ERR_INVALID_ARGUMENT;
}
assert(object->obj_magic == B_OBJECT_MAGIC);
struct b_type_component *comp
= b_type_get_component(&object->obj_type->r_components, type);
if (!comp) {
return B_ERR_INVALID_ARGUMENT;
}
if (priv) {
*priv = (char *)object + comp->c_instance_private_data_offset;
}
if (prot) {
*prot = (char *)object + comp->c_instance_protected_data_offset;
}
if (iface) {
*iface = (char *)object->obj_type->r_class
+ comp->c_class_data_offset;
}
return B_SUCCESS;
}
struct _b_object *b_object_ref(struct _b_object *p)
{
p->obj_ref++;
return p;
}
void b_object_unref(struct _b_object *p)
{
if (p->obj_ref > 1) {
p->obj_ref--;
return;
}
p->obj_ref = 0;
const struct b_type_registration *type = p->obj_type;
struct b_queue_entry *cur = b_queue_last(&type->r_class_hierarchy);
while (cur) {
struct b_type_component *comp
= b_unbox(struct b_type_component, cur, c_entry);
const struct b_type_info *class_info = comp->c_type->r_info;
void *private_data
= (char *)p + comp->c_instance_private_data_offset;
if (class_info->t_instance_fini) {
class_info->t_instance_fini(p, private_data);
}
cur = b_queue_prev(cur);
}
p->obj_magic = 0;
p->obj_type = NULL;
free(p);
}
struct _b_object *b_object_make_rvalue(struct _b_object *p)
{
p->obj_ref = 0;
return p;
}
-19
View File
@@ -1,19 +0,0 @@
#ifndef _OBJECT_H_
#define _OBJECT_H_
#include <blue/core/error.h>
#include <blue/core/misc.h>
#include <stdint.h>
struct b_type_registration;
struct _b_object {
uint64_t obj_magic;
const struct b_type_registration *obj_type;
unsigned int obj_ref, obj_main_priv_offset;
};
extern b_result b_object_instantiate(
struct b_type_registration *type, struct _b_object **out);
#endif
-245
View File
@@ -1,245 +0,0 @@
#include <blue/core/queue.h>
struct b_queue_iterator_p {
size_t i;
b_queue_entry *entry;
b_queue *_q;
};
size_t b_queue_length(const struct b_queue *q)
{
size_t i = 0;
struct b_queue_entry *x = q->q_first;
while (x) {
i++;
x = x->qe_next;
}
return i;
}
void b_queue_insert_before(
struct b_queue *q, struct b_queue_entry *entry, struct b_queue_entry *before)
{
struct b_queue_entry *x = before->qe_prev;
if (x) {
x->qe_next = entry;
} else {
q->q_first = entry;
}
entry->qe_prev = x;
before->qe_prev = entry;
entry->qe_next = before;
}
void b_queue_insert_after(
struct b_queue *q, struct b_queue_entry *entry, struct b_queue_entry *after)
{
struct b_queue_entry *x = after->qe_next;
if (x) {
x->qe_prev = entry;
} else {
q->q_last = entry;
}
entry->qe_next = x;
after->qe_next = entry;
entry->qe_prev = after;
}
void b_queue_push_front(struct b_queue *q, struct b_queue_entry *entry)
{
if (q->q_first) {
q->q_first->qe_prev = entry;
}
entry->qe_next = q->q_first;
entry->qe_prev = NULL;
q->q_first = entry;
if (!q->q_last) {
q->q_last = entry;
}
}
void b_queue_push_back(struct b_queue *q, struct b_queue_entry *entry)
{
if (q->q_last) {
q->q_last->qe_next = entry;
}
entry->qe_prev = q->q_last;
entry->qe_next = NULL;
q->q_last = entry;
if (!q->q_first) {
q->q_first = entry;
}
}
struct b_queue_entry *b_queue_pop_front(struct b_queue *q)
{
struct b_queue_entry *x = q->q_first;
if (x) {
b_queue_delete(q, x);
}
return x;
}
struct b_queue_entry *b_queue_pop_back(struct b_queue *q)
{
struct b_queue_entry *x = q->q_last;
if (x) {
b_queue_delete(q, x);
}
return x;
}
void b_queue_move(b_queue *q, b_queue_entry *dest, b_queue_entry *src)
{
if (src->qe_next) {
src->qe_next->qe_prev = dest;
}
if (src->qe_prev) {
src->qe_prev->qe_next = dest;
}
if (q->q_first == src) {
q->q_first = dest;
}
if (q->q_last == src) {
q->q_last = dest;
}
memmove(dest, src, sizeof *src);
}
void b_queue_delete(struct b_queue *q, struct b_queue_entry *entry)
{
if (!entry) {
return;
}
if (entry == q->q_first) {
q->q_first = q->q_first->qe_next;
}
if (entry == q->q_last) {
q->q_last = q->q_last->qe_prev;
}
if (entry->qe_next) {
entry->qe_next->qe_prev = entry->qe_prev;
}
if (entry->qe_prev) {
entry->qe_prev->qe_next = entry->qe_next;
}
entry->qe_next = entry->qe_prev = NULL;
}
void b_queue_delete_all(struct b_queue *q)
{
struct b_queue_entry *x = q->q_first;
while (x) {
struct b_queue_entry *next = x->qe_next;
x->qe_next = x->qe_prev = NULL;
x = next;
}
q->q_first = q->q_last = NULL;
}
b_iterator *b_queue_begin(struct b_queue *q)
{
b_queue_iterator *it_obj = b_object_create(B_TYPE_QUEUE_ITERATOR);
struct b_queue_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_QUEUE_ITERATOR);
it->_q = (struct b_queue *)q;
it->entry = q->q_first;
it->i = 0;
if (!it->entry) {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
}
return it_obj;
}
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_queue_iterator_p *it
= b_object_get_private(obj, B_TYPE_QUEUE_ITERATOR);
if (!it->entry) {
return B_ERR_NO_DATA;
}
it->entry = it->entry->qe_next;
it->i++;
return (it->entry != NULL) ? B_SUCCESS : B_ERR_NO_DATA;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_queue_iterator_p *it
= b_object_get_private(obj, B_TYPE_QUEUE_ITERATOR);
if (!it->entry) {
return B_ERR_OUT_OF_BOUNDS;
}
struct b_queue_entry *next = it->entry->qe_next;
b_queue_delete(it->_q, it->entry);
it->entry = next;
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_queue_iterator_p *it
= b_object_get_private(obj, B_TYPE_QUEUE_ITERATOR);
return B_ITERATOR_VALUE_PTR(it->entry);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_queue_iterator_p *it
= b_object_get_private(obj, B_TYPE_QUEUE_ITERATOR);
return B_ITERATOR_VALUE_CPTR(it->entry);
}
B_TYPE_CLASS_DEFINITION_BEGIN(b_queue_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_queue_iterator)
B_TYPE_DEFINITION_BEGIN(b_queue_iterator)
B_TYPE_ID(0x560dc263, 0xff98, 0x4812, 0x9b29, 0xa1218bd70881);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_queue_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_queue_iterator_p);
B_TYPE_DEFINITION_END(b_queue_iterator)
-18
View File
@@ -1,18 +0,0 @@
#ifndef _BLUELIB_RANDOM_H_
#define _BLUELIB_RANDOM_H_
#include <stdint.h>
#include <blue/core/misc.h>
struct b_random_ctx;
struct b_random_algorithm {
const char *gen_name;
void(*gen_init)(struct b_random_ctx *, unsigned long long seed);
uint64_t(*gen_getrand)(struct b_random_ctx *);
};
BLUE_API uint64_t z__b_platform_random_seed(void);
BLUE_API uint64_t z__b_platform_random_seed_secure(void);
#endif
-275
View File
@@ -1,275 +0,0 @@
#include <blue/core/bstr.h>
#include <blue/core/rope.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void b_rope_init_char(struct b_rope *rope, char c)
{
memset(rope, 0x0, sizeof *rope);
rope->r_flags = B_ROPE_F_CHAR;
rope->r_len_left = rope->r_len_total = 1;
rope->r_v.v_char = c;
}
void b_rope_init_cstr(struct b_rope *rope, const char *s)
{
memset(rope, 0x0, sizeof *rope);
rope->r_flags = B_ROPE_F_CSTR;
rope->r_v.v_cstr.hash = b_hash_cstr_ex(s, &rope->r_len_total);
rope->r_len_left = rope->r_len_total;
char *s2 = malloc(rope->r_len_total + 1);
if (!s2) {
return;
}
strcpy(s2, s);
s2[rope->r_len_total] = '\0';
rope->r_v.v_cstr.s = s2;
}
void b_rope_init_cstr_borrowed(struct b_rope *rope, const char *s)
{
memset(rope, 0x0, sizeof *rope);
rope->r_flags = B_ROPE_F_CSTR_BORROWED;
rope->r_v.v_cstr.s = s;
rope->r_v.v_cstr.hash = b_hash_cstr_ex(s, &rope->r_len_total);
rope->r_len_left = rope->r_len_total;
}
void b_rope_init_cstr_static(struct b_rope *rope, const char *s)
{
memset(rope, 0x0, sizeof *rope);
rope->r_flags = B_ROPE_F_CSTR_STATIC;
rope->r_v.v_cstr.s = s;
rope->r_v.v_cstr.hash = b_hash_cstr_ex(s, &rope->r_len_total);
rope->r_len_left = rope->r_len_total;
}
void b_rope_init_int(struct b_rope *rope, intptr_t v)
{
memset(rope, 0x0, sizeof *rope);
rope->r_flags = B_ROPE_F_INT;
rope->r_len_left = rope->r_len_total = b_int_length(v);
rope->r_v.v_int = v;
}
void b_rope_init_uint(struct b_rope *rope, uintptr_t v)
{
memset(rope, 0x0, sizeof *rope);
rope->r_flags = B_ROPE_F_UINT;
rope->r_len_left = rope->r_len_total = b_uint_length(v);
rope->r_v.v_uint = v;
}
void b_rope_destroy(struct b_rope *rope)
{
unsigned int type = B_ROPE_TYPE(rope->r_flags);
switch (type) {
case B_ROPE_F_CSTR:
free((char *)rope->r_v.v_cstr.s);
break;
case B_ROPE_F_COMPOSITE:
b_rope_destroy((struct b_rope *)rope->r_v.v_composite.r_left);
b_rope_destroy((struct b_rope *)rope->r_v.v_composite.r_right);
break;
default:
break;
}
if (rope->r_flags & B_ROPE_F_MALLOC) {
free(rope);
}
}
void b_rope_iterate(
const struct b_rope *rope, void (*func)(const b_rope *, void *), void *arg)
{
if (B_ROPE_TYPE(rope->r_flags) != B_ROPE_F_COMPOSITE) {
func(rope, arg);
return;
}
if (rope->r_v.v_composite.r_left) {
b_rope_iterate(rope->r_v.v_composite.r_left, func, arg);
}
if (rope->r_v.v_composite.r_right) {
b_rope_iterate(rope->r_v.v_composite.r_right, func, arg);
}
}
size_t b_rope_get_size(const struct b_rope *rope)
{
return rope->r_len_total;
}
void b_rope_concat(
struct b_rope *result, const struct b_rope *left, const struct b_rope *right)
{
memset(result, 0x0, sizeof *result);
result->r_flags = B_ROPE_F_COMPOSITE;
result->r_len_left = left->r_len_total;
result->r_len_total = left->r_len_total + right->r_len_total;
result->r_v.v_composite.r_left = left;
result->r_v.v_composite.r_right = right;
}
static struct b_rope *create_composite_node(void)
{
struct b_rope *out = malloc(sizeof *out);
if (!out) {
return NULL;
}
memset(out, 0x0, sizeof *out);
out->r_flags = B_ROPE_F_COMPOSITE | B_ROPE_F_MALLOC;
return out;
}
void b_rope_join(b_rope *result, const b_rope **ropes, size_t nr_ropes)
{
if (nr_ropes == 0) {
return;
}
if (nr_ropes == 1) {
*result = *ropes[0];
return;
}
struct b_rope *prev = NULL;
for (size_t i = 0; i < nr_ropes - 1; i++) {
const struct b_rope *left = ropes[i];
const struct b_rope *right = ropes[i + 1];
if (prev) {
left = prev;
}
struct b_rope *composite = create_composite_node();
if (!composite) {
return;
}
composite->r_len_left = left->r_len_total;
composite->r_len_total = left->r_len_total + right->r_len_total;
composite->r_v.v_composite.r_left = left;
composite->r_v.v_composite.r_right = right;
prev = composite;
}
*result = *prev;
result->r_flags &= ~B_ROPE_F_MALLOC;
free(prev);
}
static void rope_iterate(
const struct b_rope *rope,
void (*callback)(const struct b_rope *, void *), void *arg)
{
unsigned int type = B_ROPE_TYPE(rope->r_flags);
switch (type) {
case B_ROPE_F_CHAR:
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
case B_ROPE_F_INT:
case B_ROPE_F_UINT:
callback(rope, arg);
break;
case B_ROPE_F_COMPOSITE:
rope_iterate(rope->r_v.v_composite.r_left, callback, arg);
rope_iterate(rope->r_v.v_composite.r_right, callback, arg);
break;
default:
break;
}
}
static void to_bstr(const struct b_rope *rope, void *arg)
{
b_bstr *str = arg;
unsigned int type = B_ROPE_TYPE(rope->r_flags);
switch (type) {
case B_ROPE_F_CHAR:
b_bstr_write_char(str, rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
b_bstr_write_cstr(str, rope->r_v.v_cstr.s, NULL);
break;
case B_ROPE_F_INT:
b_bstr_write_fmt(str, NULL, "%" PRIdPTR, rope->r_v.v_int);
break;
case B_ROPE_F_UINT:
b_bstr_write_fmt(str, NULL, "%" PRIuPTR, rope->r_v.v_uint);
break;
default:
break;
}
}
static void to_stream(const struct b_rope *rope, void *arg)
{
b_stream *out = arg;
unsigned int type = B_ROPE_TYPE(rope->r_flags);
switch (type) {
case B_ROPE_F_CHAR:
b_stream_write_char(out, rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
b_stream_write_string(out, rope->r_v.v_cstr.s, NULL);
break;
case B_ROPE_F_INT:
b_stream_write_fmt(out, NULL, "%" PRIdPTR, rope->r_v.v_int);
break;
case B_ROPE_F_UINT:
b_stream_write_fmt(out, NULL, "%" PRIuPTR, rope->r_v.v_uint);
break;
default:
break;
}
}
b_status b_rope_to_cstr(const struct b_rope *rope, char *out, size_t max)
{
b_bstr str;
b_bstr_begin(&str, out, max);
rope_iterate(rope, to_bstr, &str);
return B_SUCCESS;
}
b_status b_rope_to_bstr(const struct b_rope *rope, b_bstr *str)
{
rope_iterate(rope, to_bstr, str);
return B_SUCCESS;
}
b_status b_rope_to_string(const struct b_rope *rope, b_stream *out)
{
rope_iterate(rope, to_stream, out);
return B_SUCCESS;
}
-60
View File
@@ -1,60 +0,0 @@
#include <blue/core/status.h>
#include <stddef.h>
#define ENUM_STR(s) \
case s: \
return #s;
#define ENUM_STR2(c, s) \
case c: \
return s;
const char *b_status_to_string(b_status status)
{
switch (status) {
ENUM_STR(B_SUCCESS);
ENUM_STR(B_ERR_NO_MEMORY);
ENUM_STR(B_ERR_OUT_OF_BOUNDS);
ENUM_STR(B_ERR_INVALID_ARGUMENT);
ENUM_STR(B_ERR_NAME_EXISTS);
ENUM_STR(B_ERR_NOT_SUPPORTED);
ENUM_STR(B_ERR_BAD_STATE);
ENUM_STR(B_ERR_NO_ENTRY);
ENUM_STR(B_ERR_NO_DATA);
ENUM_STR(B_ERR_NO_SPACE);
ENUM_STR(B_ERR_UNKNOWN_FUNCTION);
ENUM_STR(B_ERR_BAD_FORMAT);
ENUM_STR(B_ERR_IO_FAILURE);
ENUM_STR(B_ERR_IS_DIRECTORY);
ENUM_STR(B_ERR_NOT_DIRECTORY);
ENUM_STR(B_ERR_PERMISSION_DENIED);
ENUM_STR(B_ERR_BUSY);
default:
return NULL;
}
}
const char *b_status_description(b_status status)
{
switch (status) {
ENUM_STR2(B_SUCCESS, "Success");
ENUM_STR2(B_ERR_NO_MEMORY, "Out of memory");
ENUM_STR2(B_ERR_OUT_OF_BOUNDS, "Argument out of bounds");
ENUM_STR2(B_ERR_INVALID_ARGUMENT, "Invalid argument");
ENUM_STR2(B_ERR_NAME_EXISTS, "Name already exists");
ENUM_STR2(B_ERR_NOT_SUPPORTED, "Operation not supported");
ENUM_STR2(B_ERR_BAD_STATE, "Bad state");
ENUM_STR2(B_ERR_NO_ENTRY, "No entry");
ENUM_STR2(B_ERR_NO_DATA, "No data available");
ENUM_STR2(B_ERR_NO_SPACE, "No space available");
ENUM_STR2(B_ERR_UNKNOWN_FUNCTION, "Unknown function");
ENUM_STR2(B_ERR_BAD_FORMAT, "Bad format");
ENUM_STR2(B_ERR_IO_FAILURE, "I/O failure");
ENUM_STR2(B_ERR_IS_DIRECTORY, "Object is a directory");
ENUM_STR2(B_ERR_NOT_DIRECTORY, "Object is not a directory");
ENUM_STR2(B_ERR_PERMISSION_DENIED, "Permission denied");
ENUM_STR2(B_ERR_BUSY, "Resource busy or locked");
default:
return NULL;
}
}
-1134
View File
File diff suppressed because it is too large Load Diff
-297
View File
@@ -1,297 +0,0 @@
#include <blue/core/stringstream.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_CAPACITY 15
/*** PRIVATE DATA *************************************************************/
struct b_stringstream_p {
char *ss_buf;
size_t ss_ptr;
size_t ss_len;
size_t ss_max;
unsigned char ss_alloc;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static enum b_status __getc(struct b_stringstream_p *ss, b_wchar *out)
{
size_t available = ss->ss_len - ss->ss_ptr;
const char *p = ss->ss_buf + ss->ss_ptr;
size_t to_copy = b_wchar_utf8_codepoint_stride(p);
if (to_copy > available) {
return B_ERR_BAD_STATE;
}
b_wchar c = b_wchar_utf8_codepoint_decode(p);
*out = c;
if (c == B_WCHAR_INVALID) {
return B_ERR_BAD_STATE;
}
ss->ss_ptr += to_copy;
return B_SUCCESS;
}
static enum b_status __gets(
struct b_stringstream_p *ss, char *s, size_t len, size_t *nr_read)
{
size_t available = ss->ss_len - ss->ss_ptr;
size_t to_copy = len;
if (available < to_copy) {
to_copy = available;
}
memcpy(s, ss->ss_buf + ss->ss_ptr, to_copy);
ss->ss_ptr += to_copy;
if (nr_read) {
*nr_read = to_copy;
}
return B_SUCCESS;
}
static enum b_status __puts(
struct b_stringstream_p *ss, const char *s, size_t len, size_t *nr_written)
{
size_t available = ss->ss_max - ss->ss_len;
size_t to_copy = len;
if (to_copy > available && ss->ss_alloc == 1) {
char *new_buf = realloc(ss->ss_buf, ss->ss_len + to_copy + 1);
if (!new_buf) {
return B_ERR_NO_MEMORY;
}
ss->ss_buf = new_buf;
ss->ss_max = ss->ss_len + to_copy;
available = ss->ss_max - ss->ss_len;
}
if (available < to_copy) {
to_copy = available;
}
memcpy(ss->ss_buf + ss->ss_len, s, to_copy);
/* increment the length by the full string length, even if only a
* portion was copied */
ss->ss_len += len;
if (nr_written) {
*nr_written = to_copy;
}
return B_SUCCESS;
}
static enum b_status stringstream_reset(struct b_stringstream_p *ss)
{
ss->ss_len = 0;
if (ss->ss_buf) {
*ss->ss_buf = 0;
}
return B_SUCCESS;
}
static enum b_status stringstream_reset_with_buffer(
struct b_stringstream_p *ss, char *buf, size_t max)
{
ss->ss_len = 0;
if (ss->ss_buf && ss->ss_alloc) {
free(ss->ss_buf);
}
ss->ss_buf = buf;
ss->ss_max = max;
ss->ss_alloc = 0;
return B_SUCCESS;
}
static size_t stringstream_get_length(const struct b_stringstream_p *strv)
{
return strv->ss_len;
}
static const char *stringstream_ptr(const struct b_stringstream_p *ss)
{
return ss->ss_buf;
}
static char *stringstream_steal(struct b_stringstream_p *ss)
{
char *out = ss->ss_buf;
memset(ss, 0x0, sizeof *ss);
ss->ss_alloc = 1;
return out;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_stringstream *b_stringstream_create_with_buffer(char *buf, size_t max)
{
b_stringstream *s = b_object_create(B_TYPE_STRINGSTREAM);
if (!s) {
return NULL;
}
b_stream_cfg *cfg = b_object_get_protected(s, B_TYPE_STREAM);
struct b_stringstream_p *p = b_object_get_private(s, B_TYPE_STRINGSTREAM);
cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE | Z__B_STREAM_STATIC;
p->ss_buf = buf;
p->ss_max = max;
p->ss_len = 0;
p->ss_alloc = 0;
return s;
}
b_stringstream *b_stringstream_create(void)
{
b_stringstream *s = b_object_create(B_TYPE_STRINGSTREAM);
if (!s) {
return NULL;
}
b_stream_cfg *cfg = b_object_get_protected(s, B_TYPE_STREAM);
struct b_stringstream_p *p = b_object_get_private(s, B_TYPE_STRINGSTREAM);
cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE | Z__B_STREAM_STATIC;
p->ss_buf = malloc(DEFAULT_CAPACITY + 1);
if (!p->ss_buf) {
b_stringstream_unref(s);
return NULL;
}
memset(p->ss_buf, 0x0, DEFAULT_CAPACITY + 1);
p->ss_max = DEFAULT_CAPACITY;
p->ss_len = 0;
p->ss_alloc = 1;
return s;
}
size_t b_stringstream_get_length(const b_stringstream *strv)
{
B_CLASS_DISPATCH_STATIC_0(
B_TYPE_STRINGSTREAM, stringstream_get_length, strv);
}
enum b_status b_stringstream_reset(b_stringstream *strv)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_STRINGSTREAM, stringstream_reset, strv);
}
enum b_status b_stringstream_reset_with_buffer(
b_stringstream *strv, char *buf, size_t max)
{
B_CLASS_DISPATCH_STATIC(
B_TYPE_STRINGSTREAM, stringstream_reset_with_buffer, strv, buf,
max);
}
const char *b_stringstream_ptr(const b_stringstream *ss)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_STRINGSTREAM, stringstream_ptr, ss);
}
char *b_stringstream_steal(b_stringstream *ss)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_STRINGSTREAM, stringstream_steal, ss);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void stringstream_init(b_object *obj, void *priv)
{
struct b_stringstream_p *stream = priv;
}
static void stringstream_fini(b_object *obj, void *priv)
{
struct b_stringstream_p *stream = priv;
if (stream->ss_alloc && stream->ss_buf) {
free(stream->ss_buf);
}
}
enum b_status stream_getc(b_stream *stream, b_wchar *c)
{
struct b_stringstream_p *s
= b_object_get_private(stream, B_TYPE_STRINGSTREAM);
enum b_status status = __getc(s, c);
return status;
}
enum b_status stream_read(b_stream *stream, void *buf, size_t count, size_t *nr_read)
{
struct b_stringstream_p *s
= b_object_get_private(stream, B_TYPE_STRINGSTREAM);
enum b_status status = __gets(s, buf, count, nr_read);
return status;
}
enum b_status stream_write(
b_stream *stream, const void *buf, size_t count, size_t *nr_written)
{
struct b_stringstream_p *s
= b_object_get_private(stream, B_TYPE_STRINGSTREAM);
enum b_status status = __puts(s, (const char *)buf, count, nr_written);
return status;
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_stringstream)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_stream, B_TYPE_STREAM)
B_INTERFACE_ENTRY(s_close) = NULL;
B_INTERFACE_ENTRY(s_seek) = NULL;
B_INTERFACE_ENTRY(s_tell) = NULL;
B_INTERFACE_ENTRY(s_getc) = stream_getc;
B_INTERFACE_ENTRY(s_read) = stream_read;
B_INTERFACE_ENTRY(s_write) = stream_write;
B_INTERFACE_ENTRY(s_reserve) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)
B_TYPE_CLASS_DEFINITION_END(b_stringstream)
B_TYPE_DEFINITION_BEGIN(b_stringstream)
B_TYPE_ID(0x508a609a, 0xfac5, 0x4d31, 0x843a, 0x44b68ad329f3);
B_TYPE_EXTENDS(B_TYPE_STREAM);
B_TYPE_CLASS(b_stringstream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stringstream_p);
B_TYPE_INSTANCE_INIT(stringstream_init);
B_TYPE_INSTANCE_FINI(stringstream_fini);
B_TYPE_DEFINITION_END(b_stringstream)
-319
View File
@@ -1,319 +0,0 @@
#include "type.h"
#include "class.h"
#include "object.h"
#include <blue/core/btree.h>
#include <blue/core/endian.h>
#include <blue/core/object.h>
#include <blue/core/type.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct b_btree type_list = B_BTREE_INIT;
static union b_type zero_id = {0};
struct type_init_ctx {
size_t ctx_class_offset;
size_t ctx_instance_offset;
};
static inline int registration_compare(
const struct b_type_registration *a, const struct b_type_registration *b)
{
return b_type_id_compare(&a->r_info->t_id, &b->r_info->t_id);
}
static inline int component_compare(
const struct b_type_component *a, const struct b_type_component *b)
{
return b_type_id_compare(&a->c_type->r_info->t_id, &b->c_type->r_info->t_id);
}
B_BTREE_DEFINE_INSERT(
struct b_type_registration, r_node, r_info->r_id, put_type,
registration_compare)
B_BTREE_DEFINE_INSERT(
struct b_type_component, c_node, &c_type->r_info->t_id,
put_type_component, component_compare)
static struct b_type_registration *get_type(
const b_btree *tree, const union b_type *key)
{
b_btree_node *cur = tree->b_root;
while (cur) {
struct b_type_registration *cur_node
= b_unbox(struct b_type_registration, cur, r_node);
int cmp = b_type_id_compare(key, &cur_node->r_info->t_id);
if (cmp > 0) {
cur = b_btree_right(cur);
} else if (cmp < 0) {
cur = b_btree_left(cur);
} else {
return cur_node;
}
}
return NULL;
}
struct b_type_component *b_type_get_component(
const b_btree *tree, const union b_type *key)
{
b_btree_node *cur = tree->b_root;
while (cur) {
struct b_type_component *cur_node
= b_unbox(struct b_type_component, cur, c_node);
int cmp = b_type_id_compare(key, &cur_node->c_type->r_info->t_id);
if (cmp > 0) {
cur = b_btree_right(cur);
} else if (cmp < 0) {
cur = b_btree_left(cur);
} else {
return cur_node;
}
}
return NULL;
}
static struct b_type_component *create_type_component(
const struct b_type_registration *type_reg)
{
struct b_type_component *c = malloc(sizeof *c);
if (!c) {
return NULL;
}
memset(c, 0x0, sizeof *c);
c->c_type = type_reg;
return c;
}
void b_type_id_init(
union b_type *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
uint64_t e)
{
b_i32 x_a = b_i32_htob(a);
b_i16 x_b = b_i16_htob(b);
b_i16 x_c = b_i16_htob(c);
b_i16 x_d = b_i16_htob(d);
b_i64 x_e = b_i64_htob(e);
memcpy(&out->b[0], x_a.i_bytes, sizeof x_a.i_bytes);
memcpy(&out->b[4], x_b.i_bytes, sizeof x_b.i_bytes);
memcpy(&out->b[6], x_c.i_bytes, sizeof x_c.i_bytes);
memcpy(&out->b[8], x_d.i_bytes, sizeof x_d.i_bytes);
memcpy(&out->b[10], &x_e.i_bytes[2], sizeof x_e.i_bytes - 2);
}
static void initialise_type_component(
struct b_type_component *comp, const struct b_type_info *info,
struct type_init_ctx *init_ctx)
{
comp->c_class_data_offset = init_ctx->ctx_class_offset;
comp->c_class_data_size = info->t_class_size;
init_ctx->ctx_class_offset += comp->c_class_data_size;
comp->c_instance_private_data_offset = init_ctx->ctx_instance_offset;
comp->c_instance_private_data_size = info->t_instance_private_size;
init_ctx->ctx_instance_offset += comp->c_instance_private_data_size;
comp->c_instance_protected_data_offset = init_ctx->ctx_instance_offset;
comp->c_instance_protected_data_size = info->t_instance_protected_size;
init_ctx->ctx_instance_offset += comp->c_instance_protected_data_size;
}
static b_result locate_interface(
b_type interface_id, struct b_type_registration *dest,
struct type_init_ctx *init_ctx)
{
struct b_type_component *interface_comp
= b_type_get_component(&dest->r_components, interface_id);
if (interface_comp) {
return B_RESULT_SUCCESS;
}
struct b_type_registration *interface_reg
= get_type(&type_list, interface_id);
if (!interface_reg) {
return B_RESULT_ERR(NO_ENTRY);
}
interface_comp = create_type_component(interface_reg);
if (!interface_comp) {
return B_RESULT_ERR(NO_MEMORY);
}
initialise_type_component(interface_comp, interface_reg->r_info, init_ctx);
put_type_component(&dest->r_components, interface_comp);
return B_RESULT_SUCCESS;
}
static b_result locate_interfaces(
const union b_type *interfaces, size_t nr_interfaces,
struct b_type_registration *dest, struct type_init_ctx *init_ctx)
{
b_result result = B_RESULT_SUCCESS;
for (size_t i = 0; i < nr_interfaces; i++) {
b_type interface_id = &interfaces[i];
result = locate_interface(interface_id, dest, init_ctx);
if (b_result_is_error(result)) {
break;
}
}
return result;
}
static b_result find_type_components(struct b_type_registration *reg)
{
const struct b_type_info *current = reg->r_info;
struct b_type_component *comp = create_type_component(reg);
if (!comp) {
return B_RESULT_ERR(NO_MEMORY);
}
struct type_init_ctx init_ctx = {
.ctx_instance_offset = sizeof(struct _b_object),
.ctx_class_offset = sizeof(struct _b_class),
};
put_type_component(&reg->r_components, comp);
b_queue_push_front(&reg->r_class_hierarchy, &comp->c_entry);
b_result result = locate_interfaces(
current->t_interfaces, current->t_nr_interfaces, reg, &init_ctx);
if (b_result_is_error(result)) {
return result;
}
b_type current_id = &current->t_parent_id;
if (!current_id || b_type_id_compare(current_id, &zero_id) == 0) {
goto skip_class_hierarchy;
}
while (1) {
struct b_type_registration *dep_class
= get_type(&type_list, current_id);
if (!dep_class) {
return B_RESULT_ERR(NO_ENTRY);
}
comp = b_type_get_component(&reg->r_components, current_id);
if (comp) {
/* circular class dependency */
// result = B_RESULT_ERR(INVALID_ARGUMENT);
// break;
current_id = &dep_class->r_info->t_parent_id;
continue;
}
comp = create_type_component(dep_class);
result = locate_interfaces(
dep_class->r_info->t_interfaces,
dep_class->r_info->t_nr_interfaces, reg, &init_ctx);
if (b_result_is_error(result)) {
break;
}
put_type_component(&reg->r_components, comp);
b_queue_push_front(&reg->r_class_hierarchy, &comp->c_entry);
if (b_type_id_compare(current_id, B_TYPE_OBJECT) == 0) {
break;
}
current_id = &dep_class->r_info->t_parent_id;
}
b_queue_entry *entry = b_queue_first(&reg->r_class_hierarchy);
while (entry) {
comp = b_unbox(struct b_type_component, entry, c_entry);
initialise_type_component(comp, comp->c_type->r_info, &init_ctx);
entry = b_queue_next(entry);
}
b_btree_node *node = b_btree_first(&reg->r_components);
while (node) {
comp = b_unbox(struct b_type_component, node, c_node);
if (comp->c_type->r_category == B_TYPE_CLASS) {
/* this component was already initialised above */
node = b_btree_next(node);
continue;
}
initialise_type_component(comp, comp->c_type->r_info, &init_ctx);
node = b_btree_next(node);
}
skip_class_hierarchy:
reg->r_instance_size = init_ctx.ctx_instance_offset;
reg->r_class_size = init_ctx.ctx_class_offset;
return result;
}
static bool type_has_base_class(struct b_type_info *info)
{
if (b_type_id_compare(&info->t_id, B_TYPE_OBJECT) == 0) {
return true;
}
return b_type_id_compare(&info->t_parent_id, &zero_id) != 0;
}
b_result b_type_register(struct b_type_info *info)
{
if (!type_has_base_class(info)) {
b_type_id_copy(B_TYPE_OBJECT, &info->t_parent_id);
}
struct b_type_registration *r = get_type(&type_list, &info->t_id);
if (r) {
return B_RESULT_ERR(NAME_EXISTS);
}
r = malloc(sizeof *r);
if (!r) {
return B_RESULT_ERR(NO_MEMORY);
}
memset(r, 0x0, sizeof *r);
r->r_category = B_TYPE_CLASS;
r->r_info = info;
b_result result = find_type_components(r);
if (b_result_is_error(result)) {
free(r);
return b_result_propagate(result);
}
result = b_class_instantiate(r, &r->r_class);
if (!r->r_class) {
free(r);
return b_error_with_msg_template_caused_by_error(
B_ERRORS_BUILTIN, B_ERR_TYPE_REGISTRATION_FAILURE,
result, B_MSG_TYPE_REGISTRATION_FAILURE,
B_ERROR_PARAM("typename", info->t_name));
}
put_type(&type_list, r);
return B_RESULT_SUCCESS;
}
struct b_type_registration *b_type_get_registration(b_type id)
{
return get_type(&type_list, id);
}
-40
View File
@@ -1,40 +0,0 @@
#ifndef _TYPE_H_
#define _TYPE_H_
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#include <blue/core/type.h>
#include <stddef.h>
enum b_type_category {
B_TYPE_NONE = 0,
B_TYPE_CLASS,
B_TYPE_INTERFACE,
};
struct b_type_component {
struct b_btree_node c_node;
struct b_queue_entry c_entry;
const struct b_type_registration *c_type;
size_t c_class_data_offset, c_class_data_size;
size_t c_instance_private_data_offset, c_instance_private_data_size;
size_t c_instance_protected_data_offset, c_instance_protected_data_size;
};
struct b_type_registration {
enum b_type_category r_category;
struct b_btree_node r_node;
const b_type_info *r_info;
struct _b_class *r_class;
struct b_btree r_components;
struct b_queue r_class_hierarchy;
size_t r_instance_size, r_class_size;
};
extern struct b_type_registration *b_type_get_registration(b_type id);
extern struct b_type_component *b_type_get_component(
const b_btree *tree, const union b_type *key);
#endif
-3
View File
@@ -1,3 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_module(NAME ds DEPENDENCIES core)
-521
View File
@@ -1,521 +0,0 @@
#include <blue/core/iterator.h>
#include <blue/core/stream.h>
#include <blue/ds/array.h>
#include <blue/ds/string.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
struct b_array_p {
/* number of items in array */
size_t ar_len;
/* maximum number of items that can currently be stored in array */
size_t ar_cap;
b_object **ar_data;
};
struct b_array_iterator_p {
b_array *_a;
struct b_array_p *_a_p;
/** The index of the current value */
size_t i;
/** The current value */
b_object *value;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static b_status resize_array(struct b_array_p *array, size_t new_capacity)
{
if (array->ar_cap < new_capacity) {
void *new_data = realloc(
array->ar_data, new_capacity * sizeof(struct b_dsref *));
if (!new_data) {
return B_ERR_NO_MEMORY;
}
array->ar_data = new_data;
} else {
for (size_t i = new_capacity; i < array->ar_len; i++) {
b_object_unref(array->ar_data[i]);
}
void *new_data = realloc(
array->ar_data, new_capacity * sizeof(struct b_dsref *));
if (!new_data) {
return B_ERR_NO_MEMORY;
}
array->ar_data = new_data;
}
array->ar_cap = new_capacity;
if (array->ar_len > new_capacity) {
array->ar_len = new_capacity;
}
return B_SUCCESS;
}
static b_status array_insert(struct b_array_p *array, b_object *value, size_t at)
{
if (at == B_NPOS) {
at = array->ar_len;
}
if (at > array->ar_len) {
return B_ERR_OUT_OF_BOUNDS;
}
b_status status = B_SUCCESS;
if (array->ar_len + 1 > array->ar_cap) {
status = resize_array(array, array->ar_cap + 8);
if (status != B_SUCCESS) {
return status;
}
}
b_object **src = array->ar_data + at;
b_object **dest = src + 1;
size_t move_len = (array->ar_len - at) * sizeof(struct b_dsref *);
memmove(dest, src, move_len);
array->ar_data[at] = b_object_ref(value);
array->ar_len++;
return B_SUCCESS;
}
static b_status array_remove(struct b_array_p *array, size_t at)
{
if (at >= array->ar_len) {
return B_ERR_OUT_OF_BOUNDS;
}
b_object **src = array->ar_data + at;
b_object **dest = src + 1;
size_t move_len = array->ar_len * sizeof(struct b_dsref *);
b_object_unref(array->ar_data[at]);
memmove(dest, src, move_len);
array->ar_len--;
return B_SUCCESS;
}
static b_status array_remove_front(struct b_array_p *array)
{
return array_remove(array, 0);
}
static b_status array_remove_back(struct b_array_p *array)
{
return array_remove(array, array->ar_len - 1);
}
static b_object *array_pop(struct b_array_p *array, size_t at)
{
if (at >= array->ar_len) {
return NULL;
}
b_object **src = array->ar_data + at;
b_object **dest = src + 1;
size_t move_len = array->ar_len * sizeof(struct b_dsref *);
b_object *out = array->ar_data[at];
memmove(dest, src, move_len);
array->ar_len--;
return out;
}
static b_object *array_pop_front(struct b_array_p *array)
{
return array_pop(array, 0);
}
static b_object *array_pop_back(struct b_array_p *array)
{
return array_pop(array, array->ar_len - 1);
}
static b_object *array_at(const struct b_array_p *array, size_t at)
{
if (at >= array->ar_len) {
return NULL;
}
return array->ar_data[at];
}
static b_object *array_get(struct b_array_p *array, size_t at)
{
if (at >= array->ar_len) {
return NULL;
}
return b_object_ref(array->ar_data[at]);
}
static size_t array_size(const struct b_array_p *array)
{
return array->ar_len;
}
static size_t array_capacity(const struct b_array_p *array)
{
return array->ar_cap;
}
static void array_clear(struct b_array_p *array)
{
if (!array->ar_len) {
return;
}
for (size_t i = 0; i < array->ar_len; i++) {
b_object_unref(array->ar_data[i]);
}
memset(array->ar_data, 0x0, array->ar_cap * sizeof(b_object *));
array->ar_len = 0;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_array *b_array_create_with_values(b_object *const *values, size_t nr_values)
{
b_array *array = b_array_create();
if (!array) {
return NULL;
}
struct b_array_p *p = b_object_get_private(array, B_TYPE_ARRAY);
size_t real_nr_values = 0;
for (size_t i = 0; i < nr_values; i++) {
if (values[i]) {
real_nr_values++;
}
}
p->ar_len = real_nr_values;
p->ar_cap = real_nr_values;
p->ar_data = calloc(real_nr_values, sizeof(struct b_dsref *));
if (!p->ar_data) {
b_array_unref(array);
return NULL;
}
size_t index = 0;
for (size_t i = 0; i < nr_values; i++) {
p->ar_data[index++] = b_object_ref(values[i]);
}
return array;
}
b_status b_array_insert(b_array *array, b_object *value, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ARRAY, array_insert, array, value, at);
}
b_status b_array_remove(b_array *array, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ARRAY, array_remove, array, at);
}
b_status b_array_remove_front(b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_remove_front, array);
}
b_status b_array_remove_back(b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_remove_back, array);
}
b_object *b_array_pop(b_array *array, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ARRAY, array_pop, array, at);
}
b_object *b_array_pop_front(b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_pop_front, array);
}
b_object *b_array_pop_back(b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_pop_back, array);
}
b_object *b_array_at(const b_array *array, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ARRAY, array_at, array, at);
}
b_object *b_array_get(b_array *array, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ARRAY, array_get, array, at);
}
size_t b_array_size(const b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_size, array);
}
size_t b_array_capacity(const b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_capacity, array);
}
void b_array_clear(b_array *array)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ARRAY, array_clear, array);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
b_status b_array_append(b_array *array, b_object *value)
{
return b_array_insert(array, value, B_NPOS);
}
b_status b_array_prepend(b_array *array, b_object *value)
{
return b_array_insert(array, value, 0);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void array_init(b_object *obj, void *priv)
{
struct b_array_p *array = priv;
}
static void array_fini(b_object *obj, void *priv)
{
struct b_array_p *array = priv;
if (array->ar_data) {
for (size_t i = 0; i < array->ar_len; i++) {
b_object_unref(array->ar_data[i]);
}
free(array->ar_data);
array->ar_data = NULL;
}
}
static void array_to_string(const b_object *obj, b_stream *out)
{
struct b_array_p *array = b_object_get_private(obj, B_TYPE_ARRAY);
if (!array->ar_len) {
b_stream_write_string(out, "[]", NULL);
return;
}
b_stream_write_string(out, "[\n", NULL);
b_stream_push_indent(out, 1);
size_t len = array_size(array);
for (size_t i = 0; i < array->ar_len; i++) {
b_object *value = array->ar_data[i];
bool is_string = b_object_is_type(value, B_TYPE_STRING);
if (is_string) {
b_stream_write_char(out, '"');
}
b_object_to_string(value, out);
if (is_string) {
b_stream_write_char(out, '"');
}
if (i < len - 1) {
b_stream_write_string(out, ",", NULL);
}
b_stream_write_char(out, '\n');
}
b_stream_pop_indent(out);
b_stream_write_char(out, ']');
}
/*** ITERATOR FUNCTIONS *******************************************************/
static b_iterator *iterable_begin(b_object *obj)
{
b_array_iterator *it_obj = b_object_create(B_TYPE_ARRAY_ITERATOR);
struct b_array_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_ARRAY_ITERATOR);
it->_a = obj;
it->_a_p = b_object_get_private(obj, B_TYPE_ARRAY);
it->i = 0;
if (it->_a_p->ar_len > 0) {
it->value = it->_a_p->ar_data[0];
} else {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
it->value = NULL;
}
return it_obj;
}
static const b_iterator *iterable_cbegin(const b_object *obj)
{
b_array_iterator *it_obj = b_object_create(B_TYPE_ARRAY_ITERATOR);
struct b_array_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_ARRAY_ITERATOR);
it->_a = (b_array *)obj;
it->_a_p = b_object_get_private(obj, B_TYPE_ARRAY);
it->i = 0;
if (it->_a_p->ar_len > 0) {
it->value = it->_a_p->ar_data[0];
} else {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
it->value = NULL;
}
return it_obj;
}
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_array_iterator_p *it
= b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR);
struct b_array_p *array = it->_a_p;
if (it->value == NULL || it->i >= array->ar_len) {
return false;
}
it->i++;
if (it->i >= array->ar_len) {
it->value = NULL;
} else {
it->value = array->ar_data[it->i];
}
return (it->value != NULL) ? B_SUCCESS : B_ERR_NO_DATA;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_array_iterator_p *it
= b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR);
struct b_array_p *array = it->_a_p;
if (it->i >= array->ar_len) {
return B_ERR_OUT_OF_BOUNDS;
}
if (array->ar_data[it->i] != it->value) {
return B_ERR_BAD_STATE;
}
array_remove(array, it->i);
if (it->i < array->ar_len) {
it->value = array->ar_data[it->i];
} else {
it->value = NULL;
}
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_array_iterator_p *it
= b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR);
return B_ITERATOR_VALUE_PTR(it->value);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_array_iterator_p *it
= b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR);
return B_ITERATOR_VALUE_CPTR(it->value);
}
static enum b_status iterator_is_valid(const b_iterator *obj)
{
struct b_array_iterator_p *it
= b_object_get_private(obj, B_TYPE_ARRAY_ITERATOR);
struct b_array_p *array = it->_a_p;
if (it->i >= array->ar_len) {
return false;
}
if (array->ar_data[it->i] != it->value) {
return false;
}
return (it->value != NULL) ? B_SUCCESS : B_ERR_NO_DATA;
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_array DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_array)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = array_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = iterable_begin;
B_INTERFACE_ENTRY(it_cbegin) = iterable_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_array)
B_TYPE_DEFINITION_BEGIN(b_array)
B_TYPE_ID(0xe3c46da1, 0x5f37, 0x4e44, 0xb53b, 0xff5a6200191b);
B_TYPE_CLASS(b_array_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_array_p);
B_TYPE_INSTANCE_INIT(array_init);
B_TYPE_INSTANCE_FINI(array_fini);
B_TYPE_DEFINITION_END(b_array)
// ---- b_array_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_array_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_array_iterator)
B_TYPE_DEFINITION_BEGIN(b_array_iterator)
B_TYPE_ID(0xe5e9e8b8, 0x14cb, 0x4192, 0x8138, 0xf45238a2ae73);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_array_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_array_iterator_p);
B_TYPE_DEFINITION_END(b_array_iterator)
-38
View File
@@ -1,38 +0,0 @@
#include <blue/ds/bitbuffer.h>
/*** PRIVATE DATA *************************************************************/
struct b_bitbuffer_p {
int x;
};
/*** PRIVATE FUNCTIONS ********************************************************/
/*** PUBLIC FUNCTIONS *********************************************************/
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void bitbuffer_init(b_object *obj, void *priv)
{
struct b_bitbuffer_p *bitbuffer = priv;
}
static void bitbuffer_fini(b_object *obj, void *priv)
{
struct b_bitbuffer_p *bitbuffer = priv;
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_bitbuffer)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_bitbuffer)
B_TYPE_DEFINITION_BEGIN(b_bitbuffer)
B_TYPE_ID(0x628e33da, 0x3109, 0x4a5d, 0x98d5, 0xb0e4cb3ccb65);
B_TYPE_CLASS(b_bitbuffer_class);
B_TYPE_INSTANCE_PRIVATE(struct b_bitbuffer_p);
B_TYPE_INSTANCE_INIT(bitbuffer_init);
B_TYPE_INSTANCE_FINI(bitbuffer_fini);
B_TYPE_DEFINITION_END(b_bitbuffer)
-330
View File
@@ -1,330 +0,0 @@
#include <blue/core/bitop.h>
#include <blue/core/stream.h>
#include <blue/ds/bitmap.h>
#include <string.h>
#define BITS_PER_WORD (8 * sizeof(bitmap_word_t))
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define BITMAP_WORDS(nbits) DIV_ROUND_UP(nbits, BITS_PER_WORD)
/*** PRIVATE DATA *************************************************************/
typedef unsigned long bitmap_word_t;
struct b_bitmap_p {
bitmap_word_t *map_words;
size_t map_nr_words, map_nr_bits;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static void bitmap_set_bit(struct b_bitmap_p *map, size_t bit)
{
unsigned long index = bit / BITS_PER_WORD;
unsigned long offset = (BITS_PER_WORD - bit - 1) & (BITS_PER_WORD - 1);
unsigned long mask = 1ul << offset;
map->map_words[index] |= mask;
}
static void bitmap_clear_bit(struct b_bitmap_p *map, size_t bit)
{
unsigned long index = bit / BITS_PER_WORD;
unsigned long offset = bit & (BITS_PER_WORD - 1);
unsigned long mask = 1ul << offset;
map->map_words[index] &= ~mask;
}
static void bitmap_set_range(struct b_bitmap_p *map, size_t first_bit, size_t nbits)
{
}
static void bitmap_clear_range(struct b_bitmap_p *map, size_t first_bit, size_t nbits)
{
}
static void bitmap_set_all(struct b_bitmap_p *map)
{
memset(map->map_words, 0xFF, map->map_nr_words * sizeof(bitmap_word_t));
}
static void bitmap_clear_all(struct b_bitmap_p *map)
{
memset(map->map_words, 0x00, map->map_nr_words * sizeof(bitmap_word_t));
}
static bool bitmap_check_bit(const struct b_bitmap_p *map, size_t bit)
{
unsigned long index = bit / BITS_PER_WORD;
unsigned long offset = (BITS_PER_WORD - bit - 1) & (BITS_PER_WORD - 1);
unsigned long mask = 1ul << offset;
return (map->map_words[index] & mask) != 0;
}
static size_t bitmap_count_set_bits(const struct b_bitmap_p *map)
{
size_t set_bits = 0;
for (size_t i = 0; i < map->map_nr_words; i++) {
set_bits += b_popcountl(map->map_words[i]);
}
if (set_bits > map->map_nr_bits) {
set_bits = map->map_nr_bits;
}
return set_bits;
}
static size_t bitmap_count_clear_bits(const struct b_bitmap_p *map)
{
size_t clear_bits = 0;
for (size_t i = 0; i < map->map_nr_words; i++) {
clear_bits += b_popcountl(~map->map_words[i]);
}
if (clear_bits > map->map_nr_bits) {
clear_bits = map->map_nr_bits;
}
return clear_bits;
}
static size_t bitmap_highest_set_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = 0;
unsigned long i;
for (i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != 0x00) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
}
}
if (last_word == 0x00) {
return B_NPOS;
}
return bit_index + (BITS_PER_WORD - b_ctzl(last_word) - 1);
}
static size_t bitmap_highest_clear_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = ~(bitmap_word_t)0;
for (unsigned long i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != (~(unsigned long)0)) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
}
}
if (last_word == ~(unsigned long)0) {
return B_NPOS;
}
if (last_word == 0) {
return bit_index + BITS_PER_WORD - 1;
}
return bit_index + (BITS_PER_WORD - b_ctzl(~last_word)) - 1;
}
static size_t bitmap_lowest_set_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = 0;
unsigned long i;
for (i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != 0x00) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
break;
}
}
if (last_word == 0x00) {
return B_NPOS;
}
return bit_index + b_clzl(last_word);
}
static size_t bitmap_lowest_clear_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = 0;
unsigned long i;
for (i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != (~(unsigned long)0)) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
break;
}
}
if (last_word == 0) {
return bit_index;
}
if (last_word == (~(bitmap_word_t)0)) {
return B_NPOS;
}
return bit_index + b_clzl(~last_word);
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_bitmap *b_bitmap_create(size_t nr_bits)
{
b_bitmap *map = b_object_create(B_TYPE_BITMAP);
if (!map) {
return NULL;
}
struct b_bitmap_p *p = b_object_get_private(map, B_TYPE_BITMAP);
p->map_nr_bits = nr_bits;
p->map_nr_words = BITMAP_WORDS(nr_bits);
p->map_words = calloc(p->map_nr_words, sizeof(bitmap_word_t));
if (!p->map_words) {
b_bitmap_unref(map);
return NULL;
}
return map;
}
void b_bitmap_set_bit(b_bitmap *map, size_t bit)
{
B_CLASS_DISPATCH_STATIC_V(B_TYPE_BITMAP, bitmap_set_bit, map, bit);
}
void b_bitmap_clear_bit(b_bitmap *map, size_t bit)
{
B_CLASS_DISPATCH_STATIC_V(B_TYPE_BITMAP, bitmap_clear_bit, map, bit);
}
void b_bitmap_set_range(b_bitmap *map, size_t first_bit, size_t nbits)
{
B_CLASS_DISPATCH_STATIC_V(
B_TYPE_BITMAP, bitmap_set_range, map, first_bit, nbits);
}
void b_bitmap_clear_range(b_bitmap *map, size_t first_bit, size_t nbits)
{
B_CLASS_DISPATCH_STATIC_V(
B_TYPE_BITMAP, bitmap_clear_range, map, first_bit, nbits);
}
void b_bitmap_set_all(b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_V0(B_TYPE_BITMAP, bitmap_set_all, map);
}
void b_bitmap_clear_all(b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_V0(B_TYPE_BITMAP, bitmap_clear_all, map);
}
bool b_bitmap_check_bit(const b_bitmap *map, size_t bit)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BITMAP, bitmap_check_bit, map, bit);
}
size_t b_bitmap_count_set_bits(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_count_set_bits, map);
}
size_t b_bitmap_count_clear_bits(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_count_clear_bits, map);
}
size_t b_bitmap_highest_set_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_highest_set_bit, map);
}
size_t b_bitmap_highest_clear_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_highest_clear_bit, map);
}
size_t b_bitmap_lowest_set_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_lowest_set_bit, map);
}
size_t b_bitmap_lowest_clear_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_lowest_clear_bit, map);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void bitmap_init(b_object *obj, void *priv)
{
struct b_bitmap_p *map = priv;
}
static void bitmap_fini(b_object *obj, void *priv)
{
struct b_bitmap_p *map = priv;
}
static void bitmap_to_string(const b_object *obj, b_stream *out)
{
const struct b_bitmap_p *map = b_object_get_private(obj, B_TYPE_BITMAP);
unsigned char *bytes = (unsigned char *)map->map_words;
size_t nr_bytes = map->map_nr_words * sizeof(bitmap_word_t);
unsigned char c = 0;
for (size_t i = 0; i < nr_bytes - 1; i++) {
c = bytes[i];
b_stream_write_fmt(
out, NULL, "%c%c%c%c%c%c%c%c", c & 0x80 ? '1' : '0',
c & 0x40 ? '1' : '0', c & 0x20 ? '1' : '0',
c & 0x10 ? '1' : '0', c & 0x08 ? '1' : '0',
c & 0x04 ? '1' : '0', c & 0x02 ? '1' : '0',
c & 0x01 ? '1' : '0');
}
unsigned char mask = 0x80;
size_t remaining_bits = map->map_nr_bits - ((nr_bytes - 1) * 8);
c = bytes[nr_bytes - 1];
for (size_t i = 0; i < remaining_bits; i++) {
b_stream_write_fmt(out, NULL, "%c", (c & mask) ? '1' : '0');
}
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_bitmap)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = bitmap_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_bitmap)
B_TYPE_DEFINITION_BEGIN(b_bitmap)
B_TYPE_ID(0xea115cef, 0x8a63, 0x445f, 0x9474, 0xba9309d5dde8);
B_TYPE_CLASS(b_bitmap_class);
B_TYPE_INSTANCE_PRIVATE(struct b_bitmap_p);
B_TYPE_INSTANCE_INIT(bitmap_init);
B_TYPE_INSTANCE_FINI(bitmap_fini);
B_TYPE_DEFINITION_END(b_bitmap)
/*** ITERATOR FUNCTIONS *******************************************************/
-441
View File
@@ -1,441 +0,0 @@
#include <blue/core/iterator.h>
#include <blue/ds/buffer.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
struct b_buffer_p {
/* number of items in buffer */
unsigned int buf_len;
/* maximum number of items that can currently be stored in array */
unsigned int buf_cap;
/* the size of each individual item in the buffer */
unsigned int buf_itemsz;
void *buf_data;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static b_status resize_buffer(struct b_buffer_p *buffer, size_t new_capacity)
{
if (buffer->buf_cap < new_capacity) {
void *new_data = realloc(
buffer->buf_data, new_capacity * buffer->buf_itemsz);
if (!new_data) {
return B_ERR_NO_MEMORY;
}
buffer->buf_data = new_data;
} else {
void *new_data = realloc(
buffer->buf_data, new_capacity * buffer->buf_itemsz);
if (!new_data) {
return B_ERR_NO_MEMORY;
}
buffer->buf_data = new_data;
}
buffer->buf_cap = new_capacity;
if (buffer->buf_len > new_capacity) {
buffer->buf_len = new_capacity;
}
return B_SUCCESS;
}
static void *buffer_steal(struct b_buffer_p *buf)
{
void *p = buf->buf_data;
buf->buf_data = NULL;
buf->buf_len = 0;
buf->buf_cap = 0;
return p;
}
static enum b_status buffer_reserve(struct b_buffer_p *buf, size_t capacity)
{
if (buf->buf_cap >= capacity) {
return B_SUCCESS;
}
return resize_buffer(buf, capacity);
}
static enum b_status buffer_resize(struct b_buffer_p *buf, size_t length)
{
enum b_status status = resize_buffer(buf, length);
if (!B_OK(status)) {
return status;
}
buf->buf_len = length;
return B_SUCCESS;
}
static enum b_status buffer_insert(
struct b_buffer_p *buffer, const void *p, size_t count, size_t at)
{
if (at == B_NPOS) {
at = buffer->buf_len;
}
if (at > buffer->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
b_status status = B_SUCCESS;
if (buffer->buf_len + count > buffer->buf_cap) {
status = resize_buffer(buffer, buffer->buf_cap + count);
if (status != B_SUCCESS) {
return status;
}
}
unsigned char *src
= (unsigned char *)buffer->buf_data + (at * buffer->buf_itemsz);
unsigned char *dest = src + (count * buffer->buf_itemsz);
size_t move_len = (buffer->buf_len - at) * buffer->buf_itemsz;
memmove(dest, src, move_len);
memcpy(src, p, count * buffer->buf_itemsz);
buffer->buf_len += count;
return B_SUCCESS;
}
static enum b_status buffer_remove(struct b_buffer_p *buffer, size_t at, size_t count)
{
if (at >= buffer->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
if (at + count >= buffer->buf_len) {
count = buffer->buf_len - at;
}
unsigned char *dest = buffer->buf_data + (at * buffer->buf_itemsz);
unsigned char *src = dest + (count * buffer->buf_itemsz);
size_t move_len = (buffer->buf_len - at - count) * buffer->buf_itemsz;
memmove(dest, src, move_len);
buffer->buf_len -= count;
return B_SUCCESS;
}
static void *buffer_ptr(const struct b_buffer_p *buffer)
{
return buffer->buf_data;
}
static void *buffer_get(const struct b_buffer_p *buffer, size_t at)
{
if (at >= buffer->buf_len) {
return NULL;
}
return (unsigned char *)buffer->buf_data + (at * buffer->buf_itemsz);
}
static size_t buffer_size(const struct b_buffer_p *buffer)
{
return buffer->buf_len;
}
static size_t buffer_capacity(const struct b_buffer_p *buffer)
{
return buffer->buf_cap;
}
static enum b_status buffer_clear(struct b_buffer_p *buffer)
{
buffer->buf_len = 0;
return B_SUCCESS;
}
static enum b_status buffer_push_back(
struct b_buffer_p *buf, size_t count, void **p)
{
enum b_status status = B_SUCCESS;
if (buf->buf_len + count > buf->buf_cap) {
status = resize_buffer(buf, buf->buf_len + count);
}
if (!B_OK(status)) {
return status;
}
buf->buf_len += count;
*p = buffer_get(buf, buf->buf_len - count);
return B_SUCCESS;
}
static enum b_status buffer_push_front(
struct b_buffer_p *buf, size_t count, void **p)
{
enum b_status status = B_SUCCESS;
if (buf->buf_len + count > buf->buf_cap) {
status = resize_buffer(buf, buf->buf_len + count);
}
if (!B_OK(status)) {
return status;
}
void *src = buf->buf_data;
void *dest = b_buffer_get(buf->buf_data, count);
size_t len = count * buf->buf_itemsz;
memmove(dest, src, len);
buf->buf_len += count;
*p = buffer_get(buf, 0);
return B_SUCCESS;
}
static enum b_status buffer_pop_back(struct b_buffer_p *buf, size_t count)
{
if (count > buf->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
buf->buf_len -= count;
return B_SUCCESS;
}
static enum b_status buffer_pop_front(struct b_buffer_p *buf, size_t count)
{
if (count > buf->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
void *src = b_buffer_get(buf->buf_data, count);
void *dest = buf->buf_data;
size_t len = (buf->buf_len - count) * buf->buf_itemsz;
memmove(dest, src, len);
buf->buf_len -= count;
return B_SUCCESS;
}
static size_t buffer_get_size(const struct b_buffer_p *buf)
{
return buf->buf_len;
}
static size_t buffer_get_item_size(const struct b_buffer_p *buf)
{
return buf->buf_itemsz;
}
static size_t buffer_get_capacity(const struct b_buffer_p *buf)
{
return buf->buf_cap;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_buffer *b_buffer_create(size_t item_sz)
{
b_buffer *buffer = b_object_create(B_TYPE_BUFFER);
if (!buffer) {
return NULL;
}
struct b_buffer_p *p = b_object_get_private(buffer, B_TYPE_BUFFER);
p->buf_itemsz = item_sz;
return buffer;
}
b_buffer *b_buffer_create_from_bytes(const void *buf, size_t len)
{
b_buffer *buffer = b_object_create(B_TYPE_BUFFER);
if (!buffer) {
return NULL;
}
struct b_buffer_p *p = b_object_get_private(buffer, B_TYPE_BUFFER);
p->buf_len = len;
p->buf_cap = len;
p->buf_itemsz = 1;
p->buf_data = calloc(len, 1);
if (!p->buf_data) {
b_buffer_unref(buffer);
return NULL;
}
memcpy(p->buf_data, buf, len);
return buffer;
}
b_buffer *b_buffer_create_from_array(const void *buf, size_t item_sz, size_t len)
{
b_buffer *buffer = b_object_create(B_TYPE_BUFFER);
if (!buffer) {
return NULL;
}
struct b_buffer_p *p = b_object_get_private(buffer, B_TYPE_BUFFER);
p->buf_len = len;
p->buf_cap = len;
p->buf_itemsz = item_sz;
p->buf_data = calloc(len, item_sz);
if (!p->buf_data) {
b_buffer_unref(buffer);
return NULL;
}
memcpy(p->buf_data, buf, len * item_sz);
return buffer;
}
void *b_buffer_steal(b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_steal, buf);
}
enum b_status b_buffer_reserve(b_buffer *buf, size_t capacity)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_reserve, buf, capacity);
}
enum b_status b_buffer_resize(b_buffer *buf, size_t length)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_resize, buf, length);
}
enum b_status b_buffer_insert(
b_buffer *buffer, const void *p, size_t count, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_insert, buffer, p, count, at);
}
enum b_status b_buffer_remove(b_buffer *buffer, size_t at, size_t count)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_remove, buffer, at, count);
}
void *b_buffer_ptr(const b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_ptr, buffer);
}
void *b_buffer_get(const b_buffer *buffer, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_get, buffer, at);
}
size_t b_buffer_size(const b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_size, buffer);
}
size_t b_buffer_capacity(const b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_capacity, buffer);
}
enum b_status b_buffer_clear(b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_clear, buffer);
}
enum b_status b_buffer_push_back(b_buffer *buf, size_t count, void **p)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_push_back, buf, count, p);
}
enum b_status b_buffer_push_front(b_buffer *buf, size_t count, void **p)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_push_front, buf, count, p);
}
enum b_status b_buffer_pop_back(b_buffer *buf, size_t count)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_pop_back, buf, count);
}
enum b_status b_buffer_pop_front(b_buffer *buf, size_t count)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_pop_front, buf, count);
}
size_t b_buffer_get_size(const b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_get_size, buf);
}
size_t b_buffer_get_item_size(const b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_get_item_size, buf);
}
size_t b_buffer_get_capacity(const b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_get_capacity, buf);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
enum b_status b_buffer_append(b_buffer *buffer, const void *p, size_t count)
{
return b_buffer_insert(buffer, p, count, B_NPOS);
}
enum b_status b_buffer_prepend(b_buffer *buffer, const void *p, size_t count)
{
return b_buffer_insert(buffer, p, count, 0);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
void buffer_init(b_object *obj, void *priv)
{
struct b_buffer_p *buffer = priv;
}
void buffer_fini(b_object *obj, void *priv)
{
struct b_buffer_p *buffer = priv;
if (buffer->buf_data) {
free(buffer->buf_data);
buffer->buf_data = NULL;
}
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_buffer)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_buffer)
B_TYPE_DEFINITION_BEGIN(b_buffer)
B_TYPE_ID(0x323e6858, 0x7a43, 0x4484, 0xa6fb, 0xe3d1e47ae637);
B_TYPE_CLASS(b_buffer_class);
B_TYPE_INSTANCE_PRIVATE(struct b_buffer_p);
B_TYPE_INSTANCE_INIT(buffer_init);
B_TYPE_INSTANCE_FINI(buffer_fini);
B_TYPE_DEFINITION_END(b_buffer)
-723
View File
@@ -1,723 +0,0 @@
#include <blue/core/status.h>
#include <blue/core/stream.h>
#include <blue/ds/dict.h>
#include <blue/ds/string.h>
#include <stdbool.h>
#include <stdlib.h>
#define HASH_OFFSET_BASIS 0xcbf29ce484222325
#define HASH_PRIME 0x100000001b3
/*** PRIVATE DATA *************************************************************/
struct b_dict_bucket_item {
b_queue_entry bi_entry;
b_string *bi_str;
b_object *bi_value;
};
struct b_dict_bucket {
b_btree_node bk_node;
uint64_t bk_hash;
b_queue bk_items;
};
struct b_dict_p {
b_btree d_buckets;
};
struct b_dict_iterator_p {
size_t i;
b_dict_item item;
b_dict *_d;
struct b_dict_p *_d_p;
b_btree_node *_cbn;
b_queue_entry *_cqe;
};
/*** MISC FUNCTIONS ***********************************************************/
static B_BTREE_DEFINE_SIMPLE_GET(
struct b_dict_bucket, uint64_t, bk_node, bk_hash, get_bucket);
static B_BTREE_DEFINE_SIMPLE_INSERT(
struct b_dict_bucket, bk_node, bk_hash, put_bucket);
uint64_t b_cstr_hash(const char *s)
{
uint64_t hash = HASH_OFFSET_BASIS;
for (size_t i = 0; s[i]; i++) {
hash *= HASH_PRIME;
hash ^= s[i];
}
return hash;
}
/*** PRIVATE FUNCTIONS ********************************************************/
static struct b_dict_bucket *create_bucket(void)
{
struct b_dict_bucket *bucket = malloc(sizeof *bucket);
if (!bucket) {
return NULL;
}
memset(bucket, 0x0, sizeof *bucket);
return bucket;
}
static struct b_dict_bucket_item *create_bucket_item(void)
{
struct b_dict_bucket_item *item = malloc(sizeof *item);
if (!item) {
return NULL;
}
memset(item, 0x0, sizeof *item);
return item;
}
static b_status dict_put(struct b_dict_p *dict, const char *key, b_object *value)
{
uint64_t hash = b_cstr_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
bucket->bk_hash = hash;
put_bucket(&dict->d_buckets, bucket);
}
struct b_dict_bucket_item *item = create_bucket_item();
if (!item) {
return B_ERR_NO_MEMORY;
}
item->bi_str = b_string_create_from_cstr(key);
item->bi_value = b_object_ref(value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
return B_SUCCESS;
}
static b_status dict_put_sk(
struct b_dict_p *dict, const b_string *key, b_object *value)
{
uint64_t hash = b_string_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
bucket->bk_hash = hash;
put_bucket(&dict->d_buckets, bucket);
}
struct b_dict_bucket_item *item = create_bucket_item();
if (!item) {
return B_ERR_NO_MEMORY;
}
item->bi_str = b_string_duplicate(key);
item->bi_value = b_object_ref(value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
return B_SUCCESS;
}
static b_object *dict_at(const struct b_dict_p *dict, const char *key)
{
uint64_t hash = b_cstr_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
return NULL;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item
= b_unbox(struct b_dict_bucket_item, entry, bi_entry);
if (!strcmp(b_string_ptr(item->bi_str), key)) {
return item->bi_value;
}
entry = b_queue_next(entry);
}
return NULL;
}
static b_object *dict_at_sk(const struct b_dict_p *dict, const b_string *key)
{
uint64_t hash = b_string_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
return NULL;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item
= b_unbox(struct b_dict_bucket_item, entry, bi_entry);
if (b_string_compare(item->bi_str, key)) {
return item->bi_value;
}
entry = b_queue_next(entry);
}
return NULL;
}
static b_object *dict_get(struct b_dict_p *dict, const char *key)
{
b_object *value = dict_at(dict, key);
if (value) {
b_object_ref(value);
}
return value;
}
static b_object *dict_get_sk(struct b_dict_p *dict, const b_string *key)
{
b_object *value = dict_at_sk(dict, key);
if (value) {
b_object_ref(value);
}
return value;
}
static bool dict_has_key(const struct b_dict_p *dict, const char *key)
{
return dict_at(dict, key) != NULL;
}
static bool dict_has_skey(const struct b_dict_p *dict, const b_string *key)
{
return dict_at_sk(dict, key) != NULL;
}
static size_t dict_get_size(const struct b_dict_p *dict)
{
size_t count = 0;
#if 0
b_btree_iterator it1;
b_queue_iterator it2;
b_btree_foreach (&it1, &dict->d_buckets) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, it1.node, bk_node);
b_queue_foreach (&it2, &bucket->bk_items) {
count++;
}
}
#endif
return count;
}
static bool dict_is_empty(const struct b_dict_p *dict)
{
b_btree_node *first_node = b_btree_first(&dict->d_buckets);
struct b_dict_bucket *first_bucket
= b_unbox(struct b_dict_bucket, first_node, bk_node);
if (!first_bucket) {
return true;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_dict_bucket_item *first_item
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
if (!first_item) {
return true;
}
return false;
}
static bool get_next_node(
struct b_btree_node *cur_node, struct b_queue_entry *cur_entry,
struct b_btree_node **out_next_node, struct b_queue_entry **out_next_entry)
{
struct b_dict_bucket *cur_bucket
= b_unbox(struct b_dict_bucket, cur_node, bk_node);
if (!cur_bucket) {
return false;
}
struct b_dict_bucket_item *cur_item
= b_unbox(struct b_dict_bucket_item, cur_entry, bi_entry);
if (!cur_item) {
return false;
}
struct b_btree_node *next_node = cur_node;
struct b_queue_entry *next_entry = b_queue_next(cur_entry);
if (!next_entry) {
next_node = b_btree_next(cur_node);
if (!next_node) {
return false;
}
struct b_dict_bucket *next_bucket
= b_unbox(struct b_dict_bucket, next_node, bk_node);
if (!next_bucket) {
return false;
}
next_entry = b_queue_first(&next_bucket->bk_items);
if (!next_entry) {
return false;
}
}
struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
if (!next_item) {
return false;
}
*out_next_node = next_node;
*out_next_entry = next_entry;
return true;
}
static b_status delete_item(
struct b_dict_p *dict, struct b_dict_bucket *bucket,
struct b_dict_bucket_item *item)
{
b_queue_delete(&bucket->bk_items, &item->bi_entry);
free(item);
if (b_queue_empty(&bucket->bk_items)) {
b_btree_delete(&dict->d_buckets, &bucket->bk_node);
free(bucket);
}
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
#if 0
b_dict *b_dict_create_with_items(const b_dict_item *items)
{
b_dict *dict = b_dict_create();
if (!dict) {
return NULL;
}
struct b_dict_p *p = b_object_get_private(dict, B_TYPE_DICT);
for (size_t i = 0; items[i].key; i++) {
dict_put(p, items[i].key, items[i].value);
}
return dict;
}
#endif
b_status b_dict_put(b_dict *dict, const char *key, b_object *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put, dict, key, value);
}
b_status b_dict_put_sk(b_dict *dict, const b_string *key, b_object *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put_sk, dict, key, value);
}
b_object *b_dict_at(const b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_at, dict, key);
}
b_object *b_dict_at_sk(const b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_at_sk, dict, key);
}
b_object *b_dict_get(b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_get, dict, key);
}
b_object *b_dict_get_sk(b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_get_sk, dict, key);
}
bool b_dict_has_key(const b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_has_key, dict, key);
}
bool b_dict_has_skey(const b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_has_skey, dict, key);
}
size_t b_dict_get_size(const b_dict *dict)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_DICT, dict_get_size, dict);
}
bool b_dict_is_empty(const b_dict *dict)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_DICT, dict_is_empty, dict);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void dict_init(b_object *obj, void *priv)
{
struct b_dict_p *dict = priv;
}
static void dict_fini(b_object *obj, void *priv)
{
struct b_dict_p *dict = priv;
struct b_btree_node *node = b_btree_first(&dict->d_buckets);
while (node) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, node, bk_node);
struct b_btree_node *next_node = b_btree_next(node);
b_btree_delete(&dict->d_buckets, node);
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item = b_unbox(
struct b_dict_bucket_item, entry, bi_entry);
struct b_queue_entry *next_entry = b_queue_next(entry);
b_queue_delete(&bucket->bk_items, entry);
free(item->bi_str);
b_object_unref(item->bi_value);
free(item);
entry = next_entry;
}
free(bucket);
node = next_node;
}
}
static void dict_to_string(const b_object *obj, b_stream *out)
{
struct b_dict_p *dict = b_object_get_private(obj, B_TYPE_DICT);
if (dict_is_empty(dict)) {
b_stream_write_string(out, "{}", NULL);
return;
}
b_stream_write_string(out, "{\n", NULL);
b_stream_push_indent(out, 1);
size_t len = dict_get_size(dict);
size_t i = 0;
struct b_btree_node *node = b_btree_first(&dict->d_buckets);
while (node) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, node, bk_node);
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item = b_unbox(
struct b_dict_bucket_item, entry, bi_entry);
b_object_to_string(item->bi_str, out);
b_stream_write_string(out, ": ", NULL);
bool is_string
= b_object_is_type(item->bi_value, B_TYPE_STRING);
if (is_string) {
b_stream_write_char(out, '"');
}
b_object_to_string(item->bi_value, out);
if (is_string) {
b_stream_write_char(out, '"');
}
if (i < len - 1) {
b_stream_write_string(out, ",", NULL);
}
b_stream_write_char(out, '\n');
entry = b_queue_next(entry);
i++;
}
node = b_btree_next(node);
}
b_stream_pop_indent(out);
b_stream_write_char(out, '}');
}
/*** ITERATOR FUNCTIONS *******************************************************/
static b_iterator *iterable_begin(b_dict *dict)
{
b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR);
if (!it_obj) {
return NULL;
}
struct b_dict_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR);
it->i = 0;
it->_d = dict;
it->_d_p = b_object_get_private(dict, B_TYPE_DICT);
if (dict_is_empty(it->_d_p)) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets);
struct b_dict_bucket *first_bucket
= b_unbox(struct b_dict_bucket, first_node, bk_node);
if (!first_bucket) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_dict_bucket_item *first_item
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
if (!first_item) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
it->item.key = first_item->bi_str;
it->item.value = first_item->bi_value;
it->_d = dict;
it->_cbn = first_node;
it->_cqe = first_entry;
return it_obj;
}
static const b_iterator *iterable_cbegin(const b_dict *dict)
{
b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR);
if (!it_obj) {
return NULL;
}
struct b_dict_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR);
it->i = 0;
it->_d = (b_dict *)dict;
it->_d_p = b_object_get_private(dict, B_TYPE_DICT);
if (dict_is_empty(it->_d_p)) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets);
struct b_dict_bucket *first_bucket
= b_unbox(struct b_dict_bucket, first_node, bk_node);
if (!first_bucket) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_dict_bucket_item *first_item
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
if (!first_item) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
it->item.key = first_item->bi_str;
it->item.value = first_item->bi_value;
it->_cbn = first_node;
it->_cqe = first_entry;
return it_obj;
}
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
it->item.key = NULL;
it->item.value = NULL;
return B_ERR_NO_DATA;
}
struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
if (!next_item) {
it->item.key = NULL;
it->item.value = NULL;
return B_ERR_NO_DATA;
}
it->i++;
it->item.key = next_item->bi_str;
it->item.value = next_item->bi_value;
it->_cbn = next_node;
it->_cqe = next_entry;
return B_SUCCESS;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
if ((it->item.key || it->item.value) && !(it->_cbn && it->_cqe)) {
return B_ERR_BAD_STATE;
}
if (!it->item.key || !it->_cqe) {
return B_ERR_NO_DATA;
}
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
it->item.key = NULL;
it->item.value = NULL;
return B_ERR_NO_DATA;
}
struct b_dict_bucket *cur_bucket
= b_unbox(struct b_dict_bucket, it->_cbn, bk_node);
struct b_dict_bucket_item *cur_item
= b_unbox(struct b_dict_bucket_item, it->_cqe, bi_entry);
struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
b_status status = delete_item(it->_d_p, cur_bucket, cur_item);
if (B_ERR(status)) {
return status;
}
if (next_item) {
it->item.key = next_item->bi_str;
it->item.value = next_item->bi_value;
it->_cbn = next_node;
it->_cqe = next_entry;
} else {
it->item.key = NULL;
it->item.value = NULL;
it->_cbn = NULL;
it->_cqe = NULL;
}
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
return B_ITERATOR_VALUE_PTR(&it->item);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
return B_ITERATOR_VALUE_CPTR(&it->item);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_dict DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = dict_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = iterable_begin;
B_INTERFACE_ENTRY(it_cbegin) = iterable_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_dict)
B_TYPE_DEFINITION_BEGIN(b_dict)
B_TYPE_ID(0xd2af61d9, 0xd0be, 0x4960, 0xbe3f, 0x509749814c10);
B_TYPE_CLASS(b_dict_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_dict_p);
B_TYPE_INSTANCE_INIT(dict_init);
B_TYPE_INSTANCE_FINI(dict_fini);
B_TYPE_DEFINITION_END(b_dict)
// ---- b_dict_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_dict_iterator)
B_TYPE_DEFINITION_BEGIN(b_dict_iterator)
B_TYPE_ID(0x9ea96701, 0x1713, 0x4a3e, 0xbf63, 0xdc856b456f3b);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_dict_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_dict_iterator_p);
B_TYPE_DEFINITION_END(b_dict_iterator)
-598
View File
@@ -1,598 +0,0 @@
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <blue/ds/hashmap.h>
#include <blue/ds/string.h>
#include <stdbool.h>
#include <stdlib.h>
#define HASH_OFFSET_BASIS 0xcbf29ce484222325
#define HASH_PRIME 0x100000001b3
/*** PRIVATE DATA *************************************************************/
struct b_hashmap_bucket_item {
struct b_queue_entry bi_entry;
struct b_hashmap_key bi_key;
struct b_hashmap_value bi_value;
};
struct b_hashmap_bucket {
struct b_btree_node bk_node;
uint64_t bk_hash;
struct b_queue bk_items;
};
struct b_hashmap_p {
size_t h_count;
struct b_btree h_buckets;
b_hashmap_key_destructor h_key_dtor;
b_hashmap_value_destructor h_value_dtor;
};
struct b_hashmap_iterator_p {
size_t i;
b_hashmap_item item;
b_hashmap *_h;
struct b_hashmap_p *_h_p;
b_btree_node *_cbn;
b_queue_entry *_cqe;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static B_BTREE_DEFINE_SIMPLE_GET(
struct b_hashmap_bucket, uint64_t, bk_node, bk_hash, get_bucket);
static B_BTREE_DEFINE_SIMPLE_INSERT(
struct b_hashmap_bucket, bk_node, bk_hash, put_bucket);
static uint64_t hash_data(const void *p, size_t size)
{
const unsigned char *s = p;
uint64_t hash = HASH_OFFSET_BASIS;
for (size_t i = 0; s[i]; i++) {
hash *= HASH_PRIME;
hash ^= s[i];
}
return hash;
}
static uint64_t hash_key(const struct b_hashmap_key *key)
{
if (key->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
return hash_data(&key->key_data, sizeof key->key_data);
} else {
return hash_data(key->key_data, key->key_size);
}
}
static bool compare_key(
const struct b_hashmap_key *a, const struct b_hashmap_key *b)
{
const void *a_data = NULL, *b_data = NULL;
size_t a_len = 0, b_len = 0;
if (a->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
a_data = &a->key_data;
a_len = sizeof a->key_data;
} else {
a_data = a->key_data;
a_len = a->key_size;
}
if (b->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
b_data = &b->key_data;
b_len = sizeof b->key_data;
} else {
b_data = b->key_data;
b_len = b->key_size;
}
if (a_len != b_len) {
return false;
}
size_t cmp_len = a_len;
return memcmp(a_data, b_data, cmp_len) == 0;
}
static bool get_next_node(
struct b_btree_node *cur_node, struct b_queue_entry *cur_entry,
struct b_btree_node **out_next_node, struct b_queue_entry **out_next_entry)
{
struct b_hashmap_bucket *cur_bucket
= b_unbox(struct b_hashmap_bucket, cur_node, bk_node);
if (!cur_bucket) {
return false;
}
struct b_hashmap_bucket_item *cur_item
= b_unbox(struct b_hashmap_bucket_item, cur_entry, bi_entry);
if (!cur_item) {
return false;
}
struct b_btree_node *next_node = cur_node;
struct b_queue_entry *next_entry = b_queue_next(cur_entry);
if (!next_entry) {
next_node = b_btree_next(cur_node);
if (!next_node) {
return false;
}
struct b_hashmap_bucket *next_bucket
= b_unbox(struct b_hashmap_bucket, next_node, bk_node);
if (!next_bucket) {
return false;
}
next_entry = b_queue_first(&next_bucket->bk_items);
if (!next_entry) {
return false;
}
}
struct b_hashmap_bucket_item *next_item
= b_unbox(struct b_hashmap_bucket_item, next_entry, bi_entry);
if (!next_item) {
return false;
}
*out_next_node = next_node;
*out_next_entry = next_entry;
return true;
}
static struct b_hashmap_bucket *create_bucket(void)
{
struct b_hashmap_bucket *bucket = malloc(sizeof *bucket);
if (!bucket) {
return NULL;
}
memset(bucket, 0x0, sizeof *bucket);
return bucket;
}
static struct b_hashmap_bucket_item *create_bucket_item(void)
{
struct b_hashmap_bucket_item *item = malloc(sizeof *item);
if (!item) {
return NULL;
}
memset(item, 0x0, sizeof *item);
return item;
}
static b_status hashmap_put(
struct b_hashmap_p *hashmap, const b_hashmap_key *key,
const b_hashmap_value *value)
{
uint64_t hash = hash_key(key);
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
if (!bucket) {
bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
bucket->bk_hash = hash;
put_bucket(&hashmap->h_buckets, bucket);
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item
= b_unbox(struct b_hashmap_bucket_item, entry, bi_entry);
if (compare_key(&item->bi_key, key)) {
memcpy(&item->bi_value, value, sizeof *value);
return B_SUCCESS;
}
entry = b_queue_next(entry);
}
struct b_hashmap_bucket_item *item = create_bucket_item();
if (!item) {
return B_ERR_NO_MEMORY;
}
memcpy(&item->bi_key, key, sizeof *key);
memcpy(&item->bi_value, value, sizeof *value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
hashmap->h_count++;
return B_SUCCESS;
}
static const struct b_hashmap_value *hashmap_get(
const struct b_hashmap_p *hashmap, const struct b_hashmap_key *key)
{
uint64_t hash = hash_key(key);
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
if (!bucket) {
return NULL;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item
= b_unbox(struct b_hashmap_bucket_item, entry, bi_entry);
if (compare_key(&item->bi_key, key)) {
return &item->bi_value;
}
entry = b_queue_next(entry);
}
return NULL;
}
static bool hashmap_has_key(
const struct b_hashmap_p *hashmap, const b_hashmap_key *key)
{
uint64_t hash = hash_key(key);
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
if (!bucket) {
return false;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item
= b_unbox(struct b_hashmap_bucket_item, entry, bi_entry);
if (compare_key(&item->bi_key, key)) {
return true;
}
entry = b_queue_next(entry);
}
return false;
}
static size_t hashmap_get_size(const struct b_hashmap_p *hashmap)
{
return hashmap->h_count;
}
static bool hashmap_is_empty(const struct b_hashmap_p *hashmap)
{
b_btree_node *first_node = b_btree_first(&hashmap->h_buckets);
struct b_hashmap_bucket *first_bucket
= b_unbox(struct b_hashmap_bucket, first_node, bk_node);
if (!first_bucket) {
return true;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_hashmap_bucket_item *first_item
= b_unbox(struct b_hashmap_bucket_item, first_entry, bi_entry);
if (!first_item) {
return true;
}
return false;
}
static b_status delete_item(
struct b_hashmap_p *hashmap, struct b_hashmap_bucket *bucket,
struct b_hashmap_bucket_item *item)
{
b_queue_delete(&bucket->bk_items, &item->bi_entry);
if (hashmap->h_key_dtor) {
hashmap->h_key_dtor((void *)item->bi_key.key_data);
}
if (hashmap->h_value_dtor) {
hashmap->h_value_dtor((void *)item->bi_value.value_data);
}
free(item);
if (b_queue_empty(&bucket->bk_items)) {
b_btree_delete(&hashmap->h_buckets, &bucket->bk_node);
free(bucket);
}
hashmap->h_count--;
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_hashmap *b_hashmap_create(
b_hashmap_key_destructor key_dtor, b_hashmap_value_destructor value_dtor)
{
b_hashmap *hashmap = b_object_create(B_TYPE_HASHMAP);
if (!hashmap) {
return NULL;
}
return hashmap;
}
b_hashmap *b_hashmap_create_with_items(const b_hashmap_item *items)
{
b_hashmap *hashmap = b_hashmap_create(NULL, NULL);
if (!hashmap) {
return NULL;
}
struct b_hashmap_p *p = b_object_get_private(hashmap, B_TYPE_HASHMAP);
for (size_t i = 0; items[i].key.key_data && items[i].key.key_size; i++) {
hashmap_put(p, &items[i].key, &items[i].value);
}
return hashmap;
}
b_status b_hashmap_put(
b_hashmap *hashmap, const b_hashmap_key *key, const b_hashmap_value *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_HASHMAP, hashmap_put, hashmap, key, value);
}
const struct b_hashmap_value *b_hashmap_get(
const b_hashmap *hashmap, const struct b_hashmap_key *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_HASHMAP, hashmap_get, hashmap, key);
}
bool b_hashmap_has_key(const b_hashmap *hashmap, const b_hashmap_key *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_HASHMAP, hashmap_has_key, hashmap, key);
}
size_t b_hashmap_get_size(const b_hashmap *hashmap)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_HASHMAP, hashmap_get_size, hashmap);
}
bool b_hashmap_is_empty(const b_hashmap *hashmap)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_HASHMAP, hashmap_is_empty, hashmap);
}
b_iterator *b_hashmap_begin(b_hashmap *hashmap)
{
b_hashmap_iterator *it_obj = b_object_create(B_TYPE_HASHMAP_ITERATOR);
struct b_hashmap_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_HASHMAP_ITERATOR);
it->_h = hashmap;
it->_h_p = b_object_get_private(hashmap, B_TYPE_HASHMAP);
it->i = 0;
if (b_hashmap_is_empty(hashmap)) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
struct b_btree_node *first_node = b_btree_first(&it->_h_p->h_buckets);
struct b_hashmap_bucket *first_bucket
= b_unbox(struct b_hashmap_bucket, first_node, bk_node);
if (!first_bucket) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
struct b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_hashmap_bucket_item *first_item
= b_unbox(struct b_hashmap_bucket_item, first_entry, bi_entry);
if (!first_item) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
memcpy(&it->item.key, &first_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &first_item->bi_value, sizeof it->item.value);
it->_cbn = first_node;
it->_cqe = first_entry;
return it_obj;
}
const b_iterator *b_hashmap_cbegin(const b_hashmap *hashmap)
{
return b_hashmap_begin((b_hashmap *)hashmap);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void hashmap_init(b_object *obj, void *priv)
{
struct b_hashmap_p *map = priv;
}
static void hashmap_fini(b_object *obj, void *priv)
{
struct b_hashmap_p *map = priv;
struct b_btree_node *node = b_btree_first(&map->h_buckets);
while (node) {
struct b_hashmap_bucket *b
= b_unbox(struct b_hashmap_bucket, node, bk_node);
struct b_btree_node *next_node = b_btree_next(node);
b_btree_delete(&map->h_buckets, node);
struct b_queue_entry *entry = b_queue_first(&b->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item = b_unbox(
struct b_hashmap_bucket_item, entry, bi_entry);
struct b_queue_entry *next_entry = b_queue_next(entry);
b_queue_delete(&b->bk_items, entry);
if (map->h_key_dtor) {
map->h_key_dtor((void *)item->bi_key.key_data);
}
if (map->h_value_dtor) {
map->h_value_dtor((void *)item->bi_value.value_data);
}
free(item);
entry = next_entry;
}
free(b);
node = next_node;
}
}
/*** ITERATOR FUNCTIONS *******************************************************/
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
memset(&it->item, 0x0, sizeof it->item);
return B_ERR_NO_DATA;
}
struct b_hashmap_bucket_item *next_item
= b_unbox(struct b_hashmap_bucket_item, next_entry, bi_entry);
if (!next_item) {
memset(&it->item, 0x0, sizeof it->item);
return B_ERR_NO_DATA;
}
it->i++;
memcpy(&it->item.key, &next_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &next_item->bi_value, sizeof it->item.value);
it->_cbn = next_node;
it->_cqe = next_entry;
return B_SUCCESS;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
if ((it->item.key.key_data || it->item.value.value_data)
&& !(it->_cbn && it->_cqe)) {
return B_ERR_BAD_STATE;
}
if (!it->item.key.key_data || !it->_cqe) {
return B_ERR_NO_DATA;
}
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
memset(&it->item, 0x0, sizeof it->item);
return B_ERR_NO_DATA;
}
struct b_hashmap_bucket *cur_bucket
= b_unbox(struct b_hashmap_bucket, it->_cbn, bk_node);
struct b_hashmap_bucket_item *cur_item
= b_unbox(struct b_hashmap_bucket_item, it->_cqe, bi_entry);
struct b_hashmap_bucket_item *next_item
= b_unbox(struct b_hashmap_bucket_item, next_entry, bi_entry);
b_status status = delete_item(it->_h_p, cur_bucket, cur_item);
if (B_ERR(status)) {
return status;
}
if (next_item) {
memcpy(&it->item.key, &next_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &next_item->bi_value,
sizeof it->item.value);
it->_cbn = next_node;
it->_cqe = next_entry;
} else {
memset(&it->item, 0x0, sizeof it->item);
it->_cbn = NULL;
it->_cqe = NULL;
}
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
return B_ITERATOR_VALUE_PTR(&it->item);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
const struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
return B_ITERATOR_VALUE_CPTR(&it->item);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_hashmap DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_hashmap)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = b_hashmap_begin;
B_INTERFACE_ENTRY(it_cbegin) = b_hashmap_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_hashmap)
B_TYPE_DEFINITION_BEGIN(b_hashmap)
B_TYPE_ID(0x7bf5bcd1, 0x1ff3, 0x4e43, 0xbed8, 0x7c74f28348bf);
B_TYPE_CLASS(b_hashmap_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_hashmap_p);
B_TYPE_INSTANCE_INIT(hashmap_init);
B_TYPE_INSTANCE_FINI(hashmap_fini);
B_TYPE_DEFINITION_END(b_hashmap)
// ---- b_hashmap_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_hashmap_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_hashmap_iterator)
B_TYPE_DEFINITION_BEGIN(b_hashmap_iterator)
B_TYPE_ID(0xd9658456, 0xdd80, 0x419a, 0xb23a, 0xb513013e6431);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_hashmap_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_hashmap_iterator_p);
B_TYPE_DEFINITION_END(b_hashmap_iterator)
View File
-218
View File
@@ -1,218 +0,0 @@
/**
* A heterogeneous array of objects. b_array only stores references
* to the objects that it contains, not the object data itself.
*
* b_array stores pointers to objects in a single contiguous array,
* but this is an implementation detail that may change in the future.
* Users of b_array should not rely on this being the case.
*/
#ifndef BLUE_DS_ARRAY_H_
#define BLUE_DS_ARRAY_H_
#include <blue/core/iterator.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
B_DECLS_BEGIN;
#define B_TYPE_ARRAY (b_array_get_type())
#define B_TYPE_ARRAY_ITERATOR (b_array_iterator_get_type())
struct b_array_p;
B_DECLARE_TYPE(b_array);
B_DECLARE_TYPE(b_array_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_array)
B_TYPE_CLASS_DECLARATION_END(b_array)
B_TYPE_CLASS_DECLARATION_BEGIN(b_array_iterator)
B_TYPE_CLASS_DECLARATION_END(b_array_iterator)
BLUE_API b_type b_array_get_type(void);
BLUE_API b_type b_array_iterator_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_array, B_TYPE_ARRAY);
/**
* Creates an b_array initialised with the contents of the provided
* b_object pointer array. The b_array will take a reference to each
* object specified in `values`, and will increment the reference count.
* The order of objects in the new b_array will be the same as the order
* of objects in `values`. Any NULL pointers in the `values` array will
* be ignored, and will not result in gaps in the created b_array.
* However, `nr_values` should be large enough to cover the final
* non-NULL pointer in `values`, including any NULL pointers in-between.
*
* @param values The list of object pointers which should make up the
* contents of the new b_array.
* @param nr_values The size of the `values` array.
* @return A pointer to the new b_array, or NULL if an error occurred.
*/
BLUE_API b_array *b_array_create_with_values(
b_object *const *values, size_t nr_values);
/**
* Remove all object references from an b_array, resetting the size of the array to zero.
* The reference counts of all objects in the array will be decremented.
*
* @param array The b_array to clear.
*/
BLUE_API void b_array_clear(b_array *array);
/**
* Inserts an object at the end of an b_array. The reference count of
* the object will be incremented.
*
* @param array The b_array to append the object to.
* @param value The object to append.
* @return B_SUCCESS if the object was appended successfully, or an
* error code if an error occurred.
*/
BLUE_API b_status b_array_append(b_array *array, b_object *value);
/**
* Inserts an object at the beginning of an b_array. The reference count
* of the object will be incremented. All other objects in the array
* will be moved to make space for the object being pre-pended.
*
* @param array The b_array to prepend the object to.
* @param value The object to prepend.
* @return B_SUCCESS if the object was prepended successfully, or an
* error code if an error occurred.
*/
BLUE_API b_status b_array_prepend(b_array *array, b_object *value);
/**
* Inserts an object into an b_array at a given index. The reference
* count of the object will be incremented. If the specified index is at
* the beginning or mid-way through the array (i.e. not at the end),
* some or all of the objects already in the array will be moved to make
* space for the object being inserted.
*
* @param array The b_array to insert the object into.
* @param value The object to insert.
* @param at The index to insert the object at. If the index is
* `B_NPOS`, the object will be inserted at the end of the b_array.
* @return B_SUCCESS if the object was inserted, or a status code
* describing any error that occurred.
*/
BLUE_API b_status b_array_insert(b_array *array, b_object *value, size_t at);
/**
* Removes the object at the specified index from an b_array. The
* reference count of the removed object will be decremented. If the
* specified index is at the beginning or mid-way through the array
* (i.e. not at the end), the remaining objects will be moved to fill
* the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @param at The index of the object to be removed.
* @return B_SUCCESS if the object was removed, or a status code
* describing any error that occurred.
*/
BLUE_API b_status b_array_remove(b_array *array, size_t at);
/**
* Removes the object at the beginning of an b_array. The reference count
* of the removed object will be decremented. The remaining objects will be moved
* to fill the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove_front(b_array *array);
/**
* Removes the object at the end of an b_array. The reference count
* of the removed object will be decremented.
*
* @param array The b_array to remove the object from.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove_back(b_array *array);
/**
* Removes the object at the specified index of an b_array, and returns
* a pointer to it. The reference count of the removed object will NOT
* be decremented. The caller becomes the owner of the array's reference
* to the object. If the specified index is at the beginning or mid-way
* through the array (i.e. not at the end), the remaining objects will
* be moved to fill the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @param at The index of the object to be removed.
* @return An pointer to the removed object. This pointer is owned by
* the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop(b_array *array, size_t at);
/**
* Removes the object at the beginning of an b_array, and returns a
* pointer to it. The reference count of the removed object will NOT be
* decremented. The caller becomes the owner of the array's reference to
* the object. The remaining objects in the b_array will be moved to
* fill the empty space left by the removed object.
*
* @param array The b_array to remove the object from.
* @return An pointer to the removed object. This pointer is owned by
* the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop_front(b_array *array);
/**
* Removes the object at the end of an b_array, and returns a pointer to it. The
* reference count of the removed object will NOT be decremented. The caller
* becomes the owner of the array's reference to the object.
*
* @param array The b_array to remove the object from.
* @return An pointer to the removed object. This pointer is owned by the
* caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop_back(b_array *array);
/**
* Returns an unowned pointer to the object at the given index of an b_array.
* The caller does not own the returned pointer, and MUST NOT release it.
*
* @param array The b_array.
* @param at The index of the object to return.
* @return A pointer to the object at the given index. This pointer is NOT owned
* by the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_at(const b_array *array, size_t at);
/**
* Returns an owned pointer to the object at the given index of an
* b_array. The caller owns the returned pointer, and must release it
* when they are finished with it.
*
* @param array The b_array.
* @param at The index of the object to return.
* @return A pointer to the object at the given index. This pointer is
* owned by the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_get(b_array *array, size_t at);
/**
* Returns the number of objects contained in an b_array.
*
* @param array The b_array.
* @return The number of objects contained in the b_array.
*/
BLUE_API size_t b_array_size(const b_array *array);
/**
* Returns the current maximum capacity of an b_array. This represents
* the number of objects that can be stored in an b_array before its
* internal buffer would need to be re-sized.
*
* @param array The b_array.
* @return The maximum capacity of the b_array.
*/
BLUE_API size_t b_array_capacity(const b_array *array);
B_DECLS_END;
#endif
-25
View File
@@ -1,25 +0,0 @@
#ifndef BLUE_DS_BITBUFFER_H_
#define BLUE_DS_BITBUFFER_H_
#include <blue/core/macros.h>
B_DECLS_BEGIN;
B_DECLARE_TYPE(b_bitbuffer);
B_TYPE_CLASS_DECLARATION_BEGIN(b_bitbuffer)
;
B_TYPE_CLASS_DECLARATION_END(b_bitbuffer);
BLUE_API b_status b_bitbuffer_put_bit(b_bitbuffer *buf, int bit);
BLUE_API b_status b_bitbuffer_put_bool(b_bitbuffer *buf, bool b);
BLUE_API b_status b_bitbuffer_put_int(
b_bitbuffer *buf, uint64_t v, unsigned int nr_bits);
BLUE_API b_status b_bitbuffer_put_bytes(
b_bitbuffer *buf, const void *p, size_t len, size_t bits_per_byte);
BLUE_API b_status b_bitbuffer_put_string(
b_bitbuffer *buf, const char *p, size_t len, size_t bits_per_char);
B_DECLS_END;
#endif
-40
View File
@@ -1,40 +0,0 @@
#ifndef BLUE_DS_BITMAP_H_
#define BLUE_DS_BITMAP_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <stdbool.h>
B_DECLS_BEGIN;
#define B_TYPE_BITMAP (b_bitmap_get_type())
B_DECLARE_TYPE(b_bitmap);
B_TYPE_CLASS_DECLARATION_BEGIN(b_bitmap)
B_TYPE_CLASS_DECLARATION_END(b_bitmap)
BLUE_API b_type b_bitmap_get_type(void);
BLUE_API b_bitmap *b_bitmap_create(size_t nr_bits);
BLUE_API void b_bitmap_set_bit(b_bitmap *map, size_t bit);
BLUE_API void b_bitmap_clear_bit(b_bitmap *map, size_t bit);
BLUE_API void b_bitmap_set_range(b_bitmap *map, size_t first_bit, size_t nbits);
BLUE_API void b_bitmap_clear_range(b_bitmap *map, size_t first_bit, size_t nbits);
BLUE_API void b_bitmap_set_all(b_bitmap *map);
BLUE_API void b_bitmap_clear_all(b_bitmap *map);
BLUE_API bool b_bitmap_check_bit(const b_bitmap *map, size_t bit);
BLUE_API size_t b_bitmap_count_set_bits(const b_bitmap *map);
BLUE_API size_t b_bitmap_count_clear_bits(const b_bitmap *map);
BLUE_API size_t b_bitmap_highest_set_bit(const b_bitmap *map);
BLUE_API size_t b_bitmap_highest_clear_bit(const b_bitmap *map);
BLUE_API size_t b_bitmap_lowest_set_bit(const b_bitmap *map);
BLUE_API size_t b_bitmap_lowest_clear_bit(const b_bitmap *map);
B_DECLS_END;
#endif
-49
View File
@@ -1,49 +0,0 @@
#ifndef BLUE_DS_BUFFER_H_
#define BLUE_DS_BUFFER_H_
#include <blue/core/macros.h>
#include <stddef.h>
B_DECLS_BEGIN;
#define B_TYPE_BUFFER (b_buffer_get_type())
B_DECLARE_TYPE(b_buffer);
B_TYPE_CLASS_DECLARATION_BEGIN(b_buffer)
B_TYPE_CLASS_DECLARATION_END(b_buffer)
BLUE_API b_type b_buffer_get_type(void);
BLUE_API b_buffer *b_buffer_create(size_t item_sz);
BLUE_API b_buffer *b_buffer_create_from_bytes(const void *p, size_t len);
BLUE_API b_buffer *b_buffer_create_from_array(
const void *p, size_t item_sz, size_t len);
BLUE_API void *b_buffer_steal(b_buffer *buf);
BLUE_API b_status b_buffer_reserve(b_buffer *buf, size_t capacity);
BLUE_API b_status b_buffer_resize(b_buffer *buf, size_t length);
BLUE_API b_status b_buffer_append(b_buffer *dest, const void *p, size_t count);
BLUE_API b_status b_buffer_prepend(b_buffer *dest, const void *p, size_t count);
BLUE_API b_status b_buffer_insert(
b_buffer *dest, const void *p, size_t count, size_t at);
BLUE_API b_status b_buffer_remove(b_buffer *dest, size_t at, size_t count);
BLUE_API b_status b_buffer_clear(b_buffer *buf);
BLUE_API b_status b_buffer_push_back(b_buffer *buf, size_t count, void **p);
BLUE_API b_status b_buffer_push_front(b_buffer *buf, size_t count, void **p);
BLUE_API b_status b_buffer_pop_back(b_buffer *buf, size_t count);
BLUE_API b_status b_buffer_pop_front(b_buffer *buf, size_t count);
BLUE_API size_t b_buffer_get_size(const b_buffer *buf);
BLUE_API size_t b_buffer_get_item_size(const b_buffer *buf);
BLUE_API size_t b_buffer_get_capacity(const b_buffer *buf);
BLUE_API void *b_buffer_ptr(const b_buffer *buf);
BLUE_API void *b_buffer_get(const b_buffer *buf, size_t at);
B_DECLS_END;
#endif
-48
View File
@@ -1,48 +0,0 @@
#ifndef BLUE_DS_DATETIME_H_
#define BLUE_DS_DATETIME_H_
#include <blue/core/macros.h>
#include <blue/core/status.h>
#include <ctype.h>
B_DECLS_BEGIN;
#define B_TYPE_DATETIME (b_datetime_get_type())
B_DECLARE_TYPE(b_datetime);
B_TYPE_CLASS_DECLARATION_BEGIN(b_datetime)
B_TYPE_CLASS_DECLARATION_END(b_datetime)
typedef enum b_datetime_format {
B_DATETIME_FORMAT_RFC3339 = 1,
} b_datetime_format;
BLUE_API b_type b_datetime_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_datetime, B_TYPE_DATETIME);
BLUE_API b_datetime *b_datetime_parse(b_datetime_format format, const char *s);
BLUE_API void b_datetime_to_string(
const b_datetime *dt, b_datetime_format format,
B_TYPE_FWDREF(b_stream) * dest);
BLUE_API bool b_datetime_is_localtime(const b_datetime *dt);
BLUE_API bool b_datetime_has_date(const b_datetime *dt);
BLUE_API bool b_datetime_has_time(const b_datetime *dt);
BLUE_API long b_datetime_year(const b_datetime *dt);
BLUE_API long b_datetime_month(const b_datetime *dt);
BLUE_API long b_datetime_day(const b_datetime *dt);
BLUE_API long b_datetime_hour(const b_datetime *dt);
BLUE_API long b_datetime_minute(const b_datetime *dt);
BLUE_API long b_datetime_second(const b_datetime *dt);
BLUE_API long b_datetime_subsecond(const b_datetime *dt);
BLUE_API bool b_datetime_zone_offset_is_negative(const b_datetime *dt);
BLUE_API long b_datetime_zone_offset_hour(const b_datetime *dt);
BLUE_API long b_datetime_zone_offset_minute(const b_datetime *dt);
B_DECLS_END;
#endif
-62
View File
@@ -1,62 +0,0 @@
#ifndef BLUE_DS_DICT_H_
#define BLUE_DS_DICT_H_
#include <blue/core/btree.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/queue.h>
#include <blue/core/status.h>
#include <blue/ds/string.h>
B_DECLS_BEGIN;
#define B_TYPE_DICT (b_dict_get_type())
#define B_TYPE_DICT_ITERATOR (b_dict_iterator_get_type())
struct b_dict_p;
B_DECLARE_TYPE(b_dict);
B_DECLARE_TYPE(b_dict_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_dict)
B_TYPE_CLASS_DECLARATION_END(b_dict)
B_TYPE_CLASS_DECLARATION_BEGIN(b_dict_iterator)
B_TYPE_CLASS_DECLARATION_END(b_dict_iterator)
#define B_DICT_ITEM(k, v) {.key = (k), .value = (v)}
#define B_DICT_ITEM_END {.key = NULL, .value = NULL}
#define b_dict_foreach(it, dict) \
for (int z__b_unique_name() = b_dict_iterator_begin(dict, it); \
(it)->key != NULL; b_dict_iterator_next(it))
typedef struct b_dict_item {
const b_string *key;
b_object *value;
} b_dict_item;
BLUE_API b_type b_dict_get_type(void);
BLUE_API b_type b_dict_iterator_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_dict, B_TYPE_DICT);
#if 0
BLUE_API b_dict *b_dict_create_with_items(const b_dict_item *items);
#endif
BLUE_API b_status b_dict_put(b_dict *dict, const char *key, b_object *value);
BLUE_API b_status b_dict_put_sk(b_dict *dict, const b_string *key, b_object *value);
BLUE_API b_object *b_dict_at(const b_dict *dict, const char *key);
BLUE_API b_object *b_dict_at_sk(const b_dict *dict, const b_string *key);
BLUE_API b_object *b_dict_get(b_dict *dict, const char *key);
BLUE_API b_object *b_dict_get_sk(b_dict *dict, const b_string *key);
BLUE_API bool b_dict_has_key(const b_dict *dict, const char *key);
BLUE_API bool b_dict_has_skey(const b_dict *dict, const b_string *key);
BLUE_API size_t b_dict_get_size(const b_dict *dict);
BLUE_API bool b_dict_is_empty(const b_dict *dict);
B_DECLS_END;
#endif
-83
View File
@@ -1,83 +0,0 @@
#ifndef BLUE_DS_HASHMAP_H_
#define BLUE_DS_HASHMAP_H_
#include <blue/core/btree.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/queue.h>
#include <blue/core/status.h>
#include <stddef.h>
B_DECLS_BEGIN;
struct b_hashmap_p;
#define B_TYPE_HASHMAP (b_hashmap_get_type())
#define B_TYPE_HASHMAP_ITERATOR (b_hashmap_iterator_get_type())
B_DECLARE_TYPE(b_hashmap);
B_DECLARE_TYPE(b_hashmap_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_hashmap)
B_TYPE_CLASS_DECLARATION_END(b_hashmap)
B_TYPE_CLASS_DECLARATION_BEGIN(b_hashmap_iterator)
B_TYPE_CLASS_DECLARATION_END(b_hashmap_iterator)
#define B_HASHMAP_KEY(k, ks) {.key_data = (k), .key_size = (ks)}
#define B_HASHMAP_VALUE(v, vs) {.value_data = (v), .value_size = (vs)}
#define B_HASHMAP_ITEM(k, ks, v, vs) \
{.key = B_HASHMAP_KEY(k, ks), .value = B_HASHMAP_VALUE(v, vs)}
#define B_HASHMAP_ITEM_END {.key = {0}, .value = {0}}
#define b_hashmap_foreach(it, hashmap) \
for (int z__b_unique_name() = b_hashmap_iterator_begin(hashmap, it); \
(it)->key != NULL; b_hashmap_iterator_next(it))
typedef void (*b_hashmap_key_destructor)(void *);
typedef void (*b_hashmap_value_destructor)(void *);
typedef enum b_hashmap_key_flags {
B_HASHMAP_KEY_F_INTVALUE = 0x01u,
} b_hashmap_key_flags;
typedef struct b_hashmap_key {
b_hashmap_key_flags key_flags;
const void *key_data;
size_t key_size;
} b_hashmap_key;
typedef struct b_hashmap_value {
void *value_data;
size_t value_size;
} b_hashmap_value;
typedef struct b_hashmap_item {
b_hashmap_key key;
b_hashmap_value value;
} b_hashmap_item;
BLUE_API b_type b_hashmap_get_type(void);
BLUE_API b_type b_hashmap_iterator_get_type(void);
BLUE_API b_hashmap *b_hashmap_create(
b_hashmap_key_destructor key_dtor, b_hashmap_value_destructor value_dtor);
BLUE_API b_hashmap *b_hashmap_create_with_items(const b_hashmap_item *items);
BLUE_API b_status b_hashmap_put(
b_hashmap *hashmap, const b_hashmap_key *key, const b_hashmap_value *value);
BLUE_API const b_hashmap_value *b_hashmap_get(
const b_hashmap *hashmap, const b_hashmap_key *key);
BLUE_API bool b_hashmap_has_key(const b_hashmap *hashmap, const b_hashmap_key *key);
BLUE_API size_t b_hashmap_get_size(const b_hashmap *hashmap);
BLUE_API bool b_hashmap_is_empty(const b_hashmap *hashmap);
BLUE_API b_iterator *b_hashmap_begin(b_hashmap *hashmap);
BLUE_API const b_iterator *b_hashmap_cbegin(const b_hashmap *hashmap);
B_DECLS_END;
#endif
-63
View File
@@ -1,63 +0,0 @@
#ifndef BLUE_DS_LIST_H_
#define BLUE_DS_LIST_H_
#include <blue/core/iterator.h>
#include <blue/core/macros.h>
#include <blue/core/status.h>
B_DECLS_BEGIN;
#define B_TYPE_LIST (b_list_get_type())
#define B_TYPE_LIST_ITERATOR (b_list_iterator_get_type())
struct b_list_p;
B_DECLARE_TYPE(b_list);
B_DECLARE_TYPE(b_list_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_list)
B_TYPE_CLASS_DECLARATION_END(b_list)
B_TYPE_CLASS_DECLARATION_BEGIN(b_list_iterator)
B_TYPE_CLASS_DECLARATION_END(b_list_iterator)
typedef struct b_list_entry b_list_entry;
BLUE_API b_type b_list_get_type(void);
BLUE_API b_type b_list_iterator_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_list, B_TYPE_LIST);
BLUE_API bool b_list_empty(b_list *q);
BLUE_API void *b_list_first_item(const b_list *q);
BLUE_API void *b_list_last_item(const b_list *q);
BLUE_API b_list_entry *b_list_first_entry(const b_list *q);
BLUE_API b_list_entry *b_list_last_entry(const b_list *q);
BLUE_API b_list_entry *b_list_next(const b_list_entry *entry);
BLUE_API b_list_entry *b_list_prev(const b_list_entry *entry);
BLUE_API size_t b_list_length(const b_list *q);
BLUE_API b_list_entry *b_list_insert_before(
b_list *q, void *ptr, b_list_entry *before);
BLUE_API b_list_entry *b_list_insert_after(
b_list *q, void *ptr, b_list_entry *after);
BLUE_API b_list_entry *b_list_push_front(b_list *q, void *ptr);
BLUE_API b_list_entry *b_list_push_back(b_list *q, void *ptr);
BLUE_API void *b_list_pop_front(b_list *q);
BLUE_API void *b_list_pop_back(b_list *q);
BLUE_API b_status b_list_delete_item(b_list *q, void *ptr);
BLUE_API b_status b_list_delete_entry(b_list *q, b_list_entry *entry);
BLUE_API void b_list_delete_all(b_list *q);
BLUE_API void *b_list_entry_value(const b_list_entry *entry);
BLUE_API b_iterator *b_list_begin(b_list *q);
BLUE_API const b_iterator *b_list_cbegin(const b_list *q);
B_DECLS_END;
#endif
-254
View File
@@ -1,254 +0,0 @@
#ifndef BLUE_DS_NUMBER_H
#define BLUE_DS_NUMBER_H
#include <blue/core/macros.h>
#include <stdbool.h>
B_DECLS_BEGIN;
#define B_INT8(v) (b_number_create_int8(v))
#define B_INT16(v) (b_number_create_int16(v))
#define B_INT32(v) (b_number_create_int32(v))
#define B_INT64(v) (b_number_create_int64(v))
#define B_FLOAT32(v) (b_number_create_float32(v))
#define B_FLOAT64(v) (b_number_create_float64(v))
#define B_CHAR(v) (b_number_create_char(v))
#define B_SHORT(v) (b_number_create_short(v))
#define B_INT(v) (b_number_create_int(v))
#define B_LONG(v) (b_number_create_long(v))
#define B_LONGLONG(v) (b_number_create_longlong(v))
#define B_FLOAT(v) (b_number_create_float(v))
#define B_DOUBLE(v) (b_number_create_double(v))
#define B_SIZE_T(v) (b_number_create_size_t(v))
#define B_RV_INT8(v) B_RV(b_number_create_int8(v))
#define B_RV_INT16(v) B_RV(b_number_create_int16(v))
#define B_RV_INT32(v) B_RV(b_number_create_int32(v))
#define B_RV_INT64(v) B_RV(b_number_create_int64(v))
#define B_RV_FLOAT32(v) B_RV(b_number_create_float32(v))
#define B_RV_FLOAT64(v) B_RV(b_number_create_float64(v))
#define B_RV_CHAR(v) B_RV(b_number_create_char(v))
#define B_RV_SHORT(v) B_RV(b_number_create_short(v))
#define B_RV_INT(v) B_RV(b_number_create_int(v))
#define B_RV_LONG(v) B_RV(b_number_create_long(v))
#define B_RV_LONGLONG(v) B_RV(b_number_create_longlong(v))
#define B_RV_FLOAT(v) B_RV(b_number_create_float(v))
#define B_RV_DOUBLE(v) B_RV(b_number_create_double(v))
#define B_RV_SIZE_T(v) B_RV(b_number_create_size_t(v))
#define B_NUMBER_IVAL(p) (b_number_get_size_t(p))
#define B_NUMBER_FVAL(p) (b_number_get_double(p))
#define B_TYPE_NUMBER (b_number_get_type())
B_DECLARE_TYPE(b_number);
B_TYPE_CLASS_DECLARATION_BEGIN(b_number)
B_TYPE_CLASS_DECLARATION_END(b_number)
typedef enum b_number_type {
B_NUMBER_INT8,
B_NUMBER_INT16,
B_NUMBER_INT32,
B_NUMBER_INT64,
B_NUMBER_FLOAT32,
B_NUMBER_FLOAT64,
B_NUMBER_CHAR,
B_NUMBER_SHORT,
B_NUMBER_INT,
B_NUMBER_LONG,
B_NUMBER_LONGLONG,
B_NUMBER_FLOAT,
B_NUMBER_DOUBLE,
B_NUMBER_SIZE_T,
B_NUMBER_HANDLE,
B_NUMBER_TYPE_COUNT,
B_NUMBER_BYTE = B_NUMBER_INT8,
B_NUMBER_WORD = B_NUMBER_INT16,
B_NUMBER_DWORD = B_NUMBER_INT32,
B_NUMBER_QWORD = B_NUMBER_INT64,
} b_number_type;
BLUE_API b_type b_number_get_type(void);
BLUE_API b_number *b_number_create(b_number_type type, void *value_ptr);
static inline b_number *b_number_create_int8(int8_t value)
{
return b_number_create(B_NUMBER_INT8, &value);
}
static inline b_number *b_number_create_int16(int16_t value)
{
return b_number_create(B_NUMBER_INT16, &value);
}
static inline b_number *b_number_create_int32(int32_t value)
{
return b_number_create(B_NUMBER_INT32, &value);
}
static inline b_number *b_number_create_int64(int64_t value)
{
return b_number_create(B_NUMBER_INT64, &value);
}
static inline b_number *b_number_create_float32(float value)
{
return b_number_create(B_NUMBER_FLOAT32, &value);
}
static inline b_number *b_number_create_float64(double value)
{
return b_number_create(B_NUMBER_FLOAT64, &value);
}
static inline b_number *b_number_create_char(char value)
{
return b_number_create(B_NUMBER_CHAR, &value);
}
static inline b_number *b_number_create_short(short value)
{
return b_number_create(B_NUMBER_SHORT, &value);
}
static inline b_number *b_number_create_int(int value)
{
return b_number_create(B_NUMBER_INT, &value);
}
static inline b_number *b_number_create_long(long value)
{
return b_number_create(B_NUMBER_LONG, &value);
}
static inline b_number *b_number_create_longlong(long long value)
{
return b_number_create(B_NUMBER_LONGLONG, &value);
}
static inline b_number *b_number_create_float(float value)
{
return b_number_create(B_NUMBER_FLOAT, &value);
}
static inline b_number *b_number_create_double(double value)
{
return b_number_create(B_NUMBER_DOUBLE, &value);
}
static inline b_number *b_number_create_size_t(size_t value)
{
return b_number_create(B_NUMBER_SIZE_T, &value);
}
BLUE_API b_number_type b_number_get_number_type(const b_number *number);
BLUE_API int b_number_get_value(
const b_number *number, b_number_type type, void *value_ptr);
static inline int8_t b_number_get_int8(const b_number *number)
{
int8_t v;
b_number_get_value(number, B_NUMBER_INT8, &v);
return v;
}
static inline int16_t b_number_get_int16(const b_number *number)
{
int16_t v;
b_number_get_value(number, B_NUMBER_INT16, &v);
return v;
}
static inline int32_t b_number_get_int32(const b_number *number)
{
int32_t v;
b_number_get_value(number, B_NUMBER_INT32, &v);
return v;
}
static inline int64_t b_number_get_int64(const b_number *number)
{
int64_t v;
b_number_get_value(number, B_NUMBER_INT64, &v);
return v;
}
static inline float b_number_get_float32(const b_number *number)
{
float v;
b_number_get_value(number, B_NUMBER_FLOAT32, &v);
return v;
}
static inline double b_number_get_float64(const b_number *number)
{
double v;
b_number_get_value(number, B_NUMBER_FLOAT64, &v);
return v;
}
static inline char b_number_get_char(const b_number *number)
{
char v;
b_number_get_value(number, B_NUMBER_CHAR, &v);
return v;
}
static inline short b_number_get_short(const b_number *number)
{
short v;
b_number_get_value(number, B_NUMBER_SHORT, &v);
return v;
}
static inline int b_number_get_int(const b_number *number)
{
int v;
b_number_get_value(number, B_NUMBER_INT, &v);
return v;
}
static inline long b_number_get_long(const b_number *number)
{
long v;
b_number_get_value(number, B_NUMBER_LONG, &v);
return v;
}
static inline long long b_number_get_longlong(const b_number *number)
{
long long v;
b_number_get_value(number, B_NUMBER_LONGLONG, &v);
return v;
}
static inline float b_number_get_float(const b_number *number)
{
float v;
b_number_get_value(number, B_NUMBER_FLOAT, &v);
return v;
}
static inline double b_number_get_double(const b_number *number)
{
double v;
b_number_get_value(number, B_NUMBER_DOUBLE, &v);
return v;
}
static inline size_t b_number_get_size_t(const b_number *number)
{
size_t v;
b_number_get_value(number, B_NUMBER_SIZE_T, &v);
return v;
}
BLUE_API bool b_number_is_integer(const b_number *number);
BLUE_API bool b_number_is_float(const b_number *number);
BLUE_API bool b_number_is_inf(const b_number *number);
BLUE_API bool b_number_is_inf_positive(const b_number *number);
BLUE_API bool b_number_is_inf_negative(const b_number *number);
BLUE_API bool b_number_is_nan(const b_number *number);
BLUE_API bool b_number_is_nan_positive(const b_number *number);
BLUE_API bool b_number_is_nan_negative(const b_number *number);
BLUE_API void b_number_set_inf_positive(b_number *number, bool v);
BLUE_API void b_number_set_inf_negative(b_number *number, bool v);
BLUE_API void b_number_set_nan_positive(b_number *number, bool v);
BLUE_API void b_number_set_nan_negative(b_number *number, bool v);
BLUE_API size_t b_number_data_size(const b_number *number);
B_DECLS_END;
#endif
-129
View File
@@ -1,129 +0,0 @@
#ifndef BLUE_DS_STRING_H_
#define BLUE_DS_STRING_H_
#include <blue/core/encoding.h>
#include <blue/core/iterator.h>
#include <blue/core/macros.h>
#include <blue/core/status.h>
#include <blue/core/stringstream.h>
#include <ctype.h>
B_DECLS_BEGIN;
struct b_stream;
struct b_string_p;
#define B_TYPE_STRING (b_string_get_type())
#define B_TYPE_STRING_ITERATOR (b_string_iterator_get_type())
B_DECLARE_TYPE(b_string);
B_DECLARE_TYPE(b_string_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_string)
B_TYPE_CLASS_DECLARATION_END(b_string)
B_TYPE_CLASS_DECLARATION_BEGIN(b_string_iterator)
B_TYPE_CLASS_DECLARATION_END(b_string_iterator)
#define B_CSTR(s) (b_string_create_from_cstr(s))
#define B_RV_CSTR(s) (B_RV(b_string_create_from_cstr(s)))
typedef enum b_strlen_flags {
B_STRLEN_NORMAL = 0,
B_STRLEN_IGNORE_ESC = 0x01u,
B_STRLEN_IGNORE_MOD = 0x02u,
B_STRLEN_CODEPOINTS = 0x04u,
} b_strlen_flags;
typedef enum b_string_tokenise_flags {
B_STRING_TOK_F_NORMAL = 0x00u,
B_STRING_TOK_F_INCLUDE_EMPTY_TOKENS = 0x01u,
} b_string_tokenise_flags;
BLUE_API b_type b_string_get_type(void);
BLUE_API b_type b_string_iterator_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_string, B_TYPE_STRING);
BLUE_API b_string *b_string_create_from_cstr(const char *s);
BLUE_API b_string *b_string_create_from_wstr(const b_wchar *s);
BLUE_API b_string *b_string_create_from_c(char c, size_t count);
BLUE_API b_string *b_string_duplicate(const b_string *str);
BLUE_API char *b_string_steal(b_string *str);
BLUE_API b_status b_string_reserve(b_string *str, size_t capacity);
BLUE_API b_status b_string_replace(
b_string *str, size_t start, size_t length, const char *new_data);
BLUE_API b_status b_string_replace_all(b_string *str, const char *new_data);
BLUE_API b_status b_string_replace_all_with_stringstream(
b_string *str, const b_stringstream *new_data);
BLUE_API b_status b_string_remove(b_string *str, size_t start, size_t length);
BLUE_API b_status b_string_transform(b_string *str, int (*transformer)(int));
BLUE_API b_status b_string_trim(b_string *str);
static inline b_status b_string_toupper(b_string *str)
{
return b_string_transform(str, toupper);
}
static inline b_status b_string_tolower(b_string *str)
{
return b_string_transform(str, tolower);
}
BLUE_API b_status b_string_append_c(b_string *dest, char c);
BLUE_API b_status b_string_append_wc(b_string *dest, b_wchar c);
BLUE_API b_status b_string_append_s(b_string *dest, const b_string *src);
BLUE_API b_status b_string_append_cstr(b_string *dest, const char *src);
BLUE_API b_status b_string_append_wstr(b_string *dest, const b_wchar *src);
BLUE_API b_status b_string_append_cstrf(b_string *dest, const char *format, ...);
BLUE_API b_status b_string_prepend_c(b_string *dest, char c);
BLUE_API b_status b_string_prepend_wc(b_string *dest, b_wchar c);
BLUE_API b_status b_string_prepend_cstr(b_string *dest, const char *src);
BLUE_API b_status b_string_prepend_wstr(b_string *dest, const b_wchar *src);
BLUE_API b_status b_string_prepend_cstrf(b_string *dest, const char *format, ...);
BLUE_API b_status b_string_insert_c(b_string *dest, char c, size_t at);
BLUE_API b_status b_string_insert_wc(b_string *dest, b_wchar c, size_t at);
BLUE_API b_status b_string_insert_s(b_string *dest, const b_string *src, size_t at);
BLUE_API b_status b_string_insert_cstr(b_string *dest, const char *src, size_t at);
BLUE_API b_status b_string_insert_wstr(
b_string *dest, const b_wchar *src, size_t at);
BLUE_API b_status b_string_insert_cstrn(
b_string *dest, const char *src, size_t len, size_t at);
BLUE_API b_status b_string_insert_wstrn(
b_string *dest, const char *src, size_t len, size_t at);
BLUE_API b_status b_string_insert_cstrf(
b_string *dest, size_t at, const char *format, ...);
BLUE_API void b_string_clear(b_string *str);
BLUE_API b_iterator *b_string_tokenise(
b_string *str, const char *delims[], size_t nr_delims,
b_string_tokenise_flags flags);
BLUE_API size_t b_string_get_size(const b_string *str, b_strlen_flags flags);
BLUE_API size_t b_string_get_capacity(const b_string *str);
BLUE_API bool b_string_compare(const b_string *a, const b_string *b);
BLUE_API char b_string_front(const b_string *str);
BLUE_API char b_string_back(const b_string *str);
BLUE_API void b_string_pop_back(b_string *str);
BLUE_API const char *b_string_ptr(const b_string *str);
BLUE_API b_string *b_string_substr(const b_string *str, size_t start, size_t len);
BLUE_API int b_string_iterator_begin(const b_string *string, b_string_iterator *it);
BLUE_API bool b_string_iterator_next(b_string_iterator *it);
// BLUE_API b_status b_string_iterator_erase(b_string_iterator *it);
BLUE_API bool b_string_iterator_is_valid(const b_string_iterator *it);
BLUE_API char *b_strdup(const char *s);
BLUE_API size_t b_strlen(const char *s, b_strlen_flags flags);
BLUE_API b_wchar *b_wstrdup(const b_wchar *s);
BLUE_API size_t b_wstrlen(const b_wchar *s);
BLUE_API uint64_t b_string_hash(const b_string *s);
B_DECLS_END;
#endif
-57
View File
@@ -1,57 +0,0 @@
#ifndef BLUE_DS_TREE_H_
#define BLUE_DS_TREE_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/queue.h>
#include <blue/ds/string.h>
B_DECLS_BEGIN;
#define B_TYPE_TREE (b_tree_get_type())
#define B_TYPE_TREE_ITERATOR (b_tree_iterator_get_type())
B_DECLARE_TYPE(b_tree);
B_DECLARE_TYPE(b_tree_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_tree)
B_TYPE_CLASS_DECLARATION_END(b_tree)
B_TYPE_CLASS_DECLARATION_BEGIN(b_tree_iterator)
B_TYPE_CLASS_DECLARATION_END(b_tree_iterator)
#define B_TREE_NODE_INIT ((b_tree_node) {0})
#define B_TREE_CONTAINER(t, m, v) \
((void *)((v) ? (uintptr_t)(v) - (offsetof(t, m)) : 0))
typedef struct b_tree_node {
struct b_tree_node *__p01, *__p02, *__p03;
struct b_queue_entry __q01;
} b_tree_node;
BLUE_API b_type b_tree_get_type(void);
BLUE_API b_type b_tree_iterator_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_tree, B_TYPE_TREE);
BLUE_API void b_tree_set_root(b_tree *tree, struct b_tree_node *node);
BLUE_API void b_tree_node_add_child(b_tree_node *parent, b_tree_node *child);
BLUE_API void b_tree_node_add_sibling(b_tree_node *node, b_tree_node *to_add);
BLUE_API b_tree_node *b_tree_node_get_child(b_tree_node *node, size_t at);
BLUE_API b_tree_node *b_tree_node_get_parent(b_tree_node *node);
BLUE_API b_iterator *b_tree_begin(b_tree *tree);
BLUE_API const b_iterator *b_tree_cbegin(const b_tree *tree);
BLUE_API b_iterator *b_tree_node_begin(b_tree_node *node);
BLUE_API const b_iterator *b_tree_node_cbegin(const b_tree_node *node);
BLUE_API b_iterator *b_tree_node_begin_recursive(b_tree_node *node);
BLUE_API const b_iterator *b_tree_node_cbegin_recursive(const b_tree_node *node);
B_DECLS_END;
#endif
-50
View File
@@ -1,50 +0,0 @@
#ifndef BLUE_DS_UUID_H_
#define BLUE_DS_UUID_H_
#include <blue/core/macros.h>
#include <blue/core/status.h>
#include <blue/ds/string.h>
#define B_UUID_NBYTES 16
#define B_UUID_STRING_MAX 37
B_DECLS_BEGIN;
#define B_TYPE_UUID (b_uuid_get_type())
B_DECLARE_TYPE(b_uuid);
B_TYPE_CLASS_DECLARATION_BEGIN(b_uuid)
B_TYPE_CLASS_DECLARATION_END(b_uuid)
typedef union b_uuid_bytes {
uint8_t uuid_bytes[B_UUID_NBYTES];
uint16_t uuid_words[B_UUID_NBYTES / 2];
uint32_t uuid_dwords[B_UUID_NBYTES / 4];
uint64_t uuid_qwords[B_UUID_NBYTES / 8];
} b_uuid_bytes;
BLUE_API b_type b_uuid_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_uuid, B_TYPE_UUID);
BLUE_API b_uuid *b_uuid_create_from_bytes(
unsigned char u00, unsigned char u01, unsigned char u02,
unsigned char u03, unsigned char u04, unsigned char u05,
unsigned char u06, unsigned char u07, unsigned char u08,
unsigned char u09, unsigned char u10, unsigned char u11, unsigned char u12,
unsigned char u13, unsigned char u14, unsigned char u15);
BLUE_API b_uuid *b_uuid_create_from_bytev(const unsigned char bytes[B_UUID_NBYTES]);
BLUE_API b_uuid *b_uuid_create_from_uuid_bytes(const b_uuid_bytes *bytes);
BLUE_API b_uuid *b_uuid_create_from_string(const b_string *string);
BLUE_API b_uuid *b_uuid_create_from_cstr(const char *s);
BLUE_API b_status b_uuid_to_cstr(const b_uuid *uuid, char out[B_UUID_STRING_MAX]);
BLUE_API void b_uuid_get_bytes(
const b_uuid *uuid, unsigned char bytes[B_UUID_NBYTES]);
BLUE_API void b_uuid_get_uuid_bytes(const b_uuid *uuid, b_uuid_bytes *bytes);
BLUE_API b_uuid_bytes *b_uuid_ptr(b_uuid *uuid);
B_DECLS_END;
#endif
-529
View File
@@ -1,529 +0,0 @@
#include <blue/core/iterator.h>
#include <blue/core/queue.h>
#include <blue/ds/list.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
struct b_list_entry {
struct b_queue_entry e_entry;
void *e_data;
};
struct b_list_p {
struct b_queue l_queue;
size_t l_len;
};
struct b_list_iterator_p {
b_list *_q;
struct b_list_p *_q_p;
struct b_queue_entry *_q_entry;
size_t i;
void *item;
b_list_entry *entry;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static bool list_empty(struct b_list_p *q)
{
return q->l_len == 0;
}
static void *list_first_item(const struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_first(&q->l_queue);
if (!entry) {
return NULL;
}
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
return list_entry->e_data;
}
static void *list_last_item(const struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_last(&q->l_queue);
if (!entry) {
return NULL;
}
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
return list_entry->e_data;
}
static struct b_list_entry *list_first_entry(const struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_first(&q->l_queue);
if (!entry) {
return NULL;
}
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
return list_entry;
}
static struct b_list_entry *list_last_entry(const struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_last(&q->l_queue);
if (!entry) {
return NULL;
}
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
return list_entry;
}
static size_t list_length(const struct b_list_p *q)
{
return q->l_len;
}
static struct b_list_entry *make_entry(void *item)
{
struct b_list_entry *entry = malloc(sizeof *entry);
if (!entry) {
return NULL;
}
memset(entry, 0x0, sizeof *entry);
entry->e_data = item;
return entry;
}
static struct b_list_entry *list_insert_before(
struct b_list_p *q, void *ptr, struct b_list_entry *before)
{
struct b_list_entry *entry = make_entry(ptr);
if (!entry) {
return NULL;
}
b_queue_insert_before(&q->l_queue, &entry->e_entry, &before->e_entry);
q->l_len++;
return entry;
}
static struct b_list_entry *list_insert_after(
struct b_list_p *q, void *ptr, struct b_list_entry *after)
{
struct b_list_entry *entry = make_entry(ptr);
if (!entry) {
return NULL;
}
b_queue_insert_after(&q->l_queue, &entry->e_entry, &after->e_entry);
q->l_len++;
return entry;
}
static struct b_list_entry *list_push_front(struct b_list_p *q, void *ptr)
{
struct b_list_entry *entry = make_entry(ptr);
if (!entry) {
return NULL;
}
b_queue_push_front(&q->l_queue, &entry->e_entry);
q->l_len++;
return entry;
}
static struct b_list_entry *list_push_back(struct b_list_p *q, void *ptr)
{
struct b_list_entry *entry = make_entry(ptr);
if (!entry) {
return NULL;
}
b_queue_push_back(&q->l_queue, &entry->e_entry);
q->l_len++;
return entry;
}
static void *list_pop_front(struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_pop_front(&q->l_queue);
if (!entry) {
return NULL;
}
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
void *item = list_entry->e_data;
free(list_entry);
q->l_len--;
return item;
}
static void *list_pop_back(struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_pop_back(&q->l_queue);
if (!entry) {
return NULL;
}
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
void *item = list_entry->e_data;
free(list_entry);
q->l_len--;
return item;
}
static struct b_list_entry *find_item(struct b_list_p *list, void *item)
{
struct b_queue_entry *entry = b_queue_first(&list->l_queue);
while (entry) {
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
if (list_entry->e_data == item) {
return list_entry;
}
entry = b_queue_next(entry);
}
return NULL;
}
static b_status list_delete_item(struct b_list_p *q, void *ptr)
{
struct b_list_entry *entry = find_item(q, ptr);
if (!entry) {
return B_ERR_NO_ENTRY;
}
b_queue_delete(&q->l_queue, &entry->e_entry);
q->l_len--;
free(entry);
return B_SUCCESS;
}
static b_status list_delete_entry(struct b_list_p *q, struct b_list_entry *entry)
{
b_queue_delete(&q->l_queue, &entry->e_entry);
q->l_len--;
free(entry);
return B_SUCCESS;
}
static void list_delete_all(struct b_list_p *q)
{
struct b_queue_entry *entry = b_queue_first(&q->l_queue);
while (entry) {
struct b_list_entry *list_entry
= b_unbox(struct b_list_entry, entry, e_entry);
struct b_queue_entry *next = b_queue_next(entry);
free(list_entry);
entry = next;
}
q->l_len = 0;
}
/*** PUBLIC FUNCTIONS *********************************************************/
bool b_list_empty(b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_empty, q);
}
void *b_list_first_item(const b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_first_item, q);
}
void *b_list_last_item(const b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_last_item, q);
}
struct b_list_entry *b_list_first_entry(const b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_first_entry, q);
}
struct b_list_entry *b_list_last_entry(const b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, b_list_last_entry, q);
}
struct b_list_entry *b_list_next(const struct b_list_entry *entry)
{
if (!entry) {
return NULL;
}
struct b_queue_entry *next = b_queue_next(&entry->e_entry);
if (!next) {
return NULL;
}
return b_unbox(struct b_list_entry, next, e_entry);
}
struct b_list_entry *b_list_prev(const struct b_list_entry *entry)
{
if (!entry) {
return NULL;
}
struct b_queue_entry *next = b_queue_prev(&entry->e_entry);
if (!next) {
return NULL;
}
return b_unbox(struct b_list_entry, next, e_entry);
}
size_t b_list_length(const b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_length, q);
}
struct b_list_entry *b_list_insert_before(
b_list *q, void *ptr, struct b_list_entry *before)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_LIST, list_insert_before, q, ptr, before);
}
struct b_list_entry *b_list_insert_after(
b_list *q, void *ptr, struct b_list_entry *after)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_LIST, list_insert_after, q, ptr, after);
}
struct b_list_entry *b_list_push_front(b_list *q, void *ptr)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_LIST, list_push_front, q, ptr);
}
struct b_list_entry *b_list_push_back(b_list *q, void *ptr)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_LIST, list_push_back, q, ptr);
}
void *b_list_pop_front(b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_pop_front, q);
}
void *b_list_pop_back(b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_pop_back, q);
}
b_status b_list_delete_item(b_list *q, void *ptr)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_LIST, list_delete_item, q, ptr);
}
b_status b_list_delete_entry(b_list *q, struct b_list_entry *entry)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_LIST, list_delete_entry, q, entry);
}
void b_list_delete_all(b_list *q)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_LIST, list_delete_all, q);
}
void *b_list_entry_value(const struct b_list_entry *entry)
{
return entry ? entry->e_data : NULL;
}
b_iterator *b_list_begin(b_list *q)
{
b_list_iterator *it_obj = b_object_create(B_TYPE_LIST_ITERATOR);
struct b_list_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_LIST_ITERATOR);
it->_q = q;
it->_q_p = b_object_get_private(q, B_TYPE_LIST);
it->_q_entry = b_queue_first(&it->_q_p->l_queue);
it->i = 0;
it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry);
if (it->entry) {
it->item = it->entry->e_data;
}
return 0;
}
const b_iterator *b_list_cbegin(const b_list *q)
{
b_list_iterator *it_obj = b_object_create(B_TYPE_LIST_ITERATOR);
struct b_list_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_LIST_ITERATOR);
it->_q = (b_list *)q;
it->_q_p = b_object_get_private(q, B_TYPE_LIST);
it->_q_entry = b_queue_first(&it->_q_p->l_queue);
it->i = 0;
it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry);
if (it->entry) {
it->item = it->entry->e_data;
}
return 0;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void list_init(b_object *obj, void *priv)
{
struct b_list_p *list = priv;
}
static void list_fini(b_object *obj, void *priv)
{
struct b_list_p *list = priv;
list_delete_all(list);
}
/*** ITERATOR FUNCTIONS *******************************************************/
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_list_iterator_p *it
= b_object_get_private(obj, B_TYPE_LIST_ITERATOR);
if (!it->_q_entry) {
it->entry = NULL;
it->item = NULL;
return B_ERR_NO_DATA;
}
it->_q_entry = b_queue_next(it->_q_entry);
if (!it->_q_entry) {
it->entry = NULL;
it->item = NULL;
return B_ERR_NO_DATA;
}
it->i++;
it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry);
if (it->entry) {
it->item = it->entry->e_data;
}
return it->entry != NULL;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_list_iterator_p *it
= b_object_get_private(obj, B_TYPE_LIST_ITERATOR);
if (!it->entry || !it->_q_entry) {
return B_ERR_OUT_OF_BOUNDS;
}
struct b_queue_entry *next = b_queue_next(it->_q_entry);
b_queue_delete(&it->_q_p->l_queue, it->_q_entry);
free(it->entry);
it->_q_entry = next;
it->entry = b_unbox(struct b_list_entry, it->_q_entry, e_entry);
if (it->entry) {
it->item = it->entry->e_data;
}
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_list_iterator_p *it
= b_object_get_private(obj, B_TYPE_LIST_ITERATOR);
return B_ITERATOR_VALUE_PTR(it->item);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_list_iterator_p *it
= b_object_get_private(obj, B_TYPE_LIST_ITERATOR);
return B_ITERATOR_VALUE_CPTR(it->item);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_list DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_list)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = b_list_begin;
B_INTERFACE_ENTRY(it_cbegin) = b_list_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_list)
B_TYPE_DEFINITION_BEGIN(b_list)
B_TYPE_ID(0x8730e66f, 0x0fd9, 0x4773, 0x9bbd, 0x6428f6e495eb);
B_TYPE_CLASS(b_list_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_list_p);
B_TYPE_INSTANCE_INIT(list_init);
B_TYPE_INSTANCE_FINI(list_fini);
B_TYPE_DEFINITION_END(b_list)
// ---- b_list_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_list_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_list_iterator)
B_TYPE_DEFINITION_BEGIN(b_list_iterator)
B_TYPE_ID(0xd9658456, 0xdd80, 0x419a, 0xb23a, 0xb513013e6431);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_list_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_list_iterator_p);
B_TYPE_DEFINITION_END(b_list_iterator)
-2326
View File
File diff suppressed because it is too large Load Diff
-380
View File
@@ -1,380 +0,0 @@
#include <blue/ds/tree.h>
#include <stdlib.h>
#include <string.h>
#define ITERATOR_RECURSIVE 0x01u
#define ITERATOR_IS_RECURSIVE(it) (((it)->_f01 & ITERATOR_RECURSIVE) != 0)
#define ITERATOR_UNSET_RECURSIVE(it) ((it)->_f01 &= ~ITERATOR_RECURSIVE)
#define ITERATOR_SET_RECURSIVE(it) ((it)->_f01 |= ITERATOR_RECURSIVE)
#define NODE_PARENT(n) ((n)->__p01)
#define NODE_FIRST_CHILD(n) ((n)->__p02)
#define NODE_NEXT_SIBLING(n) ((n)->__p03)
/*** PRIVATE DATA *************************************************************/
struct b_tree_p {
struct b_tree_node *t_root;
};
struct b_tree_iterator_p {
size_t i, depth;
b_tree_node *node;
unsigned char _f01;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static void tree_set_root(struct b_tree_p *tree, struct b_tree_node *node)
{
tree->t_root = node;
}
static const struct b_tree_node *next_node(
const struct b_tree_node *node, bool recursive, int *depth_diff)
{
if (!node) {
return NULL;
}
if (!recursive) {
node = NODE_NEXT_SIBLING(node);
return node;
}
int d = 0;
struct b_tree_node *next = NODE_FIRST_CHILD(node);
if (next) {
d = 1;
*depth_diff = d;
return next;
}
const struct b_tree_node *n = node;
next = NODE_NEXT_SIBLING(n);
while (!next) {
n = NODE_PARENT(n);
if (!n) {
break;
}
d--;
next = NODE_NEXT_SIBLING(n);
}
*depth_diff = d;
return next;
}
static void remove_node(struct b_tree_node *node)
{
struct b_tree_node *parent = NODE_PARENT(node);
if (!parent) {
return;
}
struct b_tree_node *n0 = NULL, *n1 = NULL;
n0 = NODE_FIRST_CHILD(parent);
while (n0) {
if (n0 == node) {
break;
}
n1 = n0;
n0 = NODE_NEXT_SIBLING(n0);
}
if (!n0) {
return;
}
if (n1) {
NODE_NEXT_SIBLING(n1) = NODE_NEXT_SIBLING(n0);
} else {
NODE_FIRST_CHILD(parent) = NODE_NEXT_SIBLING(n0);
}
NODE_PARENT(n0) = NODE_NEXT_SIBLING(n0) = NULL;
}
static void reparent_children(
struct b_tree_node *old_parent, struct b_tree_node *new_parent)
{
struct b_tree_node *last = NODE_FIRST_CHILD(new_parent);
while (last && NODE_NEXT_SIBLING(last)) {
last = NODE_NEXT_SIBLING(last);
}
struct b_tree_node *cur = NODE_FIRST_CHILD(old_parent);
while (cur) {
struct b_tree_node *next = NODE_NEXT_SIBLING(cur);
NODE_PARENT(cur) = new_parent;
NODE_NEXT_SIBLING(cur) = NULL;
if (last) {
NODE_NEXT_SIBLING(last) = cur;
} else {
NODE_FIRST_CHILD(new_parent) = cur;
}
last = cur;
cur = next;
}
}
/*** PUBLIC FUNCTIONS *********************************************************/
void b_tree_set_root(b_tree *tree, struct b_tree_node *node)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_TREE, tree_set_root, tree, node);
}
void b_tree_node_add_child(struct b_tree_node *parent, struct b_tree_node *child)
{
if (NODE_PARENT(child)) {
return;
}
NODE_PARENT(child) = parent;
if (!NODE_FIRST_CHILD(parent)) {
NODE_FIRST_CHILD(parent) = child;
return;
}
struct b_tree_node *cur = NODE_FIRST_CHILD(parent);
while (NODE_NEXT_SIBLING(cur)) {
cur = NODE_NEXT_SIBLING(cur);
}
NODE_NEXT_SIBLING(cur) = child;
}
void b_tree_node_add_sibling(struct b_tree_node *node, struct b_tree_node *to_add)
{
if (NODE_PARENT(to_add) || !NODE_PARENT(node)) {
return;
}
b_tree_node_add_child(NODE_PARENT(node), to_add);
}
struct b_tree_node *b_tree_node_get_child(struct b_tree_node *node, size_t at)
{
size_t i = 0;
struct b_tree_node *cur = NODE_FIRST_CHILD(node);
while (i < at) {
if (!cur) {
return NULL;
}
cur = NODE_NEXT_SIBLING(cur);
i++;
}
return cur;
}
b_iterator *b_tree_begin(b_tree *tree)
{
struct b_tree_p *p = b_object_get_private(tree, B_TYPE_TREE);
return b_tree_node_begin(p->t_root);
}
const b_iterator *b_tree_cbegin(const b_tree *tree)
{
struct b_tree_p *p = b_object_get_private(tree, B_TYPE_TREE);
return b_tree_node_begin(p->t_root);
}
b_iterator *b_tree_node_begin(struct b_tree_node *node)
{
b_tree_iterator *it_obj = b_object_create(B_TYPE_TREE_ITERATOR);
struct b_tree_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_TREE_ITERATOR);
it->node = NODE_FIRST_CHILD(node);
it->i = 0;
it->depth = 0;
ITERATOR_UNSET_RECURSIVE(it);
if (!it->node) {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
}
return it_obj;
}
const b_iterator *b_tree_node_cbegin(const struct b_tree_node *node)
{
return b_tree_node_begin((struct b_tree_node *)node);
}
b_iterator *b_tree_node_begin_recursive(struct b_tree_node *node)
{
b_tree_iterator *it_obj = b_object_create(B_TYPE_TREE_ITERATOR);
struct b_tree_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_TREE_ITERATOR);
it->node = node;
it->i = 0;
it->depth = 0;
ITERATOR_SET_RECURSIVE(it);
if (!it->node) {
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
}
return it_obj;
}
const b_iterator *b_tree_node_cbegin_recursive(const struct b_tree_node *node)
{
return b_tree_node_begin_recursive((struct b_tree_node *)node);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void tree_init(b_object *obj, void *priv)
{
struct b_tree_p *tree = priv;
}
static void tree_fini(b_object *obj, void *priv)
{
struct b_tree_p *tree = priv;
}
/*** ITERATOR FUNCTIONS *******************************************************/
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_tree_iterator_p *it
= b_object_get_private(obj, B_TYPE_TREE_ITERATOR);
int depth_diff = 0;
const struct b_tree_node *next
= next_node(it->node, ITERATOR_IS_RECURSIVE(it), &depth_diff);
if (next) {
it->depth += depth_diff;
it->i++;
} else {
it->depth = 0;
it->i = 0;
}
it->node = (struct b_tree_node *)next;
return (it->node != NULL) ? B_SUCCESS : B_ERR_NO_DATA;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_tree_iterator_p *it
= b_object_get_private(obj, B_TYPE_TREE_ITERATOR);
if (!it->node) {
return B_ERR_OUT_OF_BOUNDS;
}
struct b_tree_node *parent = NODE_PARENT(it->node);
if (!parent) {
return B_ERR_NOT_SUPPORTED;
}
int d = 0;
struct b_tree_node *n = it->node;
struct b_tree_node *next = NODE_NEXT_SIBLING(n);
if (!next) {
next = NODE_FIRST_CHILD(n);
}
while (!next) {
n = NODE_PARENT(n);
if (!n) {
break;
}
d--;
next = NODE_NEXT_SIBLING(n);
}
remove_node(it->node);
reparent_children(it->node, parent);
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_tree_iterator_p *it
= b_object_get_private(obj, B_TYPE_TREE_ITERATOR);
if (!it->node) {
return B_ITERATOR_VALUE_NULL;
}
return B_ITERATOR_VALUE_PTR(it->node);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_tree_iterator_p *it
= b_object_get_private(obj, B_TYPE_TREE_ITERATOR);
if (!it->node) {
return B_ITERATOR_VALUE_NULL;
}
return B_ITERATOR_VALUE_CPTR(it->node);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_tree DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_tree)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = b_tree_begin;
B_INTERFACE_ENTRY(it_cbegin) = b_tree_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_tree)
B_TYPE_DEFINITION_BEGIN(b_tree)
B_TYPE_ID(0x8d8fa36b, 0xc515, 0x4803, 0x8124, 0xfd704f01b8ae);
B_TYPE_CLASS(b_tree_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_tree_p);
B_TYPE_INSTANCE_INIT(tree_init);
B_TYPE_INSTANCE_FINI(tree_fini);
B_TYPE_DEFINITION_END(b_tree)
// ---- b_tree_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_tree_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_tree_iterator)
B_TYPE_DEFINITION_BEGIN(b_tree_iterator)
B_TYPE_ID(0xb896e671, 0x84b2, 0x4892, 0xaf09, 0x407f305f4bf8);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_tree_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_tree_iterator_p);
B_TYPE_DEFINITION_END(b_tree_iterator)
-227
View File
@@ -1,227 +0,0 @@
#include <blue/core/stringstream.h>
#include <blue/ds/string.h>
#include <blue/ds/uuid.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
struct b_uuid_p {
union b_uuid_bytes uuid_bytes;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static b_status uuid_to_cstr(
const struct b_uuid_p *uuid, char out[B_UUID_STRING_MAX])
{
snprintf(
out, B_UUID_STRING_MAX,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%"
"02x%02x",
uuid->uuid_bytes.uuid_bytes[0], uuid->uuid_bytes.uuid_bytes[1],
uuid->uuid_bytes.uuid_bytes[2], uuid->uuid_bytes.uuid_bytes[3],
uuid->uuid_bytes.uuid_bytes[4], uuid->uuid_bytes.uuid_bytes[5],
uuid->uuid_bytes.uuid_bytes[6], uuid->uuid_bytes.uuid_bytes[7],
uuid->uuid_bytes.uuid_bytes[8], uuid->uuid_bytes.uuid_bytes[9],
uuid->uuid_bytes.uuid_bytes[10], uuid->uuid_bytes.uuid_bytes[11],
uuid->uuid_bytes.uuid_bytes[12], uuid->uuid_bytes.uuid_bytes[13],
uuid->uuid_bytes.uuid_bytes[14], uuid->uuid_bytes.uuid_bytes[15]);
return B_SUCCESS;
}
static void uuid_get_bytes(
const struct b_uuid_p *uuid, unsigned char bytes[B_UUID_NBYTES])
{
memcpy(bytes, uuid->uuid_bytes.uuid_bytes, B_UUID_NBYTES);
}
static void uuid_get_uuid_bytes(
const struct b_uuid_p *uuid, union b_uuid_bytes *bytes)
{
memcpy(bytes, &uuid->uuid_bytes, sizeof *bytes);
}
static union b_uuid_bytes *uuid_ptr(struct b_uuid_p *uuid)
{
return &uuid->uuid_bytes;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_uuid *b_uuid_create_from_bytes(
unsigned char u00, unsigned char u01, unsigned char u02,
unsigned char u03, unsigned char u04, unsigned char u05,
unsigned char u06, unsigned char u07, unsigned char u08,
unsigned char u09, unsigned char u10, unsigned char u11,
unsigned char u12, unsigned char u13, unsigned char u14, unsigned char u15)
{
b_uuid *uuid = b_uuid_create();
if (!uuid) {
return NULL;
}
struct b_uuid_p *p = b_object_get_private(uuid, B_TYPE_UUID);
p->uuid_bytes.uuid_bytes[0] = u00;
p->uuid_bytes.uuid_bytes[1] = u01;
p->uuid_bytes.uuid_bytes[2] = u02;
p->uuid_bytes.uuid_bytes[3] = u03;
p->uuid_bytes.uuid_bytes[4] = u04;
p->uuid_bytes.uuid_bytes[5] = u05;
p->uuid_bytes.uuid_bytes[6] = u06;
p->uuid_bytes.uuid_bytes[7] = u07;
p->uuid_bytes.uuid_bytes[8] = u08;
p->uuid_bytes.uuid_bytes[9] = u09;
p->uuid_bytes.uuid_bytes[10] = u10;
p->uuid_bytes.uuid_bytes[11] = u11;
p->uuid_bytes.uuid_bytes[12] = u12;
p->uuid_bytes.uuid_bytes[13] = u13;
p->uuid_bytes.uuid_bytes[14] = u14;
p->uuid_bytes.uuid_bytes[15] = u15;
return uuid;
}
b_uuid *b_uuid_create_from_bytev(const unsigned char bytes[B_UUID_NBYTES])
{
b_uuid *uuid = b_uuid_create();
if (!uuid) {
return NULL;
}
struct b_uuid_p *p = b_object_get_private(uuid, B_TYPE_UUID);
memcpy(p->uuid_bytes.uuid_bytes, bytes, B_UUID_NBYTES);
return uuid;
}
b_uuid *b_uuid_create_from_cstr(const char *str)
{
union b_uuid_bytes bytes;
bool valid = true;
bool is_guid = false;
if (*str == '{') {
is_guid = true;
str++;
}
size_t i, byte = 0;
for (i = 0; str[i] && byte < B_UUID_NBYTES;) {
if (i == 8 || i == 13 || i == 18 || i == 23) {
if (str[i] != '-') {
valid = false;
break;
}
i++;
continue;
}
char n[3];
n[0] = str[i];
n[1] = str[i + 1];
n[2] = '\0';
if (!isxdigit(n[0]) || !isxdigit(n[1])) {
valid = false;
break;
}
char *p;
unsigned long v = strtoul(n, &p, 16);
bytes.uuid_bytes[byte] = v;
byte++;
i += 2;
}
if (str[i] == '}') {
if (is_guid) {
i++;
} else {
valid = false;
}
}
if (str[i] != '\0' || byte != B_UUID_NBYTES) {
valid = false;
}
if (!valid) {
return NULL;
}
return b_uuid_create_from_uuid_bytes(&bytes);
}
b_status b_uuid_to_cstr(const b_uuid *uuid, char out[B_UUID_STRING_MAX])
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_to_cstr, uuid, out);
}
void b_uuid_get_bytes(const b_uuid *uuid, unsigned char bytes[B_UUID_NBYTES])
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_get_bytes, uuid, bytes);
}
void b_uuid_get_uuid_bytes(const b_uuid *uuid, union b_uuid_bytes *bytes)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_get_uuid_bytes, uuid, bytes);
}
union b_uuid_bytes *b_uuid_ptr(b_uuid *uuid)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_UUID, uuid_ptr, uuid);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
b_uuid *b_uuid_create_from_uuid_bytes(const union b_uuid_bytes *bytes)
{
return b_uuid_create_from_bytev(bytes->uuid_bytes);
}
b_uuid *b_uuid_create_from_string(const b_string *string)
{
return b_uuid_create_from_cstr(b_string_ptr(string));
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void uuid_init(b_object *obj, void *priv)
{
struct b_uuid_p *uuid = priv;
}
static void uuid_fini(b_object *obj, void *priv)
{
struct b_uuid_p *uuid = priv;
}
static void uuid_to_string(const b_object *uuid, b_stream *out)
{
char str[B_UUID_STRING_MAX];
b_uuid_to_cstr(uuid, str);
b_stream_write_string(out, str, NULL);
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_uuid)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = uuid_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_uuid)
B_TYPE_DEFINITION_BEGIN(b_uuid)
B_TYPE_ID(0x17037068, 0x92f7, 0x4582, 0xad1f, 0x0dea43b628de);
B_TYPE_CLASS(b_uuid_class);
B_TYPE_INSTANCE_PRIVATE(struct b_uuid_p);
B_TYPE_INSTANCE_INIT(uuid_init);
B_TYPE_INSTANCE_FINI(uuid_fini);
B_TYPE_DEFINITION_END(b_uuid)
+1
View File
@@ -0,0 +1 @@
export_fx_namespace_details(fx.cmdline)
+186
View File
@@ -0,0 +1,186 @@
#include "command.h"
#include <fx/cmd.h>
#include <fx/string.h>
#include <stdlib.h>
#include <string.h>
struct fx_command_arg *fx_command_arg_create(void)
{
struct fx_command_arg *out = malloc(sizeof *out);
if (!out) {
return out;
}
memset(out, 0x0, sizeof *out);
return out;
}
void fx_command_arg_destroy(struct fx_command_arg *arg)
{
if (arg->arg_name) {
free(arg->arg_name);
}
if (arg->arg_description) {
free(arg->arg_description);
}
if (arg->arg_allowed_values) {
for (unsigned int i = 0; arg->arg_allowed_values[i]; i++) {
free(arg->arg_allowed_values[i]);
}
free(arg->arg_allowed_values);
}
free(arg);
}
fx_status fx_command_arg_set_name(struct fx_command_arg *arg, const char *name)
{
char *n = fx_strdup(name);
if (!n) {
return FX_ERR_NO_MEMORY;
}
if (arg->arg_name) {
free(arg->arg_name);
arg->arg_name = NULL;
}
arg->arg_name = n;
return FX_SUCCESS;
}
fx_status fx_command_arg_set_description(
struct fx_command_arg *arg,
const char *description)
{
char *desc = fx_strdup(description);
if (!desc) {
return FX_ERR_NO_MEMORY;
}
if (arg->arg_description) {
free(arg->arg_description);
arg->arg_description = NULL;
}
arg->arg_description = desc;
return FX_SUCCESS;
}
fx_status fx_command_arg_set_nr_values(
struct fx_command_arg *arg,
enum fx_command_arg_value_count nr_values)
{
arg->arg_nr_values = nr_values;
return FX_SUCCESS;
}
fx_status fx_command_arg_set_allowed_values(
struct fx_command_arg *arg,
const char **allowed_values)
{
size_t count;
for (count = 0; allowed_values[count]; count++)
;
char **values = calloc(count + 1, sizeof *values);
if (!values) {
return FX_ERR_NO_MEMORY;
}
for (size_t i = 0; i < count; i++) {
values[i] = fx_strdup(allowed_values[i]);
if (!values[i]) {
/* TODO also free strings in `values` */
free(values);
return FX_ERR_NO_MEMORY;
}
}
arg->arg_allowed_values = values;
return FX_SUCCESS;
}
void z__fx_get_arg_usage_string(
struct fx_command_arg *arg,
bool colour,
fx_string *out)
{
bool optional = false, multi = false;
switch (arg->arg_nr_values) {
case FX_ARG_0_OR_1_VALUES:
optional = true;
multi = false;
break;
case FX_ARG_0_OR_MORE_VALUES:
optional = true;
multi = true;
break;
case FX_ARG_1_OR_MORE_VALUES:
optional = false;
multi = true;
break;
default:
optional = false;
multi = false;
break;
}
if (optional) {
fx_string_append_cstrf(
out,
colour ? F_GREEN "[[%s]" : "[[%s]",
arg->arg_name);
} else {
fx_string_append_cstrf(
out,
colour ? F_GREEN "<%s>" : "<%s>",
arg->arg_name);
}
for (int i = 1; i < arg->arg_nr_values; i++) {
fx_string_append_cstrf(out, " <%s>", arg->arg_name);
}
if (multi) {
fx_string_append_cstr(out, "...");
}
if (colour) {
fx_string_append_cstr(out, F_RESET);
}
}
void z__fx_get_arg_description(struct fx_command_arg *arg, fx_string *out)
{
if (arg->arg_description) {
fx_string_append_cstr(out, arg->arg_description);
}
if (!arg->arg_allowed_values) {
return;
}
if (arg->arg_description) {
fx_string_append_cstr(out, " ");
}
fx_string_append_cstr(out, "[[values:");
for (size_t i = 0; arg->arg_allowed_values[i]; i++) {
if (i > 0) {
fx_string_append_cstr(out, ",");
}
fx_string_append_cstrf(
out,
" " F_GREEN "%s" F_RESET,
arg->arg_allowed_values[i]);
}
fx_string_append_cstr(out, "]");
}
+1133
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More