Compare commits

80 Commits

Author SHA1 Message Date
wash c29465a97d build: re-enable namespace-specific tests 2026-05-05 21:17:21 +01:00
wash 4b20f8ca0e test: dynamic function call tests 2026-05-05 21:16:56 +01:00
wash f3062222cb fx: support for registering callable functions with types 2026-05-05 21:16:31 +01:00
wash 703155affe meta: update clang-format config 2026-05-05 19:03:31 +01:00
wash 90a3905f48 fx: re-arrange type system to allow for reflection 2026-05-05 19:03:22 +01:00
wash 8c12868651 fx: add simple cstr-based hashmap data structure 2026-05-05 12:38:34 +01:00
wash 2966934cd8 fx: add simple resizable array data structure 2026-05-05 12:38:12 +01:00
wash 9937546452 fx.reflection: remove fx_function_context 2026-05-04 22:56:21 +01:00
wash 5d98bc89a1 test: dynamic function argument bind test 2026-05-04 22:54:02 +01:00
wash b8e270b962 fx.reflection: function: implementing pre-binding argument values to functions 2026-05-04 22:53:45 +01:00
wash 3d1600ece6 fx: value: implement copy and unset functions 2026-05-04 22:53:23 +01:00
wash fe3af271e2 meta: update clang-format config 2026-05-04 22:53:03 +01:00
wash dea321acc2 fx.reflection: optimise darwin dynamic function calling 2026-05-04 20:44:02 +01:00
wash abe1603955 meta: update clang-format config 2026-05-04 19:42:37 +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
394 changed files with 31428 additions and 27272 deletions
+13 -71
View File
@@ -1,7 +1,5 @@
BasedOnStyle: WebKit
IndentWidth: 8
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
@@ -26,8 +24,8 @@ AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BinPackArguments: false
BinPackParameters: false
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
@@ -46,73 +44,17 @@ ReflowComments: true
SpacesBeforeTrailingComments: 3
TabWidth: 8
UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyExcessCharacter: 5
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
BreakAfterReturnType: Automatic
PenaltyBreakAssignment: 1000000
PenaltyReturnTypeOnItsOwnLine: 100000000
PenaltyExcessCharacter: 10000000
PenaltyBreakOpenParenthesis: 0
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyIndentedWhitespace: 0
AttributeMacros:
- BLUELIB_API
- FX_API
ForEachMacros:
- b_btree_foreach
- b_queue_foreach
MacroBlockBegin: "B_TYPE_.*_BEGIN"
MacroBlockEnd: "B_TYPE_.*_END"
---
Language: ObjC
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: true
BinPackParameters: true
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: 5
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- BLUELIB_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"
+34 -51
View File
@@ -1,70 +1,53 @@
cmake_minimum_required(VERSION 3.25)
project(bluelib C CXX)
project(fx C ASM)
include (TestBigEndian)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_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
core-mm ds-mm)
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 test/${module}/*.cpp)
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_cmdline)
FX_ASSEMBLY_NAME("fx.cmdline");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END(fx_cmdline)
+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_compression)
FX_ASSEMBLY_NAME("fx.compression");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END(fx_compression)
+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_io)
FX_ASSEMBLY_NAME("fx.io");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END(fx_io)
+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_runtime)
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(fx_runtime)
+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_serial)
FX_ASSEMBLY_NAME("fx.serial");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END(fx_serial)
+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_term)
FX_ASSEMBLY_NAME("fx.term");
FX_ASSEMBLY_VERSION(1, 0, 0, 0);
FX_ASSEMBLY_END(fx_term)
-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 -181
View File
@@ -1,222 +1,114 @@
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}")
foreach (ns ${arg_NAMESPACES})
file(GLOB test_sources ${fx_source_root}/${ns}/test/*.c)
foreach (test_file ${test_sources})
get_filename_component(test_name ${test_file} NAME_WE)
set(test_name ${ns}-${test_name})
string(REPLACE "." "-" test_name ${test_name})
add_executable(${test_name} ${test_file})
target_link_libraries(${test_name} ${assembly_target_name})
endforeach (test_file)
endforeach (ns)
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)
function(add_bluelib_mm_module)
set(options)
set(one_value_args NAME)
set(multi_value_args
DEPENDENCIES
SUBDIRS
EXTRA_SOURCES
LIBS
INCLUDE_DIRS
DEFINES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
macro(export_fx_namespace_details ns_name)
set(namespace_name ${ns_name})
set(short_module_name ${arg_NAME})
set(module_name ${arg_NAME}-mm)
string(REPLACE "." "/" namespace_path ${namespace_name})
set(namespace_target_name ${namespace_name})
file(GLOB sources
set(namespace_include_paths ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
file(GLOB base_namespace_sources
*.c *.h
*.cpp *.hpp)
${CMAKE_CURRENT_SOURCE_DIR}/include/${namespace_path}/*.h)
foreach (dir ${arg_SUBDIRS})
file(GLOB dir_sources
${dir}/*.c ${dir}/*.h
${dir}/*.cpp ${dir}/*.hpp)
set(sources ${sources} ${dir_sources})
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
sys/${b_system_name}/*.c sys/${b_system_name}/*.h
sys/${b_system_name}/*.cpp sys/${b_system_name}/*.hpp)
set(root_header include/blue/${short_module_name}.hpp)
file(GLOB headers include/blue/${short_module_name}/*.hpp)
string(REPLACE "-" "_" module_preproc_token ${short_module_name})
string(TOUPPER ${module_preproc_token} module_preproc_token)
set(module_preproc_token BLUELIB_${module_preproc_token})
message(STATUS "Building mm module ${short_module_name} (shared)")
add_library(blue-${module_name} SHARED
${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}
${root_header}
${headers}
${arg_EXTRA_SOURCES})
message(STATUS "Building mm module ${short_module_name} (static)")
add_library(blue-${module_name}-s STATIC
${sources}
${sys_sources}
${root_header}
${headers}
${arg_EXTRA_SOURCES})
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)
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}
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)
foreach (def ${arg_DEFINES})
target_compile_definitions(blue-${module_name} PRIVATE
${def})
target_compile_definitions(blue-${module_name}-s PRIVATE
${def})
endforeach (def)
set_target_properties(blue-${module_name} PROPERTIES
FOLDER "mm/Shared/${short_module_name}")
set_target_properties(blue-${module_name}-s PROPERTIES
FOLDER "mm/Static/${short_module_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
BIG_ENDIAN)
else()
target_compile_definitions(blue-${module_name} PRIVATE
LITTLE_ENDIAN)
target_compile_definitions(blue-${module_name}-s 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/${short_module_name})
endfunction(add_bluelib_mm_module)
-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
-6
View File
@@ -1,6 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_mm_module(
NAME core
DEPENDENCIES core
SUBDIRS hash)
-1
View File
@@ -1 +0,0 @@
#include <blue/core/encoding.hpp>
-106
View File
@@ -1,106 +0,0 @@
#ifndef BLUE_CORE_ENCODING_HPP_
#define BLUE_CORE_ENCODING_HPP_
#include <blue/core/encoding.h>
#include <cstddef>
#include <cstdint>
namespace blue::core
{
class wchar
{
public:
static const int32_t INVALID = B_WCHAR_INVALID;
wchar();
wchar(std::int32_t v)
: val_(v)
{
}
static wchar decode(const char *s);
operator int32_t() const
{
return val_;
}
bool is_alpha(void) const
{
return b_wchar_is_alpha(val_);
}
bool is_number(void) const
{
return b_wchar_is_number(val_);
}
bool is_bin_digit(void) const
{
return b_wchar_is_bin_digit(val_);
}
bool is_oct_digit(void) const
{
return b_wchar_is_oct_digit(val_);
}
bool is_hex_digit(void) const
{
return b_wchar_is_hex_digit(val_);
}
bool is_space(void) const
{
return b_wchar_is_space(val_);
}
bool is_alnum(void) const
{
return b_wchar_is_alnum(val_);
}
bool is_punct(void) const
{
return b_wchar_is_punct(val_);
}
bool is_valid_utf8_scalar(void) const
{
return b_wchar_utf8_is_valid_scalar(val_);
}
unsigned int get_utf8_codepoint_size(void) const
{
return b_wchar_utf8_codepoint_size(val_);
}
unsigned int encode_utf8(char s[4]) const
{
return b_wchar_utf8_codepoint_encode(val_, s);
}
private:
int32_t val_ = B_WCHAR_INVALID;
};
class utf8
{
public:
static unsigned int decode_header(char c)
{
return b_wchar_utf8_header_decode(c);
}
static unsigned int get_codepoint_stride(const char *s)
{
return b_wchar_utf8_codepoint_stride(s);
}
static std::size_t get_codepoint_count(const char *s, std::size_t nr_bytes)
{
return b_wchar_utf8_codepoint_count(s, nr_bytes);
}
static std::size_t get_string_encoded_size(
const wchar *s, std::size_t nr_codepoints)
{
return b_wchar_utf8_string_encoded_size(
reinterpret_cast<const b_wchar *>(s), nr_codepoints);
}
private:
utf8() = delete;
~utf8() = delete;
};
}
#endif
-13
View File
@@ -1,13 +0,0 @@
#ifndef BLUE_CORE_ITERATOR_HPP_
#define BLUE_CORE_ITERATOR_HPP_
#include <blue/core/object.hpp>
namespace blue::core
{
class iterator : public object
{
};
}
#endif
-46
View File
@@ -1,46 +0,0 @@
#ifndef BLUE_CORE_MISC_HPP_
#define BLUE_CORE_MISC_HPP_
#define Z__B_ENUM_CLASS_BITWISE_OPS(enum_name) \
inline constexpr enum_name operator&(enum_name x, enum_name y) \
{ \
return static_cast<enum_name>( \
static_cast<int>(x) & static_cast<int>(y)); \
} \
\
inline constexpr enum_name operator|(enum_name x, enum_name y) \
{ \
return static_cast<enum_name>( \
static_cast<int>(x) | static_cast<int>(y)); \
} \
\
inline constexpr enum_name operator^(enum_name x, enum_name y) \
{ \
return static_cast<enum_name>( \
static_cast<int>(x) ^ static_cast<int>(y)); \
} \
\
inline constexpr enum_name operator~(enum_name x) \
{ \
return static_cast<enum_name>(~static_cast<int>(x)); \
} \
\
inline enum_name &operator&=(enum_name &x, enum_name y) \
{ \
x = x & y; \
return x; \
} \
\
inline enum_name &operator|=(enum_name &x, enum_name y) \
{ \
x = x | y; \
return x; \
} \
\
inline enum_name &operator^=(enum_name &x, enum_name y) \
{ \
x = x ^ y; \
return x; \
}
#endif
-40
View File
@@ -1,40 +0,0 @@
#ifndef BLUE_CORE_OBJECT_HPP_
#define BLUE_CORE_OBJECT_HPP_
#include <blue/core/object.h>
namespace blue::core
{
class type;
class object
{
public:
static const size_t MAGIC = B_OBJECT_MAGIC;
object(object &) = delete;
object(object &&);
~object();
bool operator!()
{
return ptr_ == nullptr;
}
void to_string(void) const;
bool is_type(const type &type) const;
b_object *ptr(void)
{
return ptr_;
}
const b_object *ptr(void) const
{
return ptr_;
}
protected:
object() = default;
b_object *ptr_ = nullptr;
};
}
#endif
-62
View File
@@ -1,62 +0,0 @@
#ifndef BLUE_CORE_STATUS_HPP_
#define BLUE_CORE_STATUS_HPP_
#include <blue/core/status.h>
namespace blue
{
class status
{
public:
#define __MM_STATUS_ENUM(name) name = B_ERR_##name
enum _status : int {
SUCCESS = B_SUCCESS,
__MM_STATUS_ENUM(NO_MEMORY),
__MM_STATUS_ENUM(OUT_OF_BOUNDS),
__MM_STATUS_ENUM(INVALID_ARGUMENT),
__MM_STATUS_ENUM(NAME_EXISTS),
__MM_STATUS_ENUM(NOT_SUPPORTED),
__MM_STATUS_ENUM(BAD_STATE),
__MM_STATUS_ENUM(NO_ENTRY),
__MM_STATUS_ENUM(NO_DATA),
__MM_STATUS_ENUM(NO_SPACE),
__MM_STATUS_ENUM(UNKNOWN_FUNCTION),
__MM_STATUS_ENUM(BAD_FORMAT),
__MM_STATUS_ENUM(IO_FAILURE),
__MM_STATUS_ENUM(IS_DIRECTORY),
__MM_STATUS_ENUM(NOT_DIRECTORY),
__MM_STATUS_ENUM(PERMISSION_DENIED),
__MM_STATUS_ENUM(BUSY),
__MM_STATUS_ENUM(COMPRESSION_FAILURE),
__MM_STATUS_ENUM(TYPE_REGISTRATION_FAILURE),
__MM_STATUS_ENUM(CLASS_INIT_FAILURE),
};
status() = default;
status(_status v)
: v_(static_cast<b_status>(v))
{
}
status(b_status v)
: v_(v)
{
}
bool operator!() const
{
return v_ != B_SUCCESS;
}
operator b_status() const
{
return v_;
}
const char *to_string(void);
const char *description(void);
private:
b_status v_ = B_SUCCESS;
};
}
#endif
-135
View File
@@ -1,135 +0,0 @@
#ifndef BLUE_CORE_STREAM_HPP_
#define BLUE_CORE_STREAM_HPP_
#include <blue/core/encoding.hpp>
#include <blue/core/misc.hpp>
#include <blue/core/object.hpp>
#include <blue/core/status.hpp>
#include <blue/core/stream.h>
#include <blue/core/type.hpp>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <string>
namespace blue::core
{
class stream_buffer : public object
{
};
class stream : public object
{
public:
enum class mode : int {
READ = B_STREAM_READ,
WRITE = B_STREAM_WRITE,
BINARY = B_STREAM_BINARY,
__STATIC = Z__B_STREAM_STATIC,
};
enum class seek_origin : int {
START = B_STREAM_SEEK_START,
CURRENT = B_STREAM_SEEK_CURRENT,
END = B_STREAM_SEEK_END,
};
static type get_type(void);
static stream &in(void);
static stream &out(void);
static stream &err(void);
stream(stream &) = delete;
stream(std::FILE *fp);
status reserve(std::size_t len);
status seek(long long offset, seek_origin origin);
std::size_t cursor(void) const;
status push_indent(int indent);
status pop_indent(void);
status read_char(wchar &c);
status read_bytes(void *buf, std::size_t count, std::size_t &nr_read);
status read_bytes(void *buf, std::size_t count)
{
std::size_t tmp;
return read_bytes(buf, count, tmp);
}
status read_line(char *s, std::size_t max);
status read_line(std::string &out);
status read_line(stream &dest);
status read_all_bytes(void *p, std::size_t max, std::size_t &nr_read);
status read_all_bytes(
stream &dest, stream_buffer &buf, std::size_t &nr_read);
status read_all_bytes(void *p, std::size_t max)
{
std::size_t tmp;
return read_all_bytes(p, max);
}
status read_all_bytes(stream &dest, stream_buffer &buf)
{
std::size_t tmp;
return read_all_bytes(dest, buf);
}
status write_char(wchar c);
status write_string(const char *s, std::size_t &nr_written);
status write_string(const char *s)
{
std::size_t tmp;
return write_string(s, tmp);
}
status write_string(const std::string &s, std::size_t &nr_written)
{
return write_string(s.c_str(), nr_written);
}
status write_string(const std::string &s)
{
std::size_t tmp;
return write_string(s, tmp);
}
status write_bytes(
const void *buf, std::size_t count, std::size_t &nr_written);
status write_bytes(const void *buf, std::size_t count)
{
std::size_t tmp;
return write_bytes(buf, count, tmp);
}
status write_fmt(std::size_t &nr_written, const char *format, ...);
status write_vfmt(
std::size_t &nr_written, const char *format, std::va_list arg);
status write_fmt(const char *format, ...)
{
std::size_t tmp;
std::va_list arg;
va_start(arg, format);
status s = write_vfmt(tmp, format, arg);
va_end(arg);
return s;
}
status write_vfmt(const char *format, std::va_list arg)
{
std::size_t tmp;
return write_vfmt(tmp, format, arg);
}
protected:
stream() = default;
};
}
Z__B_ENUM_CLASS_BITWISE_OPS(blue::core::stream::mode)
#endif
@@ -1,23 +0,0 @@
#ifndef BLUE_CORE_STRINGSTREAM_HPP_
#define BLUE_CORE_STRINGSTREAM_HPP_
#include <blue/core/stream.hpp>
namespace blue::core
{
class stringstream : public stream
{
public:
stringstream();
stringstream(char *buf, std::size_t max);
status reset();
status reset(char *buf, std::size_t max);
const char *get_ptr() const;
char *steal_ptr();
std::size_t get_length() const;
};
}
#endif
-24
View File
@@ -1,24 +0,0 @@
#ifndef BLUE_CORE_TYPE_HPP_
#define BLUE_CORE_TYPE_HPP_
#include <blue/core/type.h>
namespace blue::core
{
class type
{
public:
type(b_type p)
{
ptr_ = p;
}
~type() = default;
type(type &) = default;
private:
const union b_type_id *ptr_;
};
}
#endif
-1
View File
@@ -1 +0,0 @@
#include <blue/core/iterator.hpp>
-20
View File
@@ -1,20 +0,0 @@
#include <blue/core/object.hpp>
namespace blue::core
{
object::object(object &&other)
{
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
object::~object()
{
if (ptr_) {
b_object_unref(ptr_);
ptr_ = nullptr;
}
}
}
-169
View File
@@ -1,169 +0,0 @@
#include <blue/core/stream.h>
#include <blue/core/stream.hpp>
namespace blue::core
{
type stream::get_type(void)
{
return b_stream_get_type();
}
stream &stream::in(void)
{
static stream s;
s.ptr_ = b_stdin;
return s;
}
stream &stream::out(void)
{
static stream s;
s.ptr_ = b_stdout;
return s;
}
stream &stream::err(void)
{
static stream s;
s.ptr_ = b_stderr;
return s;
}
stream::stream(std::FILE *fp)
{
ptr_ = b_stream_open_fp(fp);
}
status stream::reserve(std::size_t len)
{
return b_stream_reserve(ptr_, len);
}
status stream::seek(long long offset, seek_origin origin)
{
return b_stream_seek(
ptr_, offset, static_cast<b_stream_seek_origin>(origin));
}
std::size_t stream::cursor(void) const
{
return b_stream_cursor(ptr_);
}
status stream::push_indent(int indent)
{
return b_stream_push_indent(ptr_, indent);
}
status stream::pop_indent(void)
{
return b_stream_pop_indent(ptr_);
}
status stream::read_char(wchar &c)
{
b_wchar tmp;
status s = b_stream_read_char(ptr_, &tmp);
c = tmp;
return s;
}
status stream::read_bytes(void *buf, std::size_t count, std::size_t &nr_read)
{
std::size_t r;
status s = b_stream_read_bytes(ptr_, buf, count, &r);
nr_read = r;
return s;
}
status stream::read_line(char *s, std::size_t max)
{
return b_stream_read_line(ptr_, s, max);
}
status stream::read_line(std::string &out)
{
while (1) {
wchar c = wchar::INVALID;
status s = read_char(c);
if (!s) {
return s;
}
if (c == '\n') {
break;
}
char str[5] = {0};
c.encode_utf8(str);
out.append(str);
}
return status::SUCCESS;
}
status stream::read_line(stream &dest)
{
return b_stream_read_line_s(ptr_, dest.ptr_);
}
status stream::read_all_bytes(void *p, std::size_t max, std::size_t &nr_read)
{
std::size_t tmp;
status s = b_stream_read_all_bytes(ptr_, p, max, &tmp);
nr_read = tmp;
return s;
}
status stream::read_all_bytes(stream &dest, stream_buffer &buf, std::size_t &nr_read)
{
std::size_t tmp;
status s = b_stream_read_all_bytes_s(ptr_, dest.ptr_, buf.ptr(), &tmp);
nr_read = tmp;
return s;
}
status stream::write_char(wchar c)
{
return b_stream_write_char(ptr_, c);
}
status stream::write_string(const char *str, std::size_t &nr_written)
{
std::size_t tmp;
status s = b_stream_write_string(ptr_, str, &tmp);
nr_written = tmp;
return s;
}
status stream::write_bytes(
const void *buf, std::size_t count, std::size_t &nr_written)
{
std::size_t tmp;
status s = b_stream_write_bytes(ptr_, buf, count, &tmp);
nr_written = tmp;
return s;
}
status stream::write_fmt(std::size_t &nr_written, const char *format, ...)
{
size_t tmp;
std::va_list arg;
va_start(arg, format);
status s = b_stream_write_vfmt(ptr_, &tmp, format, arg);
va_end(arg);
nr_written = tmp;
return s;
}
status stream::write_vfmt(std::size_t &nr_written, const char *format, va_list arg)
{
size_t tmp;
status s = b_stream_write_vfmt(ptr_, &tmp, format, arg);
nr_written = tmp;
return s;
}
}
-42
View File
@@ -1,42 +0,0 @@
#include <blue/core/stringstream.h>
#include <blue/core/stringstream.hpp>
namespace blue::core
{
stringstream::stringstream()
{
ptr_ = b_stringstream_create();
}
stringstream::stringstream(char *buf, std::size_t max)
{
ptr_ = b_stringstream_create_with_buffer(buf, max);
}
status stringstream::reset()
{
return b_stringstream_reset(ptr_);
}
status stringstream::reset(char *buf, std::size_t max)
{
return b_stringstream_reset_with_buffer(ptr_, buf, max);
}
const char *stringstream::get_ptr() const
{
return b_stringstream_ptr(ptr_);
}
char *stringstream::steal_ptr()
{
return b_stringstream_steal(ptr_);
}
std::size_t stringstream::get_length() const
{
return b_stringstream_get_length(ptr_);
}
}
-1
View File
@@ -1 +0,0 @@
#include <blue/core/type.hpp>
-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 *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
View File
-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
-45
View File
@@ -1,45 +0,0 @@
#ifndef BLUE_CORE_ENCODING_H_
#define BLUE_CORE_ENCODING_H_
#include <blue/core/misc.h>
#include <stdbool.h>
#include <stdint.h>
B_DECLS_BEGIN;
#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);
B_DECLS_END;
#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
-192
View File
@@ -1,192 +0,0 @@
#ifndef BLUE_CORE_MACROS_H_
#define BLUE_CORE_MACROS_H_
#include <blue/core/class.h>
#include <blue/core/misc.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)
#define B_STRUCT_EMPTY char _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)
#endif
-126
View File
@@ -1,126 +0,0 @@
#ifndef BLUE_CORE_MISC_H_
#define BLUE_CORE_MISC_H_
#include <stddef.h>
#include <stdint.h>
#ifndef _Nonnull
#define _Nonnull
#endif
#ifdef __cplusplus
#define B_DECLS_BEGIN extern "C" {
#define B_DECLS_END }
#else
#define B_DECLS_BEGIN
#define B_DECLS_END
#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_
-43
View File
@@ -1,43 +0,0 @@
#ifndef BLUE_CORE_OBJECT_H_
#define BLUE_CORE_OBJECT_H_
#include <blue/core/misc.h>
#include <blue/core/type.h>
B_DECLS_BEGIN;
#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);
B_DECLS_END;
#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
-101
View File
@@ -1,101 +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_STRUCT_EMPTY;
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
-36
View File
@@ -1,36 +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_STRUCT_EMPTY;
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
-70
View File
@@ -1,70 +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>
B_DECLS_BEGIN;
#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_id {
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_id t_id;
union b_type_id t_parent_id;
const char *t_name;
b_type_flags t_flags;
union b_type_id 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_id *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_id *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_id));
}
BLUE_API b_result b_type_register(b_type_info *info);
B_DECLS_END;
#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_id 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_id *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_id *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_id *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_id *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_id *key);
#endif
-5
View File
@@ -1,5 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_mm_module(
NAME ds
DEPENDENCIES core-mm ds)
View File
View File
-63
View File
@@ -1,63 +0,0 @@
#ifndef BLUE_DS_STRING_HPP_
#define BLUE_DS_STRING_HPP_
#include <blue/core/encoding.hpp>
#include <blue/core/object.hpp>
#include <blue/core/status.hpp>
#include <blue/core/stringstream.hpp>
#include <cstddef>
namespace blue::ds
{
class string : public core::object
{
public:
core::type get_type(void);
string();
string(const char *s);
string(const core::wchar *s);
string(char c, std::size_t count);
char *steal(void);
status reserve(size_t capacity);
status replace(size_t start, size_t len, const char *new_data);
status replace(const char *new_data);
status replace(const core::stringstream &new_data);
status remove(size_t start, size_t len);
status transform(int (*transformer)(int));
status trim(void);
status toupper(void)
{
return transform(::toupper);
}
status tolower(void)
{
return transform(::tolower);
}
status append(char c);
status append(core::wchar c);
status append(const string &s);
status append(const core::wchar *s);
status append(const char *format, ...);
status prepend(char c);
status prepend(core::wchar c);
status prepend(const char *s);
status prepend(const core::wchar *s);
status prepend(const char *format, ...);
status insert(char c, std::size_t at);
status insert(core::wchar c, std::size_t at);
status insert(const string &s, std::size_t at);
status insert(const char *s, std::size_t at);
status insert(const core::wchar *s, std::size_t at);
status insert(std::size_t at, const char *format, ...);
void clear(void);
};
}
#endif
View File
-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)

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