Compare commits

107 Commits

Author SHA1 Message Date
wash 5ead9118b3 build: add module to handle querying platform details 2026-05-05 21:31:12 +01:00
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
wash 84df46489a meta: update clang-format config 2026-02-03 14:47:36 +00:00
wash 0d5a186d80 test: core: add bstr tests; update rope tests 2026-02-03 14:47:25 +00:00
wash 2632feac32 cmd: add support for dynamically generating command options at runtime 2026-02-03 14:46:40 +00:00
wash f5c4fa561f ds: uuid: convert uuid bytes struct to union 2026-02-03 14:45:30 +00:00
wash 5639aefd61 ds: string: set iterator value to B_WCHAR_INVALID when end of string is reached 2026-02-03 14:44:36 +00:00
wash 30a9db17dc ds: list: update iterator interface 2026-02-03 14:43:35 +00:00
wash ce50cfd18b ds: hashmap: update iterator interface 2026-02-03 14:43:17 +00:00
wash 9b48fc2b45 ds: convert (stub) bitbuffer implementation to (stub) b_object sub-class 2026-02-03 14:42:05 +00:00
wash 5889426478 core: rope: add bstr support 2026-02-03 14:39:33 +00:00
wash c13b7a7e3a core: stream: add bstr support
despite not being a b_object, the b_stream interface can now detect when
a b_bstr instance has been passed as a stream parameter and use the correct
functions to handle writing to it.

this allows any function that expects a b_stream parameter to be called
with a b_bstr instance instead, allowing complex stream-based I/O operations
to be directed towards bounded character arrays with no heap allocation
required.
2026-02-03 14:36:48 +00:00
wash 23aba2a27f core: add bstr data structure
bstr is very similar to b_stringstream, with the key difference being it can be
stack-allocated. this allows you to write a complex formatted string to a
stack-allocated character buffer with no heap memory allocation required.
bstr also supports automatically-managed dynamic string buffers for unbounded
string construction.
2026-02-03 14:34:58 +00:00
wash bdcd4163c7 core: stringstream: added read-support
any characters written to a stringstream can be optionally read back again
using the b_stream read API.

this functions similar to a ringbuffer, with two key differences:
 1) the buffer is not circular, and will continuously expand to accomodate all incoming data.
 2) reading data from the stringstream does not remove it from the buffer.
2026-02-03 14:33:06 +00:00
wash add05ef478 core: iterator: added inline definition of is_valid() 2026-02-03 14:32:15 +00:00
wash 68ab79fe2a core: hash: add support for hashing the contents of ropes 2026-02-03 14:31:35 +00:00
wash ce9195c130 core: queue: implement moving queue entries
this works exactly the same as moving btree nodes.
2026-02-03 14:30:53 +00:00
wash 837a42e249 core: btree: implement moving btree nodes
moving a btree node is similar to simply using memmove() or memcpy(), with the added
bonus of updating the pointers in the wider data structure to the new node memory
and zeroing the old node memory so that it isn't used accidentally after the move
is complete.
2026-02-03 14:28:58 +00:00
wash d14a1fc61f io: directory: update error api usage 2025-11-04 10:03:21 +00:00
wash 6b65727535 core: error: rename b_error_release to b_error_discard 2025-11-04 10:03:10 +00:00
wash 5c6030488b test: fix some memory leaks 2025-11-03 21:29:59 +00:00
wash bd2fe50ec9 test: move all module tests to the test/ directory 2025-11-01 10:12:18 +00:00
wash a68b9f7ba7 test: update tests 2025-11-01 10:04:41 +00:00
wash 9e21e0c4b2 serial: toml: update iterator usage 2025-11-01 10:04:28 +00:00
wash 5d3a987b0e io: directory: implement new b_iterator interface 2025-11-01 10:03:59 +00:00
wash ec500c04ad cmd: remove internal usage of legacy iterator interface 2025-11-01 10:02:42 +00:00
wash c94f976751 ds: string: implement b_iterable interface 2025-11-01 10:01:59 +00:00
wash 3db808d4c4 ds: array: fix iterable_begin not setting iterator status 2025-11-01 10:01:17 +00:00
374 changed files with 31831 additions and 25639 deletions
+13 -14
View File
@@ -1,10 +1,7 @@
BasedOnStyle: WebKit BasedOnStyle: WebKit
IndentWidth: 8 IndentWidth: 8
---
Language: Cpp
DerivePointerAlignment: false DerivePointerAlignment: false
PointerAlignment: Right PointerAlignment: Right
ReferenceAlignment: Left
ColumnLimit: 80 ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None AlignConsecutiveAssignments: None
@@ -27,8 +24,8 @@ AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true BinPackArguments: false
BinPackParameters: true BinPackParameters: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both BitFieldColonSpacing: Both
BreakBeforeBraces: Linux BreakBeforeBraces: Linux
@@ -47,15 +44,17 @@ ReflowComments: true
SpacesBeforeTrailingComments: 3 SpacesBeforeTrailingComments: 3
TabWidth: 8 TabWidth: 8
UseTab: AlignWithSpaces UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000 BreakAfterReturnType: Automatic
PenaltyExcessCharacter: 5 PenaltyBreakAssignment: 1000000
PenaltyBreakOpenParenthesis: 5 PenaltyReturnTypeOnItsOwnLine: 100000000
PenaltyBreakBeforeFirstCallParameter: 5 PenaltyExcessCharacter: 10000000
PenaltyBreakOpenParenthesis: 0
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyIndentedWhitespace: 0 PenaltyIndentedWhitespace: 0
AttributeMacros: AttributeMacros:
- BLUE_API - FX_API
ForEachMacros: ForEachMacros:
- b_btree_foreach - fx_btree_foreach
- b_queue_foreach - fx_queue_foreach
MacroBlockBegin: "^B_(TYPE|PARAM)_.*_BEGIN$" MacroBlockBegin: "FX_(TYPE|ASSEMBLY).*_BEGIN"
MacroBlockEnd: "^B_(TYPE|PARAM)_.*_END$" MacroBlockEnd: "FX_(TYPE|ASSEMBLY).*_END"
+35 -49
View File
@@ -1,66 +1,52 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(bluelib C) project(fx C ASM)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
include (TestBigEndian) include (TestBigEndian)
include(Templates)
include(Platform)
set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(b_modules core ds serial term cmd io compress) set(fx_source_root ${CMAKE_CURRENT_SOURCE_DIR})
set(fx_build_root ${CMAKE_CURRENT_BINARY_DIR})
file(GLOB _all_assemblies assemblies/*
LIST_DIRECTORIES TRUE)
set(b_system_name ${CMAKE_SYSTEM_NAME}) foreach (assembly_path ${_all_assemblies})
string(TOLOWER ${b_system_name} b_system_name) 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}")
get_platform_details(
SYSTEM fx_system_name
PROCESSOR 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_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_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) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
foreach (module ${b_modules}) foreach (assembly ${fx_assemblies})
add_subdirectory(${module}) add_subdirectory(assemblies/${assembly})
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${module}-test) endforeach (assembly)
message(STATUS "Building unit tests for module ${module}")
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${module}-test/${module}-units.c) add_subdirectory(test)
add_executable(blue-${module}-units
${module}-test/${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}")
endif ()
file(GLOB test_sources ${module}-test/*.c)
list(REMOVE_ITEM test_sources "${CMAKE_CURRENT_SOURCE_DIR}/${module}-test/${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)
+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()
+36
View File
@@ -0,0 +1,36 @@
function(get_platform_details)
set(options)
set(one_value_args SYSTEM PROCESSOR)
set(multi_value_args
NAMESPACES
DEPENDENCIES
LIBS)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(system_name "")
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(system_name "linux")
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set(system_name "apple")
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
set(system_name "win32")
else ()
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif ()
if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
set(system_arch "amd64")
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64")
set(system_arch "aarch64")
else ()
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif ()
set(${arg_SYSTEM} ${system_name} PARENT_SCOPE)
set(${arg_PROCESSOR} ${system_arch} PARENT_SCOPE)
endfunction (get_platform_details)
+84 -77
View File
@@ -1,107 +1,114 @@
function(add_bluelib_module) function(add_fx_assembly)
set(options) set(options)
set(one_value_args NAME) set(one_value_args NAME)
set(multi_value_args set(multi_value_args
NAMESPACES
DEPENDENCIES DEPENDENCIES
SUBDIRS LIBS)
EXTRA_SOURCES
LIBS
INCLUDE_DIRS
DEFINES)
cmake_parse_arguments(PARSE_ARGV 0 arg cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}" "${options}"
"${one_value_args}" "${one_value_args}"
"${multi_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}) foreach (dir ${arg_NAMESPACES})
file(GLOB dir_sources ${dir}/*.c ${dir}/*.h) add_subdirectory(${fx_source_root}/${dir} ${fx_build_root}/namespaces/${dir})
set(sources ${sources} ${dir_sources}) set(assembly_sources ${assembly_sources} ${namespace_sources})
set(assembly_include_paths ${assembly_include_paths} ${namespace_include_paths})
endforeach (dir) endforeach (dir)
file(GLOB sys_sources sys/${b_system_name}/*.c sys/${b_system_name}/*.h) message(STATUS "Building assembly ${assembly_name}")
set(root_header include/blue/${module_name}.h) add_library(${assembly_target_name} SHARED
file(GLOB headers include/blue/${module_name}/*.h) ${assembly_sources})
string(REPLACE "-" "_" module_preproc_token ${module_name}) target_include_directories(${assembly_target_name} PUBLIC ${assembly_include_paths})
string(TOUPPER ${module_preproc_token} module_preproc_token)
set(module_preproc_token BLUELIB_${module_preproc_token})
message(STATUS "Building module ${module_name} (shared)") target_compile_definitions(${assembly_target_name} PUBLIC
add_library(blue-${module_name} SHARED FX_EXPORT=1
${sources} FX_ENABLE_FLOATING_POINT=${fx_enable_floating_point})
${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_include_directories(blue-${module_name} PUBLIC include/) set_target_properties(${assembly_target_name}
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) PROPERTIES POSITION_INDEPENDENT_CODE ON)
foreach (dep ${arg_DEPENDENCIES}) target_link_libraries(${assembly_target_name} ${internal_libs} ${arg_DEPENDENCIES})
target_link_libraries(blue-${module_name} blue-${dep}) target_include_directories(${assembly_target_name} PRIVATE ${internal_include_dirs})
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}) foreach (def ${arg_DEFINES})
target_compile_definitions(blue-${module_name} PRIVATE target_compile_definitions(${assembly_target_name} PRIVATE ${def})
${def})
target_compile_definitions(blue-${module_name}-s PRIVATE
${def})
endforeach (def) endforeach (def)
set_target_properties(blue-${module_name} PROPERTIES foreach (ns ${arg_NAMESPACES})
FOLDER "Shared/${module_name}") file(GLOB test_sources ${fx_source_root}/${ns}/test/*.c)
set_target_properties(blue-${module_name}-s PROPERTIES foreach (test_file ${test_sources})
FOLDER "Static/${module_name}") 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) TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN) if(IS_BIG_ENDIAN)
target_compile_definitions(blue-${module_name} PRIVATE target_compile_definitions(${assembly_target_name} PRIVATE
BIG_ENDIAN)
target_compile_definitions(blue-${module_name}-s PRIVATE
BIG_ENDIAN) BIG_ENDIAN)
else() else()
target_compile_definitions(blue-${module_name} PRIVATE target_compile_definitions(${assembly_target_name} PRIVATE
LITTLE_ENDIAN)
target_compile_definitions(blue-${module_name}-s PRIVATE
LITTLE_ENDIAN) LITTLE_ENDIAN)
endif() endif()
install(TARGETS blue-${module_name} blue-${module_name}-s) install(TARGETS ${assembly_target_name})
install(FILES ${root_header} DESTINATION include/blue) install(FILES ${headers} DESTINATION include/${assembly_path})
install(FILES ${headers} DESTINATION include/blue/${module_name}) endfunction(add_fx_assembly)
endfunction(add_bluelib_module)
macro(export_fx_namespace_details ns_name)
set(namespace_name ${ns_name})
string(REPLACE "." "/" namespace_path ${namespace_name})
set(namespace_target_name ${namespace_name})
set(namespace_include_paths ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
file(GLOB base_namespace_sources
*.c *.h
${CMAKE_CURRENT_SOURCE_DIR}/include/${namespace_path}/*.h)
foreach (dir ${source_dirs})
file(GLOB dir_sources ${dir}/*.c ${dir}/*.h)
set(dir_namespace_sources ${dir_namespace_sources} ${dir_sources})
endforeach (dir)
file(GLOB sys_sources
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.h
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.S)
file(GLOB headers include/${namespace_path}/*.h)
set(namespace_sources
${namespace_sources}
${base_namespace_sources}
${dir_namespace_sources}
${sys_sources}
${headers}
PARENT_SCOPE)
set(internal_include_dirs
${internal_include_dirs}
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/include
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/include
PARENT_SCOPE)
set(internal_libs ${internal_libs} PARENT_SCOPE)
set(internal_defines ${internal_defines} PARENT_SCOPE)
endmacro(export_fx_namespace_details)
-175
View File
@@ -1,175 +0,0 @@
#include <blue/cmd.h>
#include <stdio.h>
enum {
CMD_TEST,
CMD_SUB,
OPT_NAME,
OPT_NAME_VALUE,
OPT_OTHER,
OPT_OTHER_VALUE,
OPT_VERBOSE,
OPT_REALLY_VERBOSE,
OPT_MODE,
OPT_MODE_VALUE,
OPT_MODE_VALUE2,
ARG_FILE,
ARG_MORE,
};
const char *text
= "No one rejects, dislikes, or avoids pleasure itself, because it is "
"pleasure, but because those who do not know how to pursue pleasure "
"rationally encounter consequences that are extremely painful. Nor "
"again is there anyone who loves or pursues or desires to obtain "
"pain of itself, because it is pain, but because occasionally "
"circumstances occur in which toil and pain can procure him some "
"great pleasure.";
static int test_command(
const b_command *self, const b_arglist *opt, const b_array *args)
{
printf("Hello, world!\n");
b_arglist_iterator it;
b_arglist_iterator_begin(
opt, B_COMMAND_INVALID_ID, B_COMMAND_INVALID_ID, &it);
while (b_arglist_iterator_is_valid(&it)) {
printf("opt:%u,arg:%u,i:%zu,value: %s\n", it.opt_id,
it.value->val_id, it.i, it.value->val_str);
b_arglist_iterator_next(&it);
}
return 0;
}
B_COMMAND(CMD_TEST, B_COMMAND_INVALID_ID)
{
B_COMMAND_NAME("test");
B_COMMAND_DESC("A test command.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(test_command);
B_COMMAND_OPTION(OPT_NAME)
{
B_OPTION_LONG_NAME("name");
B_OPTION_SHORT_NAME('n');
B_OPTION_DESC("The name of the data.");
B_OPTION_ARG(OPT_NAME_VALUE)
{
B_ARG_NAME("name");
B_ARG_NR_VALUES(2);
}
}
B_COMMAND_OPTION(OPT_OTHER)
{
B_OPTION_LONG_NAME("other");
B_OPTION_DESC(text);
B_OPTION_ARG(OPT_OTHER_VALUE)
{
B_ARG_NAME("value");
B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES);
}
}
B_COMMAND_OPTION(OPT_VERBOSE)
{
B_OPTION_LONG_NAME("verbose");
B_OPTION_SHORT_NAME('v');
B_OPTION_DESC("Show detailed log output.");
}
B_COMMAND_OPTION(OPT_REALLY_VERBOSE)
{
B_OPTION_LONG_NAME("really-verbose");
B_OPTION_SHORT_NAME('V');
B_OPTION_DESC("Show REALLY detailed log output.");
}
B_COMMAND_OPTION(OPT_MODE)
{
B_OPTION_SHORT_NAME('m');
B_OPTION_LONG_NAME("mode");
B_OPTION_DESC("modes to operate in.");
B_OPTION_ARG(OPT_MODE_VALUE)
{
B_ARG_NAME("mode");
B_ARG_NR_VALUES(1);
B_ARG_ALLOWED_VALUES("fast", "slow");
}
B_OPTION_ARG(OPT_MODE_VALUE2)
{
B_ARG_NAME("mode2");
B_ARG_NR_VALUES(1);
B_ARG_ALLOWED_VALUES("very-fast", "very-slow");
}
}
B_COMMAND_ARG(ARG_FILE)
{
B_ARG_NAME("file");
B_ARG_DESC("The file(s) to use");
B_ARG_NR_VALUES(2);
}
B_COMMAND_ARG(ARG_MORE)
{
B_ARG_NAME("more");
B_ARG_DESC("More args to use");
B_ARG_ALLOWED_VALUES("how", "wow");
B_ARG_NR_VALUES(2);
}
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_NAME);
B_COMMAND_USAGE_ARG(ARG_FILE);
B_COMMAND_USAGE_ARG(ARG_MORE);
}
}
B_COMMAND(CMD_SUB, CMD_TEST)
{
B_COMMAND_NAME("sub");
B_COMMAND_LONG_NAME("sub");
B_COMMAND_SHORT_NAME('S');
B_COMMAND_DESC("A test subcommand");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(test_command);
B_COMMAND_OPTION(OPT_NAME)
{
B_OPTION_LONG_NAME("name");
B_OPTION_SHORT_NAME('n');
B_OPTION_DESC("The name of the data");
B_OPTION_ARG(OPT_NAME_VALUE)
{
B_ARG_NAME("name");
}
}
B_COMMAND_OPTION(OPT_OTHER)
{
B_OPTION_LONG_NAME("other");
B_OPTION_SHORT_NAME('o');
B_OPTION_DESC("The other argument");
B_OPTION_ARG(OPT_OTHER_VALUE)
{
B_ARG_NAME("value");
}
}
B_COMMAND_HELP_OPTION();
}
int main(int argc, const char **argv)
{
return b_command_dispatch(CMD_TEST, argc, argv);
}
-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, "]");
}
-1097
View File
File diff suppressed because it is too large Load Diff
-1009
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
-280
View File
@@ -1,280 +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_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 {
b_iterator _base;
size_t i;
unsigned int opt_id;
struct b_arglist_value *value;
b_btree_iterator _opt_it, _arg_it;
unsigned int _opt_filter, _arg_filter;
} b_arglist_iterator;
typedef struct b_arglist_option_iterator {
b_iterator _base;
size_t i;
unsigned int opt_id;
struct b_arglist_option *opt;
b_btree_iterator _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 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
-251
View File
@@ -1,251 +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);
}
b_queue_iterator it = {0};
b_queue_iterator_begin(&opt->opt_args, &it);
while (b_queue_iterator_is_valid(&it)) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry);
if (!arg) {
break;
}
b_queue_iterator_erase(&it);
b_command_arg_destroy(arg);
}
free(opt);
}
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;
b_queue_iterator it;
b_queue_foreach (&it, &opt->opt_args) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry);
if (!arg || !arg->arg_allowed_values) {
continue;
}
if (it.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]);
}
}
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, "}");
}
b_queue_iterator it;
b_queue_foreach (&it, &opt->opt_args) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry);
if (!arg) {
continue;
}
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);
}
}
}
struct b_command_arg *b_command_option_get_arg_with_id(
struct b_command_option *opt, unsigned int id)
{
b_queue_iterator it;
b_queue_foreach (&it, &opt->opt_args) {
struct b_command_arg *arg
= b_unbox(struct b_command_arg, it.entry, arg_entry);
if (!arg) {
continue;
}
if (arg->arg_id == id) {
return arg;
}
}
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;
}
-76
View File
@@ -1,76 +0,0 @@
#include <assert.h>
#include <blue/compress/compressor.h>
#include <blue/compress/cstream.h>
#include <blue/compress/zstd.h>
#include <blue/core/ringbuffer.h>
#include <blue/core/stream.h>
#include <stdio.h>
#include <string.h>
int main(int argc, const char **argv)
{
if (argc < 2) {
fprintf(stderr, "usage: %s <inpath>\n", argv[0]);
return -1;
}
b_compressor_mode mode = B_COMPRESSOR_MODE_DECOMPRESS;
FILE *in_fp = fopen(argv[1], "rb");
if (!in_fp) {
fprintf(stderr, "cannot open input file %s\n", argv[1]);
return -1;
}
b_stream *in_stream = b_stream_open_fp(in_fp);
b_cstream *cstream;
b_cstream_open(in_stream, B_TYPE_ZSTD_COMPRESSOR, mode, &cstream);
bool compressed = false;
char buf[513];
for (int i = 0;; i++) {
if (compressed) {
b_cstream_begin_compressed_section(cstream, NULL);
}
memset(buf, 0x0, sizeof buf);
size_t nr_read = 0;
b_status status
= b_cstream_read(cstream, buf, sizeof buf - 1, &nr_read);
if (!B_OK(status)) {
fprintf(stderr, "write error: %s\n",
b_status_description(status));
break;
}
if (nr_read == 0) {
break;
}
size_t nr_read_compressed = 0;
if (compressed) {
b_cstream_end_compressed_section(
cstream, &nr_read_compressed, &nr_read);
}
size_t tx_total = 0;
b_cstream_tx_bytes(cstream, &tx_total);
printf(" * iteration %d: read %zu (compressed) / %zu "
"(uncompressed) / %zu (total) bytes (%s)\n",
i, nr_read_compressed, nr_read, tx_total,
compressed ? "compressed" : "uncompressed");
printf("%s\n", buf);
compressed = !compressed;
}
printf("Done\n");
b_cstream_unref(cstream);
b_stream_unref(in_stream);
fclose(in_fp);
return 0;
}
-143
View File
@@ -1,143 +0,0 @@
#include <assert.h>
#include <blue/compress/compressor.h>
#include <blue/compress/cstream.h>
#include <blue/compress/zstd.h>
#include <blue/core/ringbuffer.h>
#include <blue/core/stream.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 32
static int compress(b_type compressor_type, FILE *in, FILE *out)
{
b_stream *out_stream = b_stream_open_fp(out);
b_cstream *cstream;
b_status status = b_cstream_open(
out_stream, compressor_type, B_COMPRESSOR_MODE_COMPRESS, &cstream);
if (!B_OK(status)) {
fprintf(stderr, "cannot initialise compressor\n");
return -1;
}
b_cstream_begin_compressed_section(cstream, NULL);
char buf[4096];
while (1) {
size_t r = fread(buf, 1, sizeof buf, in);
size_t w = 0;
b_cstream_write(cstream, buf, r, &w);
if (r != w) {
fprintf(stderr, "write error\n");
return -1;
}
if (r < sizeof buf) {
break;
}
}
b_cstream_end_compressed_section(cstream, NULL, NULL);
b_cstream_unref(cstream);
b_stream_unref(out_stream);
return 0;
}
static int decompress(b_type compressor_type, FILE *in, FILE *out)
{
b_stream *in_stream = b_stream_open_fp(in);
b_cstream *cstream;
b_status status = b_cstream_open(
in_stream, compressor_type, B_COMPRESSOR_MODE_DECOMPRESS, &cstream);
if (!B_OK(status)) {
fprintf(stderr, "cannot initialise compressor\n");
return -1;
}
b_cstream_begin_compressed_section(cstream, NULL);
char buf[4096];
while (1) {
size_t r = 0;
b_status status = b_cstream_read(cstream, buf, sizeof buf, &r);
if (!B_OK(status)) {
fprintf(stderr, "read error: %s\n",
b_status_description(status));
return -1;
}
size_t w = fwrite(buf, 1, r, out);
if (r != w) {
fprintf(stderr, "write error\n");
return -1;
}
if (r < sizeof buf) {
break;
}
}
b_cstream_end_compressed_section(cstream, NULL, NULL);
b_cstream_unref(cstream);
b_stream_unref(in_stream);
return 0;
}
int main(int argc, const char **argv)
{
if (argc < 4) {
fprintf(stderr, "usage: %s <C/D> <inpath> <outpath>\n", argv[0]);
return -1;
}
b_compressor_mode mode;
if (!strcmp(argv[1], "C")) {
mode = B_COMPRESSOR_MODE_COMPRESS;
} else if (!strcmp(argv[1], "D")) {
mode = B_COMPRESSOR_MODE_DECOMPRESS;
} else {
fprintf(stderr, "invalid mode %s\n", argv[1]);
return -1;
}
FILE *in_fp = fopen(argv[2], "rb");
if (!in_fp) {
fprintf(stderr, "cannot open input file %s\n", argv[2]);
return -1;
}
FILE *out_fp = fopen(argv[3], "wb");
if (!out_fp) {
fclose(in_fp);
fprintf(stderr, "cannot open output file %s\n", argv[3]);
return -1;
}
int ret = 0;
switch (mode) {
case B_COMPRESSOR_MODE_COMPRESS:
ret = compress(B_TYPE_ZSTD_COMPRESSOR, in_fp, out_fp);
break;
case B_COMPRESSOR_MODE_DECOMPRESS:
ret = decompress(B_TYPE_ZSTD_COMPRESSOR, in_fp, out_fp);
break;
default:
ret = -1;
break;
}
printf("Done\n");
fclose(in_fp);
fclose(out_fp);
return ret;
}
-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
-199
View File
@@ -1,199 +0,0 @@
#include "blue/core/misc.h"
#include <CuTest.h>
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#include <blue/core/stringstream.h>
#include <stdlib.h>
#include <time.h>
struct test_tree_node {
int value;
b_btree_node node;
};
struct test_queue_entry {
int value;
b_queue_entry entry;
};
B_BTREE_DEFINE_SIMPLE_INSERT(struct test_tree_node, node, value, test_tree_insert);
void test_btree_insert(CuTest *tc)
{
b_btree tree = {0};
struct test_tree_node nodes[3] = {0};
for (int i = 0; i < sizeof nodes / sizeof *nodes; i++) {
nodes[i].value = i;
}
test_tree_insert(&tree, &nodes[0]);
CuAssertPtrEquals(tc, NULL, nodes[0].node.b_left);
CuAssertPtrEquals(tc, NULL, nodes[0].node.b_right);
CuAssertIntEquals(tc, 1, nodes[0].node.b_height);
test_tree_insert(&tree, &nodes[1]);
CuAssertPtrEquals(tc, NULL, nodes[0].node.b_left);
CuAssertPtrEquals(tc, &nodes[1].node, nodes[0].node.b_right);
CuAssertIntEquals(tc, 2, nodes[0].node.b_height);
CuAssertPtrEquals(tc, NULL, nodes[1].node.b_left);
CuAssertPtrEquals(tc, NULL, nodes[1].node.b_right);
CuAssertIntEquals(tc, 1, nodes[1].node.b_height);
test_tree_insert(&tree, &nodes[2]);
CuAssertPtrEquals(tc, &nodes[0].node, nodes[1].node.b_left);
CuAssertPtrEquals(tc, &nodes[2].node, nodes[1].node.b_right);
CuAssertIntEquals(tc, 2, nodes[1].node.b_height);
CuAssertPtrEquals(tc, NULL, nodes[0].node.b_left);
CuAssertPtrEquals(tc, NULL, nodes[0].node.b_right);
CuAssertIntEquals(tc, 1, nodes[0].node.b_height);
CuAssertPtrEquals(tc, NULL, nodes[2].node.b_left);
CuAssertPtrEquals(tc, NULL, nodes[2].node.b_right);
CuAssertIntEquals(tc, 1, nodes[2].node.b_height);
}
void test_btree_iterate(CuTest *tc)
{
static const size_t nr_nodes = 256;
srand(time(NULL));
b_btree tree = {0};
struct test_tree_node *nodes = calloc(nr_nodes, sizeof *nodes);
CuAssertPtrNotNull(tc, nodes);
for (int i = 0; i < nr_nodes; i++) {
nodes[i].value = rand();
test_tree_insert(&tree, &nodes[i]);
}
int prev = -1;
b_btree_iterator it;
b_btree_foreach (&it, &tree) {
struct test_tree_node *node
= b_unbox(struct test_tree_node, it.node, node);
CuAssertPtrNotNull(tc, node);
if (prev == -1) {
prev = node->value;
continue;
}
CuAssertTrue(tc, prev <= node->value);
prev = node->value;
}
free(nodes);
}
void test_queue_insert(CuTest *tc)
{
struct test_queue_entry entries[5] = {0};
for (int i = 0; i < sizeof entries / sizeof *entries; i++) {
entries[i].value = i;
}
b_queue q = B_QUEUE_INIT;
b_queue_push_back(&q, &entries[0].entry);
b_queue_push_back(&q, &entries[2].entry);
b_queue_push_back(&q, &entries[4].entry);
b_queue_insert_after(&q, &entries[3].entry, &entries[2].entry);
b_queue_insert_before(&q, &entries[1].entry, &entries[2].entry);
CuAssertPtrEquals(tc, NULL, entries[0].entry.qe_prev);
CuAssertPtrEquals(tc, &entries[1].entry, entries[0].entry.qe_next);
CuAssertPtrEquals(tc, &entries[0].entry, entries[1].entry.qe_prev);
CuAssertPtrEquals(tc, &entries[2].entry, entries[1].entry.qe_next);
CuAssertPtrEquals(tc, &entries[1].entry, entries[2].entry.qe_prev);
CuAssertPtrEquals(tc, &entries[3].entry, entries[2].entry.qe_next);
CuAssertPtrEquals(tc, &entries[2].entry, entries[3].entry.qe_prev);
CuAssertPtrEquals(tc, &entries[4].entry, entries[3].entry.qe_next);
CuAssertPtrEquals(tc, &entries[3].entry, entries[4].entry.qe_prev);
CuAssertPtrEquals(tc, NULL, entries[4].entry.qe_next);
}
void test_queue_iterate(CuTest *tc)
{
b_queue q = B_QUEUE_INIT;
struct test_queue_entry entries[32] = {0};
for (int i = 0; i < sizeof entries / sizeof *entries; i++) {
entries[i].value = i;
b_queue_push_back(&q, &entries[i].entry);
}
int prev = -1;
b_queue_iterator it;
b_queue_foreach (&it, &q) {
struct test_queue_entry *e
= b_unbox(struct test_queue_entry, it.entry, entry);
CuAssertPtrNotNull(tc, e);
if (prev == -1) {
prev = e->value;
continue;
}
CuAssertTrue(tc, prev < e->value);
prev = e->value;
}
}
void test_stringstream_1(CuTest *tc)
{
char buf[1024];
b_stringstream *s = b_stringstream_create_with_buffer(buf, sizeof buf);
b_stream_write_string(s, "hello", NULL);
b_stream_write_fmt(s, NULL, "(%d + %.1f)", 32, 2.3);
char *end = b_stringstream_steal(s);
b_stringstream_unref(s);
CuAssertStrEquals(tc, "hello(32 + 2.3)", end);
}
void test_stringstream_2(CuTest *tc)
{
char buf[1024];
b_stringstream *s = b_stringstream_create_with_buffer(buf, sizeof buf);
b_stream_write_string(s, "{\n", NULL);
b_stream_push_indent(s, 1);
b_stream_write_string(s, "a = 32,\n", NULL);
b_stream_write_string(s, "b = 64\n", NULL);
b_stream_pop_indent(s);
b_stream_write_string(s, "}", NULL);
char *str = b_stringstream_steal(s);
b_stringstream_unref(s);
CuAssertStrEquals(tc, "{\n a = 32,\n b = 64\n}", str);
}
CuSuite *get_all_tests(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_btree_insert);
SUITE_ADD_TEST(suite, test_btree_iterate);
SUITE_ADD_TEST(suite, test_queue_insert);
SUITE_ADD_TEST(suite, test_queue_iterate);
SUITE_ADD_TEST(suite, test_stringstream_1);
SUITE_ADD_TEST(suite, test_stringstream_2);
return suite;
}
-74
View File
@@ -1,74 +0,0 @@
#include <blue/core/hash.h>
#include <stdio.h>
#include <string.h>
static void print_digest(
const char *func_name, b_hash_function func, const char *msg,
size_t msg_len, size_t digest_len)
{
unsigned char digest[128];
b_hash_ctx ctx;
if (!B_OK(b_hash_ctx_init(&ctx, func))) {
printf("b_hash_ctx_init failed\n");
return;
}
if (!B_OK(b_hash_ctx_update(&ctx, msg, msg_len))) {
printf("b_hash_ctx_update failed\n");
return;
}
if (!B_OK(b_hash_ctx_finish(&ctx, digest, sizeof digest))) {
printf("b_hash_ctx_finish failed\n");
return;
}
char digest_str[256];
for (size_t i = 0; i < digest_len; i++) {
snprintf(
digest_str + (i * 2), sizeof digest_str - (i * 2),
"%02x", digest[i]);
}
printf("%s(%s) = %s\n", func_name, msg, digest_str);
}
int main(void)
{
const char *msg = "Hello, world!";
size_t msg_len = strlen(msg);
print_digest("MD4", B_HASH_MD4, msg, msg_len, B_DIGEST_LENGTH_MD4);
print_digest("MD5", B_HASH_MD5, msg, msg_len, B_DIGEST_LENGTH_MD5);
print_digest("SHA1", B_HASH_SHA1, msg, msg_len, B_DIGEST_LENGTH_SHA1);
print_digest(
"SHA224", B_HASH_SHA2_224, msg, msg_len, B_DIGEST_LENGTH_SHA2_224);
print_digest(
"SHA256", B_HASH_SHA2_256, msg, msg_len, B_DIGEST_LENGTH_SHA2_256);
print_digest(
"SHA384", B_HASH_SHA2_384, msg, msg_len, B_DIGEST_LENGTH_SHA2_384);
print_digest(
"SHA512", B_HASH_SHA2_512, msg, msg_len, B_DIGEST_LENGTH_SHA2_512);
print_digest(
"SHA3-224", B_HASH_SHA3_224, msg, msg_len,
B_DIGEST_LENGTH_SHA3_224);
print_digest(
"SHA3-256", B_HASH_SHA3_256, msg, msg_len,
B_DIGEST_LENGTH_SHA3_256);
print_digest(
"SHA3-384", B_HASH_SHA3_384, msg, msg_len,
B_DIGEST_LENGTH_SHA3_384);
print_digest(
"SHA3-512", B_HASH_SHA3_512, msg, msg_len,
B_DIGEST_LENGTH_SHA3_512);
print_digest(
"SHAKE128", B_HASH_SHAKE128, msg, msg_len,
B_DIGEST_LENGTH_SHAKE128);
print_digest(
"SHAKE256", B_HASH_SHAKE256, msg, msg_len,
B_DIGEST_LENGTH_SHAKE256);
return 0;
}
-28
View File
@@ -1,28 +0,0 @@
#include <blue/core/rope.h>
#include <stdio.h>
int main(void)
{
b_rope a = B_ROPE_CHAR('a');
b_rope b = B_ROPE_CSTR_STATIC("Hello, world!");
b_rope c = B_ROPE_INT(-4096);
b_rope d = B_ROPE_UINT(4096);
b_rope str;
const b_rope *ropes[] = {
&a,
&b,
&c,
&d,
};
b_rope_join(&str, ropes, sizeof ropes / sizeof ropes[0]);
char cstr[1024];
b_rope_to_cstr(&str, cstr, sizeof cstr);
b_rope_destroy(&str);
printf("%s\n", cstr);
return 0;
}
-10
View File
@@ -1,10 +0,0 @@
#include <blue/core/stream.h>
#include <stdio.h>
int main(void)
{
b_stream_read_line_s(b_stdin, b_stdout);
b_stream_write_char(b_stdout, '\n');
return 0;
}
-5
View File
@@ -1,5 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_module(
NAME core
SUBDIRS hash)
-79
View File
@@ -1,79 +0,0 @@
#include "class.h"
#include "type.h"
#include <assert.h>
#include <blue/core/class.h>
#include <stdlib.h>
#include <string.h>
void *b_class_get(b_type id)
{
struct b_type_registration *r = b_type_get_registration(id);
if (!r) {
return NULL;
}
return r->r_class;
}
const char *b_class_get_name(const struct _b_class *c)
{
if (!c) {
return NULL;
}
assert(c->c_magic == B_CLASS_MAGIC);
return c->c_type->r_info->t_name;
}
void *b_class_get_interface(const struct _b_class *c, const union b_type *id)
{
if (!c) {
return NULL;
}
assert(c->c_magic == B_CLASS_MAGIC);
const struct b_type_registration *type_reg = c->c_type;
struct b_type_component *comp
= b_type_get_component(&type_reg->r_components, id);
if (!comp) {
return NULL;
}
return (char *)c + comp->c_class_data_offset;
}
b_result b_class_instantiate(
struct b_type_registration *type, struct _b_class **out_class)
{
struct _b_class *out = malloc(type->r_class_size);
if (!out) {
return B_RESULT_ERR(NO_MEMORY);
}
memset(out, 0x0, type->r_class_size);
out->c_magic = B_CLASS_MAGIC;
out->c_type = type;
struct b_queue_entry *entry = b_queue_first(&type->r_class_hierarchy);
while (entry) {
struct b_type_component *comp
= b_unbox(struct b_type_component, entry, c_entry);
const struct b_type_info *class_info = comp->c_type->r_info;
void *class_data = (char *)out + comp->c_class_data_offset;
if (class_info->t_class_init) {
class_info->t_class_init(out, class_data);
}
entry = b_queue_next(entry);
}
*out_class = out;
return B_RESULT_SUCCESS;
}
-18
View File
@@ -1,18 +0,0 @@
#ifndef _CLASS_H_
#define _CLASS_H_
#include <blue/core/error.h>
#include <blue/core/misc.h>
#include <stdint.h>
struct b_type_registration;
struct _b_class {
uint64_t c_magic;
const struct b_type_registration *c_type;
};
extern b_result b_class_instantiate(
struct b_type_registration *type, struct _b_class **out);
#endif
-1059
View File
File diff suppressed because it is too large Load Diff
-37
View File
@@ -1,37 +0,0 @@
#ifndef _BLUELIB_ERROR_H_
#define _BLUELIB_ERROR_H_
#include <blue/core/error.h>
#include <blue/core/queue.h>
struct b_error_stack_frame {
b_queue_entry f_entry;
const char *f_file;
unsigned int f_line_number;
const char *f_function;
};
struct b_error_submsg {
b_queue_entry msg_entry;
b_error_submsg_type msg_type;
char *msg_content;
const struct b_error_msg *msg_msg;
struct b_error_template_parameter msg_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
};
struct b_error {
const struct b_error_vendor *err_vendor;
b_error_status_code err_code;
const struct b_error_definition *err_def;
const struct b_error_msg *err_msg;
char *err_description;
struct b_error_template_parameter err_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
struct b_queue err_submsg;
struct b_queue err_stack;
b_queue_entry err_entry;
struct b_error *err_caused_by;
};
#endif
-139
View File
@@ -1,139 +0,0 @@
#include "hash.h"
#include <blue/core/hash.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;
}
enum b_status b_hash_ctx_finish(
struct b_hash_ctx *ctx, void *out_digest, size_t out_max)
{
if (!ctx->ctx_ops) {
return B_ERR_BAD_STATE;
}
if (!ctx->ctx_ops->hash_finish) {
return B_ERR_NOT_SUPPORTED;
}
ctx->ctx_ops->hash_finish(ctx, out_digest, out_max);
memset(&ctx->ctx_state, 0x0, sizeof ctx->ctx_state);
if (ctx->ctx_ops->hash_init) {
ctx->ctx_ops->hash_init(ctx);
}
return B_SUCCESS;
}
-14
View File
@@ -1,14 +0,0 @@
#ifndef _HASH_H_
#define _HASH_H_
#include <stddef.h>
struct b_hash_ctx;
struct b_hash_function_ops {
void (*hash_init)(struct b_hash_ctx *);
void (*hash_update)(struct b_hash_ctx *, const void *, size_t);
void (*hash_finish)(struct b_hash_ctx *, void *, size_t);
};
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef BLUELIB_CORE_BITOP_H_
#define BLUELIB_CORE_BITOP_H_
#include <blue/core/misc.h>
BLUE_API int b_popcountl(long v);
BLUE_API int b_ctzl(long v);
BLUE_API int b_clzl(long v);
#if defined(__GNUC__) || defined(__clang__)
#define b_cmpxchg(v, expected_val, new_val) \
__atomic_compare_exchange_n( \
v, expected_val, new_val, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED)
#elif defined(_MSC_VER)
/* TODO add MSVC support */
#error MSVC intrinsics not yet supported
#else
#error Unsupported compiler
#endif
#endif
-357
View File
@@ -1,357 +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;
}
/* get the height of `node`.
the height of a node is defined as the length of the longest path
between the node and a leaf node.
this count includes the node itself, so the height of a leaf node will be 1.
*/
static inline unsigned short b_btree_height(b_btree_node *node)
{
return node->b_height;
}
BLUE_API b_iterator *b_btree_begin(b_btree *tree);
BLUE_API const b_iterator *b_btree_cbegin(const b_btree *tree);
#ifdef __cplusplus
}
#endif
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef BLUE_OBJECT_CLASS_H_
#define BLUE_OBJECT_CLASS_H_
#include <blue/core/type.h>
#define B_CLASS_MAGIC 0xDEADFACEDCAFEBEDULL
#define B_CLASS(p) ((b_class *)(p))
typedef struct _b_class b_class;
BLUE_API void *b_class_get(b_type id);
BLUE_API const char *b_class_get_name(const b_class *c);
BLUE_API void *b_class_get_interface(const b_class *c, b_type id);
#endif
-41
View File
@@ -1,41 +0,0 @@
#ifndef BLUE_CORE_ENCODING_H_
#define BLUE_CORE_ENCODING_H_
#include <blue/core/misc.h>
#include <stdbool.h>
#include <stdint.h>
#define B_WCHAR_INVALID ((b_wchar) - 1)
typedef int32_t b_wchar;
BLUE_API bool b_wchar_is_alpha(b_wchar c);
BLUE_API bool b_wchar_is_number(b_wchar c);
static inline bool b_wchar_is_bin_digit(b_wchar c)
{
return c >= '0' && c <= '1';
}
static inline bool b_wchar_is_oct_digit(b_wchar c)
{
return c >= '0' && c <= '7';
}
BLUE_API bool b_wchar_is_hex_digit(b_wchar c);
BLUE_API bool b_wchar_is_space(b_wchar c);
static inline bool b_wchar_is_alnum(b_wchar c)
{
return b_wchar_is_alpha(c) || b_wchar_is_number(c);
}
BLUE_API bool b_wchar_is_punct(b_wchar c);
BLUE_API bool b_wchar_utf8_is_valid_scalar(b_wchar c);
BLUE_API unsigned int b_wchar_utf8_header_decode(char c);
BLUE_API unsigned int b_wchar_utf8_codepoint_size(b_wchar c);
BLUE_API b_wchar b_wchar_utf8_codepoint_decode(const char *s);
BLUE_API unsigned int b_wchar_utf8_codepoint_encode(b_wchar c, char s[4]);
BLUE_API unsigned int b_wchar_utf8_codepoint_stride(const char *s);
BLUE_API size_t b_wchar_utf8_codepoint_count(const char *s, size_t nr_bytes);
BLUE_API size_t b_wchar_utf8_string_encoded_size(
const b_wchar *s, size_t nr_codepoints);
#endif
-49
View File
@@ -1,49 +0,0 @@
#ifndef BLUELIB_CORE_ENDIAN_H_
#define BLUELIB_CORE_ENDIAN_H_
#include <blue/core/misc.h>
#include <stdint.h>
typedef struct {
union {
unsigned char i_bytes[sizeof(uint16_t)];
int16_t i_val;
uint16_t i_uval;
};
} b_i16;
typedef struct {
union {
unsigned char i_bytes[sizeof(uint32_t)];
int32_t i_val;
uint32_t i_uval;
};
} b_i32;
typedef struct {
union {
unsigned char i_bytes[sizeof(uint64_t)];
int64_t i_val;
uint64_t i_uval;
};
} b_i64;
BLUE_API b_i16 b_i16_htob(uint16_t v);
BLUE_API b_i16 b_i16_htos(uint16_t v);
BLUE_API uint16_t b_i16_btoh(b_i16 v);
BLUE_API uint16_t b_i16_stoh(b_i16 v);
BLUE_API b_i32 b_i32_htob(uint32_t v);
BLUE_API b_i32 b_i32_htos(uint32_t v);
BLUE_API uint32_t b_i32_btoh(b_i32 v);
BLUE_API uint32_t b_i32_stoh(b_i32 v);
BLUE_API b_i64 b_i64_htob(uint64_t v);
BLUE_API b_i64 b_i64_htos(uint64_t v);
BLUE_API uint64_t b_i64_btoh(b_i64 v);
BLUE_API uint64_t b_i64_stoh(b_i64 v);
#endif
-418
View File
@@ -1,418 +0,0 @@
#ifndef BLUE_CORE_ERROR_H_
#define BLUE_CORE_ERROR_H_
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdarg.h>
#include <stdbool.h>
#define B_ERROR_TEMPLATE_PARAMETER_MAX 4
#define B_ERROR_MSG_ID_INVALID ((unsigned long)-1)
#define B_CATCH(err, expr) ((err = (expr)) != NULL)
#define b_result_is_error(result) ((result) != NULL)
#define b_result_is_success(result) ((result) == NULL)
#define B_RESULT_SUCCESS ((b_result)NULL)
#define B_RESULT_ERR(err_name) \
b_error_with_code(b_error_vendor_get_builtin(), B_ERR_##err_name)
#define B_RESULT_ERR_WITH_STRING(err_name, ...) \
b_error_with_string( \
b_error_vendor_get_builtin(), B_ERR_##err_name, __VA_ARGS__)
#define B_RESULT_STATUS(code) \
((code) == B_SUCCESS \
? B_RESULT_SUCCESS \
: (b_error_with_code(b_error_vendor_get_builtin(), code)))
#define B_RESULT_STATUS_WITH_STRING(code, ...) \
((code) == B_SUCCESS \
? B_RESULT_SUCCESS \
: (b_error_with_string( \
b_error_vendor_get_builtin(), code, __VA_ARGS__)))
#define B_ERRORS_BUILTIN (b_error_vendor_get_builtin())
#define B_ERRORS_ERRNO (b_error_vendor_get_errno())
#define B_ERROR_PARAM(name, value) \
(b_error_template_parameter) \
{ \
.param_name = (name), .param_value = (uintptr_t)(value), \
}
#define B_ERROR_TEMPLATE_PARAM(name, type, format) \
(b_error_template_parameter_definition) \
{ \
.param_name = (name), .param_type = (type), \
.param_format = (format), \
}
#define B_ERROR_DEFINITION(code, name, msg) \
[code] = (b_error_definition) \
{ \
.err_name = (name), .err_message = (msg), \
}
#define B_ERROR_DEFINITION_TEMPLATE(code, name, msg, ...) \
[code] = (b_error_definition) \
{ \
.err_name = (name), .err_message = (msg), \
.err_params = __VA_ARGS__, \
}
#define B_ERROR_MSG(id, content) \
[id] = (b_error_msg) \
{ \
.msg_message = (content), \
}
#define B_ERROR_MSG_TEMPLATE(id, content, ...) \
[id] = (b_error_msg) \
{ \
.msg_message = (content), .msg_params = __VA_ARGS__, \
}
#define z__b_error_create_status(status_code) \
(z__b_error_create( \
b_error_vendor_get_builtin(), status_code, NULL, NULL, 0, \
NULL, NULL))
/* Error creation macros */
#define b_error_with_code(vendor, code) \
(z__b_error_create( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_caused_by_error(vendor, code, cause_error) \
(z__b_error_create( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_caused_by_status(vendor, code, cause_status) \
(z__b_error_create( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_caused_by_code(vendor, code, cause_vendor, cause_code) \
(z__b_error_create( \
vendor, code, b_error_with_code(cause_vendor, cause_code), \
__FILE__, __LINE__, __FUNCTION__, NULL))
#define b_error_with_string(vendor, code, ...) \
(z__b_error_create( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__))
#define b_error_with_string_caused_by_error(vendor, code, cause_error, ...) \
(z__b_error_create( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
__VA_ARGS__))
#define b_error_with_string_caused_by_status(vendor, code, cause_status, ...) \
(z__b_error_create( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__))
#define b_error_with_msg(vendor, code, msg_id) \
(z__b_error_create_msg( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {{}}))
#define b_error_with_msg_caused_by_error(vendor, code, cause_error, msg_id) \
(z__b_error_create_msg( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
msg_id, (b_error_template_parameter[]) {{}}))
#define b_error_with_msg_caused_by_status(vendor, code, cause_status, msg_id) \
(z__b_error_create_msg( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {{}}))
#define b_error_with_msg_template(vendor, code, msg_id, ...) \
(z__b_error_create_msg( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_msg_template_caused_by_error( \
vendor, code, cause_error, msg_id, ...) \
(z__b_error_create_msg( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
msg_id, (b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_msg_template_caused_by_status( \
vendor, code, cause_status, msg_id, ...) \
(z__b_error_create_msg( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_template(vendor, code, ...) \
(z__b_error_create_template( \
vendor, code, NULL, __FILE__, __LINE__, __FUNCTION__, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_template_caused_by_error(vendor, code, cause_error, ...) \
(z__b_error_create_template( \
vendor, code, cause_error, __FILE__, __LINE__, __FUNCTION__, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
#define b_error_with_template_caused_by_status(vendor, code, cause_status, ...) \
(z__b_error_create_template( \
vendor, code, z__b_error_create_status(cause_status), \
__FILE__, __LINE__, __FUNCTION__, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
/* Error propagation macros */
#define b_result_propagate(err) \
(z__b_error_propagate(err, __FILE__, __LINE__, __FUNCTION__))
#define b_error_caused_by(err, caused_by) (z__b_error_caused_by(err, caused_by))
#define b_error_caused_by_b_status(err, status) \
(z__b_error_caused_by_b_status(err, status))
#define b_error_replace(err, caused_by) \
(z__b_error_propagate(err, __FILE__, __LINE__, __FUNCTION__))
/* Error throw macros */
#define z__b_throw(err) (z__b_error_throw(err, NULL, 0, NULL))
#define b_throw(err) (z__b_error_throw(err, __FILE__, __LINE__, __FUNCTION__))
#define b_throw_status(status) \
(z__b_error_throw( \
z__b_error_create( \
b_error_vendor_get_builtin(), status, NULL, NULL, 0, \
NULL, NULL), \
__FILE__, __LINE__, __FUNCTION__))
#define b_throw_status_string(status, ...) \
(z__b_error_throw( \
z__b_error_create( \
b_error_vendor_get_builtin(), status, NULL, NULL, 0, \
NULL, __VA_ARGS__), \
__FILE__, __LINE__, __FUNCTION__))
#define b_throw_error_code(vendor, code) \
z__b_throw(b_error_with_code(vendor, code))
#define b_throw_error_caused_by_error(vendor, code, cause) \
z__b_throw(b_error_caused_by_error(vendor, code, cause))
#define b_throw_error_caused_by_status(vendor, code, cause) \
z__b_throw(b_error_caused_by_status(vendor, code, cause))
#define b_throw_error_with_string(vendor, code, ...) \
z__b_throw(b_error_with_string(vendor, code, __VA_ARGS__))
#define b_throw_error_with_string_caused_by_error(vendor, code, cause, ...) \
z__b_throw(b_error_with_string_caused_by_error( \
vendor, code, cause, __VA_ARGS__))
#define b_throw_error_with_string_caused_by_status(vendor, code, cause, ...) \
z__b_throw(b_error_with_string_caused_by_status( \
vendor, code, cause, __VA_ARGS__))
#define b_throw_error_with_msg(vendor, code, msg_id) \
z__b_throw(b_error_with_msg(vendor, code, msg_id))
#define b_throw_error_with_msg_caused_by_error(vendor, code, cause, msg_id) \
z__b_throw(b_error_with_msg_caused_by_error(vendor, code, cause, msg_id))
#define b_throw_error_with_msg_caused_by_status(vendor, code, cause, msg_id) \
z__b_throw(b_error_with_msg_caused_by_status(vendor, code, cause, msg_id))
#define b_throw_error_with_msg_template(vendor, code, msg_id, ...) \
z__b_throw(b_error_with_msg_template(vendor, code, msg_id, __VA_ARGS__))
#define b_throw_error_with_msg_template_caused_by_error( \
vendor, code, cause, msg_id, ...) \
z__b_throw(b_error_with_msg_template_caused_by_error( \
vendor, code, cause, msg_id, __VA_ARGS__))
#define b_throw_error_with_msg_template_caused_by_status( \
vendor, code, cause, msg_id, ...) \
z__b_throw(b_error_with_msg_template_caused_by_status( \
vendor, code, cause, msg_id, __VA_ARGS__))
#define b_throw_error_with_template(vendor, code, ...) \
z__b_throw(b_error_with_template(vendor, code, __VA_ARGS__))
#define b_throw_error_with_template_caused_by_error(vendor, code, cause, ...) \
z__b_throw(b_error_with_template_caused_by_error( \
vendor, code, cause, __VA_ARGS__))
#define b_throw_error_with_template_caused_by_status(vendor, code, cause, ...) \
z__b_throw(b_error_with_template_caused_by_status( \
vendor, code, cause, __VA_ARGS__))
#define B_ERR_MSG(s) \
{ \
.msg_type = B_ERROR_MESSAGE_ERROR, \
.msg_content = (s), \
}
#define B_ERR_MSG_WARN(s) \
{ \
.msg_type = B_ERROR_MESSAGE_WARN, \
.msg_content = (s), \
}
#define B_ERR_MSG_INFO(s) \
{ \
.msg_type = B_ERROR_MESSAGE_INFO, \
.msg_content = (s), \
}
#define B_ERR_MSG_END(s) \
{ \
.msg_type = B_ERROR_MESSAGE_NONE, \
.msg_content = NULL, \
}
typedef enum b_error_submsg_type {
B_ERROR_SUBMSG_NONE = 0,
B_ERROR_SUBMSG_ERROR,
B_ERROR_SUBMSG_WARNING,
B_ERROR_SUBMSG_INFO,
} b_error_submsg_type;
typedef enum b_error_report_flags {
B_ERROR_REPORT_NONE = 0,
B_ERROR_REPORT_STATUS = 0x01u,
B_ERROR_REPORT_DESCRIPTION = 0x02u,
B_ERROR_REPORT_SUBMSG = 0x04u,
B_ERROR_REPORT_STACK_TRACE = 0x08u,
B_ERROR_REPORT_CAUSE = 0x10u,
B_ERROR_REPORT_MINIMAL = B_ERROR_REPORT_STATUS | B_ERROR_REPORT_DESCRIPTION,
B_ERROR_REPORT_DEFAULT = B_ERROR_REPORT_MINIMAL | B_ERROR_REPORT_SUBMSG
| B_ERROR_REPORT_CAUSE,
B_ERROR_REPORT_ALL = B_ERROR_REPORT_DEFAULT | B_ERROR_REPORT_STACK_TRACE,
} b_error_report_flags;
typedef enum b_error_template_parameter_type {
B_ERROR_TEMPLATE_PARAM_NONE = 0,
B_ERROR_TEMPLATE_PARAM_STRING,
B_ERROR_TEMPLATE_PARAM_CHAR,
B_ERROR_TEMPLATE_PARAM_INT,
B_ERROR_TEMPLATE_PARAM_UINT,
B_ERROR_TEMPLATE_PARAM_LONG,
B_ERROR_TEMPLATE_PARAM_ULONG,
B_ERROR_TEMPLATE_PARAM_LONGLONG,
B_ERROR_TEMPLATE_PARAM_ULONGLONG,
B_ERROR_TEMPLATE_PARAM_SIZE_T,
B_ERROR_TEMPLATE_PARAM_INTPTR,
B_ERROR_TEMPLATE_PARAM_UINTPTR,
B_ERROR_TEMPLATE_PARAM_PTR,
} b_error_template_parameter_type;
typedef struct b_error_template_parameter_definition {
const char *param_name;
b_error_template_parameter_type param_type;
const char *param_format;
} b_error_template_parameter_definition;
typedef struct b_error_template_parameter {
const char *param_name;
uintptr_t param_value;
const struct b_error_template_parameter_definition *__param_def;
} b_error_template_parameter;
struct b_error_vendor;
typedef struct b_error b_error;
typedef struct b_error *b_result;
typedef struct b_error_submsg b_error_submsg;
typedef struct b_error_stack_frame b_error_stack_frame;
typedef long b_error_status_code;
typedef unsigned long b_error_msg_id;
typedef struct b_error_definition {
const char *err_name;
const char *err_message;
const b_error_template_parameter_definition err_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
} b_error_definition;
typedef struct b_error_msg {
const char *msg_message;
const b_error_template_parameter_definition msg_params[B_ERROR_TEMPLATE_PARAMETER_MAX];
} b_error_msg;
typedef const b_error_definition *(*b_error_status_code_get_definition)(
const struct b_error_vendor *, b_error_status_code);
typedef const b_error_msg *(*b_error_msg_get_definition)(
const struct b_error_vendor *, b_error_msg_id);
typedef void (*b_error_report_function)(
const struct b_error *, b_error_report_flags);
typedef struct b_error_vendor {
const char *v_name;
b_error_status_code_get_definition v_status_get_definition;
b_error_msg_get_definition v_msg_get_definition;
const b_error_definition *v_error_definitions;
size_t v_error_definitions_length;
const b_error_msg *v_msg;
size_t v_msg_length;
} b_error_vendor;
BLUE_API b_error *z__b_error_create_template(
const b_error_vendor *, b_error_status_code, b_error *, const char *,
unsigned int, const char *, const b_error_template_parameter[]);
BLUE_API b_error *z__b_error_create_string(
const b_error_vendor *, b_error_status_code, b_error *, const char *,
unsigned int, const char *, const char *, va_list);
BLUE_API b_error *z__b_error_create_msg(
const b_error_vendor *, b_error_status_code, b_error *, const char *,
unsigned int, const char *, b_error_msg_id,
const b_error_template_parameter[]);
BLUE_API b_error *z__b_error_propagate(
b_error *, const char *, unsigned int, const char *);
BLUE_API b_error *z__b_error_caused_by(b_error *, b_error *);
BLUE_API b_error *z__b_error_caused_by_b_status(b_error *, b_status);
BLUE_API void z__b_error_throw(b_error *, const char *, unsigned int, const char *);
BLUE_API bool b_result_is(
b_result result, const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const b_error_vendor *b_error_vendor_get_builtin(void);
BLUE_API const b_error_vendor *b_error_vendor_get_errno(void);
BLUE_API const b_error_definition *b_error_vendor_get_error_definition(
const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const char *b_error_vendor_get_status_code_name(
const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const char *b_error_vendor_get_status_code_description(
const b_error_vendor *vendor, b_error_status_code code);
BLUE_API const b_error_msg *b_error_vendor_get_msg(
const b_error_vendor *vendor, b_error_msg_id msg_id);
static inline b_error *z__b_error_create(
const b_error_vendor *v, b_error_status_code c, b_error *c2,
const char *f0, unsigned int l, const char *f1, const char *d, ...)
{
va_list arg;
va_start(arg, d);
b_error *err = z__b_error_create_string(v, c, c2, f0, l, f1, d, arg);
va_end(arg);
return err;
}
BLUE_API enum b_status b_error_add_submsg_string(
b_error *error, b_error_submsg_type type, const char *msg, ...);
BLUE_API enum b_status z__b_error_add_submsg_template(
b_error *error, b_error_submsg_type type, b_error_msg_id msg_id,
b_error_template_parameter param[]);
#define b_error_add_submsg(error, type, msg_id) \
(z__b_error_add_submsg_template( \
error, type, msg_id, (b_error_template_parameter[]) {{}}))
#define b_error_add_submsg_template(error, type, msg_id, ...) \
(z__b_error_add_submsg_template( \
error, type, msg_id, \
(b_error_template_parameter[]) {__VA_ARGS__, {}}))
BLUE_API void b_error_release(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
-109
View File
@@ -1,109 +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;
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_finish(
b_hash_ctx *ctx, void *out_digest, size_t out_max);
#endif
-90
View File
@@ -1,90 +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);
BLUE_API b_status b_iterator_is_valid(const b_iterator *it);
B_DECLS_END;
#endif
-197
View File
@@ -1,197 +0,0 @@
#ifndef BLUE_CORE_MACROS_H_
#define BLUE_CORE_MACROS_H_
#include <blue/core/class.h>
#include <blue/core/object.h>
#include <blue/core/thread.h>
#include <blue/core/type.h>
#include <stdlib.h>
#define __B_IFACE_I0(p, x) p##x
#define __B_IFACE_I1(p, x) __B_IFACE_I0(p, x)
/* Type definitions macros (for use in .c source file) */
#define B_TYPE_CLASS_DEFINITION_BEGIN(type_name) \
static void type_name##_class_init(b_class *p, void *d) \
{
#define B_TYPE_CLASS_DEFINITION_END(type_name) }
#define B_TYPE_CLASS_INTERFACE_BEGIN(interface_name, interface_id) \
interface_name##_class *__B_IFACE_I1(iface, __LINE__) \
= b_class_get_interface(p, interface_id); \
if (!__B_IFACE_I1(iface, __LINE__)) { \
b_throw_error_with_msg_template( \
B_ERRORS_BUILTIN, B_ERR_CLASS_INIT_FAILURE, \
B_MSG_CLASS_SPECIFIES_UNKNOWN_INTERFACE, \
B_ERROR_PARAM("class_name", b_class_get_name(p)), \
B_ERROR_PARAM("interface_name", #interface_name)); \
exit(-1); \
} else { \
interface_name##_class *iface = __B_IFACE_I1(iface, __LINE__);
#define B_TYPE_CLASS_INTERFACE_END(interface_name, interface_id) }
#define B_INTERFACE_ENTRY(slot) iface->slot
#define B_TYPE_DEFINITION_BEGIN(name) \
static b_type_info name##_type_info = {0}; \
static void name##_class_init(b_class *, void *); \
static void name##_type_init(void) \
{ \
b_type_info *type_info = &name##_type_info; \
unsigned int nr_vtables = 0; \
type_info->t_name = #name; \
type_info->t_class_init = name##_class_init;
#define B_TYPE_DEFINITION_END(name) \
b_result result = b_type_register(type_info); \
if (b_result_is_error(result)) { \
b_throw_error_caused_by_error( \
B_ERRORS_BUILTIN, B_ERR_TYPE_REGISTRATION_FAILURE, \
result); \
abort(); \
} \
} \
b_type name##_get_type(void) \
{ \
static b_once static_type_init = B_ONCE_INIT; \
\
if (b_init_once(&static_type_init)) { \
name##_type_init(); \
} \
\
return &name##_type_info.t_id; \
}
#define B_TYPE_ID(a, b, c, d, e) b_type_id_init(&type_info->t_id, a, b, c, d, e)
#define B_TYPE_EXTENDS(parent_id) \
b_type_id_copy(parent_id, &type_info->t_parent_id)
#define B_TYPE_IMPLEMENTS(interface_id) \
b_type_id_copy( \
interface_id, \
&type_info->t_interfaces[type_info->t_nr_interfaces++])
#define B_TYPE_CLASS(class_struct) \
type_info->t_class_size = sizeof(class_struct)
#define B_TYPE_FLAGS(flags) type_info->t_flags = (flags)
#define B_TYPE_INSTANCE_INIT(func) type_info->t_instance_init = (func)
#define B_TYPE_INSTANCE_FINI(func) type_info->t_instance_fini = (func)
#if 0
#define B_TYPE_VTABLE_BEGIN(vtable_struct, interface_id) \
vtable_struct __B_IFACE_I1(iface, __LINE__) = {0}; \
{ \
vtable_struct *iface = &__B_IFACE_I1(iface, __LINE__); \
type_info->t_vtables[nr_vtables].v_vtable = iface; \
type_info->t_vtables[nr_vtables].v_interface_id = interface_id; \
nr_vtables++;
#define B_TYPE_VTABLE_END(vtable_struct, interface_id) }
#endif
#define B_TYPE_INSTANCE_PRIVATE(instance_struct) \
type_info->t_instance_private_size = sizeof(instance_struct)
#define B_TYPE_INSTANCE_PROTECTED(instance_struct) \
type_info->t_instance_protected_size = sizeof(instance_struct)
/* Type declaration macros (for use in .h header file) */
#define __B_DECLARE_TYPE(name) \
typedef B_TYPE_FWDREF(name) name; \
typedef struct _##name##_class name##_class;
#define B_DECLARE_TYPE(name) \
__B_DECLARE_TYPE(name); \
static inline name *name##_ref(name *p) \
{ \
return b_object_ref(p); \
} \
static inline void name##_unref(name *p) \
{ \
b_object_unref(p); \
}
#define B_TYPE_CLASS_DECLARATION_BEGIN(name) struct _##name##_class {
#define B_TYPE_CLASS_DECLARATION_END(name) \
} \
;
#define B_TYPE_VIRTUAL_METHOD(return_type, method_name) \
return_type(*method_name)
#define B_TYPE_DEFAULT_CONSTRUCTOR(type_name, type_id) \
static inline type_name *type_name##_create(void) \
{ \
return b_object_create(type_id); \
}
/* Other macros */
#define B_CLASS_DISPATCH_VIRTUAL( \
type_name, type_id, default_value, func, object, ...) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
return iface->func(object, __VA_ARGS__); \
} else { \
return default_value; \
} \
} while (0)
#define B_CLASS_DISPATCH_VIRTUAL_0(type_name, type_id, default_value, func, object) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
return iface->func(object); \
} else { \
return default_value; \
} \
} while (0)
#define B_CLASS_DISPATCH_VIRTUAL_V(type_name, type_id, func, object, ...) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
iface->func(object, __VA_ARGS__); \
return; \
} \
} while (0)
#define B_CLASS_DISPATCH_VIRTUAL_V0(type_name, type_id, func, object) \
do { \
type_name##_class *iface \
= b_object_get_interface(object, type_id); \
if (iface && iface->func) { \
iface->func(object); \
return; \
} \
} while (0)
#define B_CLASS_DISPATCH_STATIC(type_id, func_name, obj, ...) \
do { \
void *priv = b_object_get_private(obj, type_id); \
return func_name(priv, __VA_ARGS__); \
} while (0)
#define B_CLASS_DISPATCH_STATIC_V(type_id, func_name, obj, ...) \
do { \
void *priv = b_object_get_private(obj, type_id); \
func_name(priv, __VA_ARGS__); \
} while (0)
#define B_CLASS_DISPATCH_STATIC_0(type_id, func_name, obj) \
do { \
void *priv = b_object_get_private(obj, type_id); \
return func_name(priv); \
} while (0)
#define B_CLASS_DISPATCH_STATIC_V0(type_id, func_name, obj) \
do { \
void *priv = b_object_get_private(obj, type_id); \
func_name(priv); \
} while (0)
#ifdef __cplusplus
#define B_DECLS_BEGIN extern "C" {
#define B_DECLS_END }
#else
#define B_DECLS_BEGIN
#define B_DECLS_END
#endif
#endif
-118
View File
@@ -1,118 +0,0 @@
#ifndef BLUE_CORE_MISC_H_
#define BLUE_CORE_MISC_H_
#include <stddef.h>
#include <stdint.h>
#ifndef _Nonnull
#define _Nonnull
#endif
#define B_NPOS ((size_t)-1)
#define b_min(type, x, y) (z__b_min_##type(x, y))
#define b_max(type, x, y) (z__b_max_##type(x, y))
#define b_unbox(type, box, member) \
((type *_Nonnull)((box) ? (uintptr_t)(box) - (offsetof(type, member)) : 0))
#define z__b_merge_(a, b) a##b
#define z__b_label_(a) z__b_merge_(__unique_name_, a)
#define z__b_unique_name() z__b_label_(__LINE__)
#define z__b_numargs(arg_type, ...) \
(sizeof((arg_type[]) {__VA_ARGS__}) / sizeof(arg_type))
#ifdef _MSC_VER
#ifdef BLUELIB_STATIC
#define BLUE_API extern
#else
#ifdef BLUELIB_EXPORT
#define BLUE_API extern __declspec(dllexport)
#else
#define BLUE_API extern __declspec(dllimport)
#endif
#endif
#else
#define BLUE_API extern
#endif
static inline char z__b_min_char(char x, char y)
{
return x < y ? x : y;
}
static inline unsigned char z__b_min_uchar(unsigned char x, unsigned char y)
{
return x < y ? x : y;
}
static inline int z__b_min_int(int x, int y)
{
return x < y ? x : y;
}
static inline unsigned int z__b_min_uint(unsigned int x, unsigned int y)
{
return x < y ? x : y;
}
static inline long z__b_min_long(long x, long y)
{
return x < y ? x : y;
}
static inline unsigned int z__b_min_ulong(unsigned long x, unsigned long y)
{
return x < y ? x : y;
}
static inline long long z__b_min_longlong(long long x, long long y)
{
return x < y ? x : y;
}
static inline unsigned long long z__b_min_ulonglong(
unsigned long long x, unsigned long long y)
{
return x < y ? x : y;
}
static inline size_t z__b_min_size_t(size_t x, size_t y)
{
return x < y ? x : y;
}
static inline char z__b_max_char(char x, char y)
{
return x > y ? x : y;
}
static inline unsigned char z__b_max_uchar(unsigned char x, unsigned char y)
{
return x > y ? x : y;
}
static inline int z__b_max_int(int x, int y)
{
return x > y ? x : y;
}
static inline unsigned int z__b_max_uint(unsigned int x, unsigned int y)
{
return x > y ? x : y;
}
static inline long z__b_max_long(long x, long y)
{
return x > y ? x : y;
}
static inline unsigned int z__b_max_ulong(unsigned long x, unsigned long y)
{
return x > y ? x : y;
}
static inline long long z__b_max_longlong(long long x, long long y)
{
return x > y ? x : y;
}
static inline unsigned long long z__b_max_ulonglong(
unsigned long long x, unsigned long long y)
{
return x > y ? x : y;
}
static inline size_t z__b_max_size_t(size_t x, size_t y)
{
return x > y ? x : y;
}
BLUE_API size_t b_int_length(intptr_t v);
BLUE_API size_t b_uint_length(uintptr_t v);
#endif // BLUE_CORE_MISC_H_
-39
View File
@@ -1,39 +0,0 @@
#ifndef BLUE_CORE_OBJECT_H_
#define BLUE_CORE_OBJECT_H_
#include <blue/core/misc.h>
#include <blue/core/type.h>
#define B_OBJECT_MAGIC 0xDECAFC0C0ABEEF13ULL
#define B_OBJECT(p) ((b_object *)(p))
#define B_TYPE_OBJECT (b_object_get_type())
#define B_TYPE_FWDREF(name) struct _b_object
#define B_RV(p) (b_object_make_rvalue(p))
typedef B_TYPE_FWDREF(b_object) b_object;
typedef struct _b_object_class {
void (*to_string)(const b_object *, B_TYPE_FWDREF(b_stream) *);
} b_object_class;
BLUE_API b_type b_object_get_type(void);
BLUE_API void *b_object_get_private(const b_object *object, b_type type);
BLUE_API void *b_object_get_protected(const b_object *object, b_type type);
BLUE_API void *b_object_get_interface(const b_object *object, b_type type);
BLUE_API b_status b_object_get_data(
const b_object *object, b_type type, void **priv, void **prot,
void **iface);
BLUE_API b_object *b_object_ref(b_object *p);
BLUE_API void b_object_unref(b_object *p);
BLUE_API b_object *b_object_make_rvalue(b_object *p);
BLUE_API b_object *b_object_create(b_type type);
BLUE_API void b_object_to_string(const b_object *p, B_TYPE_FWDREF(b_stream) * out);
BLUE_API bool b_object_is_type(const b_object *p, b_type type);
#endif
-81
View File
@@ -1,81 +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_first == NULL;
}
static inline b_queue_entry *b_queue_first(const b_queue *q)
{
return q->q_first;
}
static inline b_queue_entry *b_queue_last(const b_queue *q)
{
return q->q_last;
}
static inline b_queue_entry *b_queue_next(const b_queue_entry *entry)
{
return entry->qe_next;
}
static inline b_queue_entry *b_queue_prev(const b_queue_entry *entry)
{
return entry->qe_prev;
}
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_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
-103
View File
@@ -1,103 +0,0 @@
#ifndef BLUE_CORE_ROPE_H_
#define BLUE_CORE_ROPE_H_
#include <blue/core/hash.h>
#include <blue/core/misc.h>
#include <stdint.h>
#include <string.h>
struct b_string;
#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 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 void b_rope_to_cstr(const b_rope *rope, char *out, size_t max);
#endif
-48
View File
@@ -1,48 +0,0 @@
#ifndef BLUELIB_CORE_STATUS_H_
#define BLUELIB_CORE_STATUS_H_
#include <blue/core/misc.h>
#define B_OK(status) ((enum b_status)((uintptr_t)(status)) == B_SUCCESS)
#define B_ERR(status) ((status) != B_SUCCESS)
typedef enum b_status {
B_SUCCESS = 0x00u,
B_ERR_NO_MEMORY,
B_ERR_OUT_OF_BOUNDS,
B_ERR_INVALID_ARGUMENT,
B_ERR_NAME_EXISTS,
B_ERR_NOT_SUPPORTED,
B_ERR_BAD_STATE,
B_ERR_NO_ENTRY,
B_ERR_NO_DATA,
B_ERR_NO_SPACE,
B_ERR_UNKNOWN_FUNCTION,
B_ERR_BAD_FORMAT,
B_ERR_IO_FAILURE,
B_ERR_IS_DIRECTORY,
B_ERR_NOT_DIRECTORY,
B_ERR_PERMISSION_DENIED,
B_ERR_BUSY,
/* blue-compress specific code */
B_ERR_COMPRESSION_FAILURE,
/* blue-object specific code */
B_ERR_TYPE_REGISTRATION_FAILURE,
B_ERR_CLASS_INIT_FAILURE,
} b_status;
typedef enum b_status_msg {
B_MSG_SUCCESS = 0,
/* blue-object specific messages */
B_MSG_TYPE_REGISTRATION_FAILURE,
B_MSG_CLASS_INIT_FAILURE,
B_MSG_CLASS_SPECIFIES_UNKNOWN_INTERFACE,
} b_status_msg;
BLUE_API const char *b_status_to_string(b_status status);
BLUE_API const char *b_status_description(b_status status);
#endif
-100
View File
@@ -1,100 +0,0 @@
#ifndef BLUE_CORE_STREAM_H_
#define BLUE_CORE_STREAM_H_
#include <blue/core/encoding.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdarg.h>
#include <stdio.h>
B_DECLS_BEGIN;
#define b_stdin (z__b_stream_get_stdin())
#define b_stdout (z__b_stream_get_stdout())
#define b_stderr (z__b_stream_get_stderr())
#define B_TYPE_STREAM (b_stream_get_type())
#define B_TYPE_STREAM_BUFFER (b_stream_buffer_get_type())
B_DECLARE_TYPE(b_stream);
B_DECLARE_TYPE(b_stream_buffer);
typedef enum b_stream_mode {
B_STREAM_READ = 0x01u,
B_STREAM_WRITE = 0x02u,
B_STREAM_BINARY = 0x10u,
Z__B_STREAM_STATIC = 0x80u,
} b_stream_mode;
typedef enum b_stream_seek_origin {
B_STREAM_SEEK_START = 0x01u,
B_STREAM_SEEK_CURRENT = 0x02u,
B_STREAM_SEEK_END = 0x03u,
} b_stream_seek_origin;
typedef struct b_stream_cfg {
b_stream_mode s_mode;
} b_stream_cfg;
B_TYPE_CLASS_DECLARATION_BEGIN(b_stream)
b_status (*s_close)(b_stream *);
b_status (*s_seek)(b_stream *, long long, b_stream_seek_origin);
b_status (*s_tell)(const b_stream *, size_t *);
b_status (*s_getc)(b_stream *, b_wchar *);
b_status (*s_read)(b_stream *, void *, size_t, size_t *);
b_status (*s_write)(b_stream *, const void *, size_t, size_t *);
b_status (*s_reserve)(b_stream *, size_t);
B_TYPE_CLASS_DECLARATION_END(b_stream)
B_TYPE_CLASS_DECLARATION_BEGIN(b_stream_buffer)
B_TYPE_CLASS_DECLARATION_END(b_stream_buffer)
BLUE_API b_type b_stream_get_type();
BLUE_API b_type b_stream_buffer_get_type();
BLUE_API b_stream *z__b_stream_get_stdin(void);
BLUE_API b_stream *z__b_stream_get_stdout(void);
BLUE_API b_stream *z__b_stream_get_stderr(void);
BLUE_API b_stream_buffer *b_stream_buffer_create(void *p, size_t len);
BLUE_API b_stream_buffer *b_stream_buffer_create_dynamic(size_t buffer_size);
BLUE_API b_stream *b_stream_open_fp(FILE *fp);
BLUE_API b_status b_stream_reserve(b_stream *stream, size_t len);
BLUE_API b_status b_stream_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin);
BLUE_API size_t b_stream_cursor(const b_stream *stream);
BLUE_API b_status b_stream_push_indent(b_stream *stream, int indent);
BLUE_API b_status b_stream_pop_indent(b_stream *stream);
BLUE_API b_status b_stream_read_char(b_stream *stream, b_wchar *c);
BLUE_API b_status b_stream_read_bytes(
b_stream *stream, void *buf, size_t count, size_t *nr_read);
BLUE_API b_status b_stream_read_line(b_stream *stream, char *s, size_t max);
BLUE_API b_status b_stream_read_line_s(b_stream *src, b_stream *dest);
BLUE_API b_status b_stream_read_all_bytes(
b_stream *stream, void *p, size_t max, size_t *nr_read);
BLUE_API b_status b_stream_read_all_bytes_s(
b_stream *src, b_stream *dest, b_stream_buffer *buffer, size_t *nr_read);
BLUE_API b_status b_stream_write_char(b_stream *stream, b_wchar c);
BLUE_API b_status b_stream_write_string(
b_stream *stream, const char *s, size_t *nr_written);
BLUE_API b_status b_stream_write_bytes(
b_stream *stream, const void *buf, size_t count, size_t *nr_written);
BLUE_API b_status b_stream_write_fmt(
b_stream *stream, size_t *nr_written, const char *format, ...);
BLUE_API b_status b_stream_write_vfmt(
b_stream *stream, size_t *nr_written, const char *format, va_list arg);
B_DECLS_END;
#endif
-49
View File
@@ -1,49 +0,0 @@
#ifndef BLUE_CORE_STRINGSTREAM_H_
#define BLUE_CORE_STRINGSTREAM_H_
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <blue/core/stream.h>
#include <stddef.h>
B_DECLS_BEGIN;
#define B_TYPE_STRINGSTREAM (b_stringstream_get_type())
B_DECLARE_TYPE(b_stringstream);
B_TYPE_CLASS_DECLARATION_BEGIN(b_stringstream)
B_TYPE_CLASS_DECLARATION_END(b_stringstream)
BLUE_API b_type b_stringstream_get_type(void);
BLUE_API b_stringstream *b_stringstream_create(void);
BLUE_API b_stringstream *b_stringstream_create_with_buffer(char *buf, size_t max);
BLUE_API b_status b_stringstream_reset(b_stringstream *strv);
BLUE_API b_status b_stringstream_reset_with_buffer(
b_stringstream *strv, char *buf, size_t max);
BLUE_API const char *b_stringstream_ptr(const b_stringstream *strv);
BLUE_API char *b_stringstream_steal(b_stringstream *strv);
BLUE_API size_t b_stringstream_get_length(const b_stringstream *strv);
#if 0
BLUE_API void b_stringstream_push_indent(b_stringstream *strv, int indent);
BLUE_API void b_stringstream_pop_indent(b_stringstream *strv);
BLUE_API b_status b_stringstream_add(b_stringstream *strv, const char *str);
BLUE_API b_status b_stringstream_addf(b_stringstream *strv, const char *format, ...);
BLUE_API b_status b_stringstream_addv(b_stringstream *strv, const char **strs);
BLUE_API b_status b_stringstream_addvf(
b_stringstream *strv, const char *format, va_list arg);
BLUE_API b_status b_stringstream_addvl(
b_stringstream *strv, const char **strs, size_t count);
BLUE_API b_status b_stringstream_add_many(b_stringstream *strv, ...);
#endif
B_DECLS_END;
#endif
-36
View File
@@ -1,36 +0,0 @@
#ifndef BLUELIB_CORE_THREAD_H_
#define BLUELIB_CORE_THREAD_H_
#include <blue/core/bitop.h>
#include <blue/core/misc.h>
#include <stdbool.h>
#if defined(__APPLE__) || defined(__linux__)
#include <pthread.h>
#define B_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t b_mutex;
#else
#error Unsupported compiler/system
#endif
#define B_ONCE_INIT ((b_once)0)
typedef struct b_thread b_thread;
typedef int b_once;
static inline bool b_init_once(b_once *once)
{
int x = 0;
return b_cmpxchg(once, &x, 1);
}
BLUE_API b_thread *b_thread_self(void);
BLUE_API bool b_mutex_lock(b_mutex *mut);
BLUE_API bool b_mutex_trylock(b_mutex *mut);
BLUE_API bool b_mutex_unlock(b_mutex *mut);
#endif
-66
View File
@@ -1,66 +0,0 @@
#ifndef BLUE_CORE_TYPE_H_
#define BLUE_CORE_TYPE_H_
#include <blue/core/error.h>
#include <blue/core/misc.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define B_TYPE_MAX_INTERFACES 64
struct _b_class;
struct _b_object;
typedef void (*b_class_init_function)(struct _b_class *, void *);
typedef void (*b_instance_init_function)(struct _b_object *, void *);
typedef void (*b_instance_fini_function)(struct _b_object *, void *);
typedef const union b_type {
struct {
uint64_t p00, p01;
} a;
unsigned char b[16];
} *b_type;
typedef enum b_type_flags {
B_TYPE_F_ABSTRACT = 0x01u,
} b_type_flags;
typedef struct b_type_info {
union b_type t_id;
union b_type t_parent_id;
const char *t_name;
b_type_flags t_flags;
union b_type t_interfaces[B_TYPE_MAX_INTERFACES];
size_t t_nr_interfaces;
size_t t_class_size;
b_class_init_function t_class_init;
size_t t_instance_private_size;
size_t t_instance_protected_size;
b_instance_init_function t_instance_init;
b_instance_fini_function t_instance_fini;
} b_type_info;
BLUE_API void b_type_id_init(
union b_type *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
uint64_t e);
static inline void b_type_id_copy(b_type src, union b_type *dest)
{
dest->a.p00 = src->a.p00;
dest->a.p01 = src->a.p01;
}
static inline int b_type_id_compare(b_type a, b_type b)
{
if (a == b) {
return 0;
}
return memcmp(a, b, sizeof(union b_type));
}
BLUE_API b_result b_type_register(b_type_info *info);
#endif
-115
View File
@@ -1,115 +0,0 @@
#include <blue/core/iterator.h>
/*** PRIVATE DATA *************************************************************/
struct b_iterator_p {
enum b_status it_status;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static enum b_status iterator_get_status(const struct b_iterator_p *it)
{
return it->it_status;
}
static enum b_status iterator_set_status(struct b_iterator_p *it, b_status status)
{
it->it_status = status;
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_iterator *b_iterator_begin(b_iterable *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(b_iterable, B_TYPE_ITERABLE, NULL, it_begin, it);
}
const b_iterator *b_iterator_cbegin(const b_iterable *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(b_iterable, B_TYPE_ITERABLE, NULL, it_cbegin, it);
}
enum b_status b_iterator_get_status(const b_iterator *it)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_ITERATOR, iterator_get_status, it);
}
enum b_status b_iterator_set_status(const b_iterator *it, b_status status)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_ITERATOR, iterator_set_status, it, status);
}
enum b_status b_iterator_move_next(const b_iterator *it)
{
enum b_status status = B_ERR_NOT_SUPPORTED;
b_iterator_class *iface = b_object_get_interface(it, B_TYPE_ITERATOR);
if (iface && iface->it_move_next) {
status = iface->it_move_next(it);
}
struct b_iterator_p *p = b_object_get_private(it, B_TYPE_ITERATOR);
p->it_status = status;
return status;
}
b_iterator_value b_iterator_get_value(b_iterator *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(
b_iterator, B_TYPE_ITERATOR, B_ITERATOR_VALUE_NULL,
it_get_value, it);
}
const b_iterator_value b_iterator_get_cvalue(const b_iterator *it)
{
B_CLASS_DISPATCH_VIRTUAL_0(
b_iterator, B_TYPE_ITERATOR, B_ITERATOR_VALUE_NULL,
it_get_cvalue, it);
}
b_status b_iterator_erase(b_iterator *it)
{
enum b_status status = B_ERR_NOT_SUPPORTED;
b_iterator_class *iface = b_object_get_interface(it, B_TYPE_ITERATOR);
if (iface && iface->it_erase) {
status = iface->it_erase(it);
}
struct b_iterator_p *p = b_object_get_private(it, B_TYPE_ITERATOR);
p->it_status = status;
return status;
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_iterator)
B_TYPE_DEFINITION_BEGIN(b_iterator)
B_TYPE_FLAGS(B_TYPE_F_ABSTRACT);
B_TYPE_ID(0xfd40b67f, 0x7087, 0x40a9, 0x8fd8, 0x8ae27bd58c9e);
B_TYPE_CLASS(b_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_iterator_p);
B_TYPE_DEFINITION_END(b_iterator)
// ---- b_iterable DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_iterable)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_iterable)
B_TYPE_DEFINITION_BEGIN(b_iterable)
B_TYPE_FLAGS(B_TYPE_F_ABSTRACT);
B_TYPE_ID(0x4bbabf2d, 0xfc5d, 0x40cc, 0x89fc, 0x164085e47f73);
B_TYPE_CLASS(b_iterable_class);
B_TYPE_DEFINITION_END(b_iterable)
-219
View File
@@ -1,219 +0,0 @@
#include "object.h"
#include "type.h"
#include <assert.h>
#include <blue/core/class.h>
#include <blue/core/macros.h>
#include <blue/core/object.h>
#include <blue/core/stream.h>
#include <blue/core/thread.h>
B_TYPE_CLASS_DEFINITION_BEGIN(b_object)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_object)
B_TYPE_DEFINITION_BEGIN(b_object)
B_TYPE_ID(0x45f15a2c, 0x6831, 0x4bef, 0xb350, 0x15c650679211);
B_TYPE_CLASS(b_object_class);
B_TYPE_DEFINITION_END(b_object)
b_result b_object_instantiate(
struct b_type_registration *type, struct _b_object **out_object)
{
struct _b_object *out = malloc(type->r_instance_size);
if (!out) {
return B_RESULT_ERR(NO_MEMORY);
}
memset(out, 0x0, type->r_instance_size);
out->obj_magic = B_OBJECT_MAGIC;
out->obj_type = type;
out->obj_ref = 1;
struct b_queue_entry *entry = b_queue_first(&type->r_class_hierarchy);
while (entry) {
struct b_type_component *comp
= b_unbox(struct b_type_component, entry, c_entry);
const struct b_type_info *class_info = comp->c_type->r_info;
void *private_data
= (char *)out + comp->c_instance_private_data_offset;
if (class_info->t_instance_init) {
class_info->t_instance_init(out, private_data);
}
if (comp->c_type == type) {
out->obj_main_priv_offset
= comp->c_instance_private_data_offset;
}
entry = b_queue_next(entry);
}
*out_object = out;
return B_RESULT_SUCCESS;
}
struct _b_object *b_object_create(b_type type)
{
struct b_type_registration *type_reg = b_type_get_registration(type);
if (!type_reg) {
return NULL;
}
struct _b_object *out = NULL;
b_result result = b_object_instantiate(type_reg, &out);
if (b_result_is_error(result)) {
b_error_release(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
-224
View File
@@ -1,224 +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_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
-236
View File
@@ -1,236 +0,0 @@
#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);
}
}
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;
}
}
struct to_cstr_args {
char *str;
size_t max;
size_t ptr;
};
static void to_cstr(const struct b_rope *rope, void *arg)
{
struct to_cstr_args *str = arg;
if (str->ptr >= str->max) {
return;
}
unsigned int type = B_ROPE_TYPE(rope->r_flags);
char *dest = str->str + str->ptr;
size_t capacity = str->max - str->ptr;
size_t nr_written = 0;
switch (type) {
case B_ROPE_F_CHAR:
nr_written = snprintf(dest, capacity, "%c", rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
nr_written = snprintf(dest, capacity, "%s", rope->r_v.v_cstr.s);
break;
case B_ROPE_F_INT:
nr_written
= snprintf(dest, capacity, "%" PRIdPTR, rope->r_v.v_int);
break;
case B_ROPE_F_UINT:
nr_written
= snprintf(dest, capacity, "%" PRIuPTR, rope->r_v.v_uint);
break;
default:
break;
}
str->ptr += nr_written;
}
void b_rope_to_cstr(const struct b_rope *rope, char *out, size_t max)
{
struct to_cstr_args args = {
.str = out,
.max = max,
.ptr = 0,
};
rope_iterate(rope, to_cstr, &args);
}
-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;
}
}
-967
View File
@@ -1,967 +0,0 @@
#include "printf.h"
#include <blue/core/stream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define B_TYPE_STDIO_STREAM (b_stdio_stream_get_type())
#define STREAM_DISPATCH_VIRTUAL(func, stream, ...) \
do { \
struct stream_data _stream; \
enum b_status status = stream_get_data(stream, &_stream); \
if (!B_OK(status)) { \
return status; \
} \
return func(&_stream, __VA_ARGS__); \
} while (0)
#define STREAM_DISPATCH_VIRTUAL_0(func, stream) \
do { \
struct stream_data _stream; \
enum b_status status = stream_get_data(stream, &_stream); \
if (!B_OK(status)) { \
return status; \
} \
return func(&_stream); \
} while (0)
#define IDX_STDIN 0
#define IDX_STDOUT 1
#define IDX_STDERR 2
B_DECLARE_TYPE(b_stdio_stream);
B_TYPE_CLASS_DECLARATION_BEGIN(b_stdio_stream)
B_TYPE_CLASS_DECLARATION_END(b_stdio_stream)
/*** PRIVATE DATA *************************************************************/
typedef enum b_stream_buffer_flags {
B_STREAM_BUFFER_F_NONE = 0x00u,
B_STREAM_BUFFER_F_DYNAMIC = 0x01u,
} b_stream_buffer_flags;
struct b_stream_p {
int *s_istack;
int s_add_indent;
size_t s_istack_ptr, s_istack_size;
void *s_ptr0, *s_ptr1;
};
struct b_stdio_stream_p {
FILE *s_fp;
};
struct b_stream_buffer_p {
b_stream_buffer_flags p_flags;
void *p_buf;
size_t p_buf_len;
};
struct stream_data {
b_stream *s_obj;
struct b_stream_p *s_private;
struct b_stream_cfg *s_cfg;
b_stream_class *s_ops;
};
static b_stream *stdio[] = {
[IDX_STDIN] = NULL,
[IDX_STDOUT] = NULL,
[IDX_STDERR] = NULL,
};
/*** PRIVATE FUNCTIONS ********************************************************/
b_type b_stdio_stream_get_type(void);
static enum b_status stdio_read(b_stream *, void *, size_t, size_t *);
static enum b_status stdio_write(b_stream *, const void *, size_t, size_t *);
static enum b_status stdio_seek(b_stream *, long long, b_stream_seek_origin);
static enum b_status stdio_tell(const b_stream *, size_t *);
static enum b_status stream_get_data(const b_stream *strp, struct stream_data *out)
{
out->s_obj = (b_stream *)strp;
return b_object_get_data(
strp, B_TYPE_STREAM, (void **)&out->s_private,
(void **)&out->s_cfg, (void **)&out->s_ops);
}
static int current_indent(struct stream_data *stream)
{
if (!stream->s_private->s_istack || !stream->s_private->s_istack_size) {
return 0;
}
return stream->s_private->s_istack[stream->s_private->s_istack_ptr];
}
static size_t stream_cursor(const struct stream_data *stream)
{
if (!stream || !stream->s_ops || !stream->s_ops->s_tell) {
return B_NPOS;
}
size_t p = B_NPOS;
b_status status = stream->s_ops->s_tell(stream->s_obj, &p);
if (!B_OK(status)) {
return B_NPOS;
}
return p;
}
static enum b_status stream_seek(
struct stream_data *stream, long long offset, b_stream_seek_origin origin)
{
if (!stream || !stream->s_ops || !stream->s_ops->s_seek) {
return B_ERR_NOT_SUPPORTED;
}
return stream->s_ops->s_seek(stream->s_obj, offset, origin);
}
static enum b_status stream_reserve(struct stream_data *stream, size_t len)
{
if (!stream || !stream->s_ops || !stream->s_ops->s_reserve) {
return B_ERR_NOT_SUPPORTED;
}
return stream->s_ops->s_reserve(stream->s_obj, len);
}
static enum b_status read_char_binary(struct stream_data *stream, b_wchar *c)
{
size_t r;
unsigned char v = 0;
enum b_status status = stream->s_ops->s_read(stream->s_obj, &v, 1, &r);
*c = v;
if (status == B_SUCCESS && r < 1) {
status = B_ERR_NO_DATA;
}
return status;
}
static enum b_status read_char_utf8(struct stream_data *stream, b_wchar *c)
{
size_t r;
unsigned char s[4];
unsigned int len = 0;
enum b_status status = stream->s_ops->s_read(stream->s_obj, s, 1, &r);
if (!B_OK(status)) {
return status;
}
if (r < 1) {
return B_ERR_NO_DATA;
}
len = b_wchar_utf8_header_decode(s[0]);
if (len <= 0 || len > 4) {
return B_ERR_BAD_FORMAT;
}
if (len == 1) {
*c = s[0];
return B_SUCCESS;
}
status = stream->s_ops->s_read(stream->s_obj, s + 1, len - 1, &r);
if (!B_OK(status)) {
return status;
}
if (r != len - 1) {
return B_ERR_BAD_FORMAT;
}
b_wchar result = b_wchar_utf8_codepoint_decode((char *)s);
if (result == B_WCHAR_INVALID) {
return B_ERR_BAD_FORMAT;
}
*c = result;
return B_SUCCESS;
}
static enum b_status stream_read_char(struct stream_data *stream, b_wchar *c)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
#if 0
if (stream->s_ops->s_getc) {
return stream->s_ops->s_getc(stream->s_obj, c);
}
#endif
if (!stream->s_ops->s_read) {
return B_ERR_NOT_SUPPORTED;
}
if (stream->s_cfg->s_mode & B_STREAM_BINARY) {
return read_char_binary(stream, c);
}
return read_char_utf8(stream, c);
}
static enum b_status __write_char(struct stream_data *stream, b_wchar c)
{
size_t w, len;
enum b_status status;
char s[4];
if (stream->s_cfg->s_mode & B_STREAM_BINARY) {
s[0] = c & 0xFF;
len = 1;
} else {
len = b_wchar_utf8_codepoint_encode(c, s);
if (len == 0 || len > 4) {
return B_ERR_INVALID_ARGUMENT;
}
}
status = stream->s_ops->s_write(stream->s_obj, (unsigned char *)s, len, &w);
if (!B_OK(status)) {
return status;
}
if (status == B_SUCCESS && w < len) {
status = B_ERR_IO_FAILURE;
}
return status;
}
static enum b_status stream_write_char(struct stream_data *stream, b_wchar c)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (!stream->s_ops->s_write) {
return B_ERR_NOT_SUPPORTED;
}
if (c == '\n') {
stream->s_private->s_add_indent = 1;
}
if (!stream->s_private->s_istack_size) {
return __write_char(stream, c);
}
if (stream->s_private->s_add_indent && c != '\n') {
int indent = current_indent(stream);
for (int i = 0; i < indent; i++) {
__write_char(stream, ' ');
__write_char(stream, ' ');
}
stream->s_private->s_add_indent = 0;
}
__write_char(stream, c);
if (c == '\n') {
stream->s_private->s_add_indent = 1;
}
return B_SUCCESS;
}
static enum b_status stream_read_bytes(
struct stream_data *stream, void *buf, size_t count, size_t *nr_read)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (!stream->s_ops->s_read) {
return status;
}
return stream->s_ops->s_read(stream->s_obj, buf, count, nr_read);
}
static enum b_status stream_read_line(struct stream_data *stream, char *s, size_t max)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_SUCCESS;
size_t i = 0;
b_wchar c = 0;
while (1) {
if (i >= max) {
break;
}
status = stream_read_char(stream, &c);
if (status != B_SUCCESS) {
break;
}
if (c == '\n') {
break;
}
s[i++] = c;
s[i] = '\0';
}
return B_SUCCESS;
}
static enum b_status stream_read_line_s(
struct stream_data *src, struct stream_data *dest)
{
if (!(src->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
if (!(dest->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_SUCCESS;
size_t i = 0;
b_wchar c = 0;
while (1) {
status = stream_read_char(src, &c);
if (status != B_SUCCESS) {
break;
}
stream_write_char(dest, c);
i++;
if (c == '\n') {
break;
}
}
if (status == B_ERR_NO_DATA && i > 0) {
status = B_SUCCESS;
}
return status;
}
static enum b_status stream_write_bytes(
struct stream_data *stream, const void *buf, size_t count, size_t *nr_written)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (!stream->s_ops->s_write) {
return status;
}
return stream->s_ops->s_write(stream->s_obj, buf, count, nr_written);
}
static enum b_status stream_read_all_bytes(
struct stream_data *stream, void *p, size_t max, size_t *out_nr_read)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_SUCCESS;
size_t nr_read = 0;
unsigned char *s = p;
while (nr_read < max) {
int c;
status = stream_read_char(stream, &c);
if (status != B_SUCCESS) {
break;
}
s[nr_read++] = c;
}
if (status == B_ERR_NO_DATA && nr_read > 0) {
status = B_SUCCESS;
}
*out_nr_read = nr_read;
return status;
}
static enum b_status stream_read_all_bytes_s(
struct stream_data *src, struct stream_data *dest,
struct b_stream_buffer_p *buffer, size_t *out_nr_read)
{
if (!(src->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
if (!(dest->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
if (!buffer) {
return B_ERR_INVALID_ARGUMENT;
}
if (src->s_ops->s_seek && dest->s_ops->s_reserve) {
size_t offset = stream_cursor(src);
stream_seek(src, 0, B_STREAM_SEEK_END);
size_t length = stream_cursor(src);
stream_seek(src, offset, B_STREAM_SEEK_START);
stream_reserve(dest, length);
}
enum b_status status = B_SUCCESS;
size_t nr_read = 0;
while (1) {
size_t r = 0, w = 0;
status = stream_read_bytes(
src, buffer->p_buf, buffer->p_buf_len, &r);
if (status != B_SUCCESS) {
break;
}
status = stream_write_bytes(dest, buffer->p_buf, r, &w);
nr_read += w;
if (status != B_SUCCESS || w != buffer->p_buf_len) {
break;
}
}
if (status == B_ERR_NO_DATA && nr_read > 0) {
status = B_SUCCESS;
}
if (out_nr_read) {
*out_nr_read = nr_read;
}
return status;
}
static enum b_status stream_write_string(
struct stream_data *stream, const char *s, size_t *nr_written)
{
size_t i;
enum b_status status = B_SUCCESS;
for (i = 0; s[i]; i++) {
status = stream_write_char(stream, s[i]);
if (!B_OK(status)) {
break;
}
}
if (nr_written) {
*nr_written = i;
}
return status;
}
static b_stream *init_stdio_stream(FILE *fp, b_stream_mode mode)
{
b_stdio_stream *stream = b_object_create(B_TYPE_STDIO_STREAM);
if (!stream) {
return NULL;
}
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
b_stream_cfg *cfg = b_object_get_protected(stream, B_TYPE_STREAM);
p->s_fp = fp;
cfg->s_mode = mode;
return stream;
}
static enum b_status stream_push_indent(struct stream_data *stream, int indent)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
if (stream->s_cfg->s_mode & B_STREAM_BINARY) {
return B_ERR_NOT_SUPPORTED;
}
if (!stream->s_private->s_istack) {
stream->s_private->s_istack = calloc(4, sizeof(int));
stream->s_private->s_istack_size = 4;
stream->s_private->s_istack_ptr = 0;
}
if (stream->s_private->s_istack_ptr + 1 >= stream->s_private->s_istack_size) {
int *buf = realloc(
stream->s_private->s_istack,
(stream->s_private->s_istack_size + 4) * sizeof(int));
if (!buf) {
return B_ERR_NO_MEMORY;
}
stream->s_private->s_istack = buf;
stream->s_private->s_istack_size += 4;
}
int cur_indent
= stream->s_private->s_istack[stream->s_private->s_istack_ptr];
stream->s_private->s_istack[++stream->s_private->s_istack_ptr]
= cur_indent + indent;
return B_SUCCESS;
}
static enum b_status stream_pop_indent(struct stream_data *stream)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
if (stream->s_cfg->s_mode & B_STREAM_BINARY) {
return B_ERR_NOT_SUPPORTED;
}
if (!stream->s_private->s_istack || !stream->s_private->s_istack_size
|| !stream->s_private->s_istack_ptr) {
return B_SUCCESS;
}
stream->s_private->s_istack_ptr--;
return B_SUCCESS;
}
static void fctprintf_callback(char c, void *p)
{
struct stream_data *stream = p;
stream_write_char(stream, c);
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_stream *z__b_stream_get_stdin(void)
{
if (!stdio[IDX_STDIN]) {
stdio[IDX_STDIN] = init_stdio_stream(stdin, B_STREAM_READ);
}
return stdio[IDX_STDIN];
}
b_stream *z__b_stream_get_stdout(void)
{
if (!stdio[IDX_STDOUT]) {
stdio[IDX_STDOUT] = init_stdio_stream(stdout, B_STREAM_WRITE);
}
return stdio[IDX_STDOUT];
}
b_stream *z__b_stream_get_stderr(void)
{
if (!stdio[IDX_STDERR]) {
stdio[IDX_STDERR] = init_stdio_stream(stderr, B_STREAM_WRITE);
}
return stdio[IDX_STDERR];
}
b_stream_buffer *b_stream_buffer_create_dynamic(size_t buffer_size)
{
b_stream_buffer *buffer = b_object_create(B_TYPE_STREAM_BUFFER);
if (!buffer) {
return NULL;
}
struct b_stream_buffer_p *p
= b_object_get_private(buffer, B_TYPE_STREAM_BUFFER);
p->p_buf = malloc(buffer_size);
if (!p->p_buf) {
b_stream_buffer_unref(buffer);
return NULL;
}
p->p_buf_len = buffer_size;
p->p_flags = B_STREAM_BUFFER_F_DYNAMIC;
return buffer;
}
b_stream_buffer *b_stream_buffer_create(void *buf, size_t len)
{
b_stream_buffer *buffer = b_object_create(B_TYPE_STREAM_BUFFER);
if (!buffer) {
return NULL;
}
struct b_stream_buffer_p *p
= b_object_get_private(buffer, B_TYPE_STREAM_BUFFER);
p->p_buf = buf;
p->p_buf_len = len;
p->p_flags = 0;
return buffer;
}
b_stream *b_stream_open_fp(FILE *fp)
{
return init_stdio_stream(fp, B_STREAM_READ | B_STREAM_WRITE);
}
enum b_status b_stream_reserve(b_stream *stream, size_t len)
{
B_CLASS_DISPATCH_VIRTUAL(
b_stream, B_TYPE_STREAM, B_ERR_NOT_SUPPORTED, s_reserve, stream,
len);
}
enum b_status b_stream_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin)
{
B_CLASS_DISPATCH_VIRTUAL(
b_stream, B_TYPE_STREAM, B_ERR_NOT_SUPPORTED, s_seek, stream,
offset, origin);
}
size_t b_stream_cursor(const b_stream *stream)
{
STREAM_DISPATCH_VIRTUAL_0(stream_cursor, stream);
}
enum b_status b_stream_push_indent(b_stream *strp, int indent)
{
STREAM_DISPATCH_VIRTUAL(stream_push_indent, strp, indent);
}
enum b_status b_stream_pop_indent(b_stream *strp)
{
STREAM_DISPATCH_VIRTUAL_0(stream_pop_indent, strp);
}
enum b_status b_stream_read_char(b_stream *strp, int *c)
{
STREAM_DISPATCH_VIRTUAL(stream_read_char, strp, c);
}
enum b_status b_stream_read_bytes(
b_stream *strp, void *buf, size_t count, size_t *nr_read)
{
STREAM_DISPATCH_VIRTUAL(stream_read_bytes, strp, buf, count, nr_read);
}
enum b_status b_stream_read_line(b_stream *strp, char *s, size_t max)
{
STREAM_DISPATCH_VIRTUAL(stream_read_line, strp, s, max);
}
enum b_status b_stream_read_line_s(b_stream *src, b_stream *dest)
{
enum b_status status;
struct stream_data src_p, dest_p;
status = stream_get_data(src, &src_p);
if (!B_OK(status)) {
return status;
}
status = stream_get_data(dest, &dest_p);
if (!B_OK(status)) {
return status;
}
return stream_read_line_s(&src_p, &dest_p);
}
enum b_status b_stream_read_all_bytes(
b_stream *stream, void *p, size_t max, size_t *out_nr_read)
{
STREAM_DISPATCH_VIRTUAL(stream_read_all_bytes, stream, p, max, out_nr_read);
}
enum b_status b_stream_read_all_bytes_s(
b_stream *src, b_stream *dest, b_stream_buffer *buffer, size_t *out_nr_read)
{
enum b_status status;
struct stream_data src_p, dest_p;
struct b_stream_buffer_p *buffer_p;
status = stream_get_data(src, &src_p);
if (!B_OK(status)) {
return status;
}
status = stream_get_data(dest, &dest_p);
if (!B_OK(status)) {
return status;
}
buffer_p = b_object_get_private(buffer, B_TYPE_STREAM_BUFFER);
if (!buffer_p) {
return B_ERR_INVALID_ARGUMENT;
}
return stream_read_all_bytes_s(&src_p, &dest_p, buffer_p, out_nr_read);
}
enum b_status b_stream_write_char(b_stream *stream, b_wchar c)
{
STREAM_DISPATCH_VIRTUAL(stream_write_char, stream, c);
}
enum b_status b_stream_write_string(
b_stream *stream, const char *s, size_t *nr_written)
{
STREAM_DISPATCH_VIRTUAL(stream_write_string, stream, s, nr_written);
}
enum b_status b_stream_write_bytes(
b_stream *stream, const void *buf, size_t count, size_t *nr_written)
{
STREAM_DISPATCH_VIRTUAL(stream_write_bytes, stream, buf, count, nr_written);
}
enum b_status b_stream_write_fmt(
b_stream *stream, size_t *nr_written, const char *format, ...)
{
struct stream_data p;
enum b_status status = stream_get_data(stream, &p);
va_list arg;
va_start(arg, format);
int w = z__b_fctprintf(fctprintf_callback, &p, format, arg);
va_end(arg);
if (nr_written) {
*nr_written = w;
}
return B_SUCCESS;
}
enum b_status b_stream_write_vfmt(
b_stream *stream, size_t *nr_written, const char *format, va_list arg)
{
struct stream_data p;
enum b_status status = stream_get_data(stream, &p);
int w = z__b_fctprintf(fctprintf_callback, &p, format, arg);
if (nr_written) {
*nr_written = w;
}
return B_SUCCESS;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void stream_init(b_object *obj, void *priv)
{
struct b_stream_p *stream = priv;
}
static void stream_fini(b_object *obj, void *priv)
{
struct b_stream_p *stream = priv;
b_stream_class *ops = b_object_get_interface(obj, B_TYPE_STREAM);
if (stream->s_istack) {
free(stream->s_istack);
}
if (ops->s_close) {
ops->s_close(obj);
}
}
static void stream_buffer_init(b_object *obj, void *priv)
{
struct b_stream_buffer_p *buffer = priv;
}
static void stream_buffer_fini(b_object *obj, void *priv)
{
struct b_stream_buffer_p *buffer = priv;
if (buffer->p_flags & B_STREAM_BUFFER_F_DYNAMIC) {
free(buffer->p_buf);
}
}
static void stdio_stream_init(b_object *obj, void *priv)
{
struct b_stdio_stream_p *stream = priv;
}
static void stdio_stream_fini(b_object *obj, void *priv)
{
struct b_stdio_stream_p *stream = priv;
}
static enum b_status stdio_read(
b_stream *stream, void *out, size_t max, size_t *nr_read)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
enum b_status status = B_SUCCESS;
size_t count = fread(out, 1, max, p->s_fp);
if (ferror(p->s_fp)) {
status = B_ERR_IO_FAILURE;
}
*nr_read = count;
return status;
}
static enum b_status stdio_write(
b_stream *stream, const void *data, size_t count, size_t *nr_written)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
enum b_status status = B_SUCCESS;
size_t w = fwrite(data, 1, count, p->s_fp);
if (ferror(p->s_fp)) {
status = B_ERR_IO_FAILURE;
}
*nr_written = w;
return status;
}
static enum b_status stdio_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
int whence = 0;
switch (origin) {
case B_STREAM_SEEK_START:
whence = SEEK_SET;
break;
case B_STREAM_SEEK_CURRENT:
whence = SEEK_CUR;
break;
case B_STREAM_SEEK_END:
whence = SEEK_END;
break;
default:
return B_ERR_INVALID_ARGUMENT;
}
int ret = fseek(p->s_fp, offset, whence);
if (ret != 0) {
return B_ERR_NOT_SUPPORTED;
}
return B_SUCCESS;
}
static enum b_status stdio_tell(const b_stream *stream, size_t *cursor)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
long pos = ftell(p->s_fp);
if (pos == -1L) {
return B_ERR_NOT_SUPPORTED;
}
*cursor = (size_t)pos;
return B_SUCCESS;
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_stream DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_stream)
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_stream)
B_TYPE_DEFINITION_BEGIN(b_stream)
B_TYPE_ID(0xa2c98988, 0x30e5, 0x47c7, 0x88cd, 0x6c8ea79f69cd);
B_TYPE_CLASS(b_stream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stream_p);
B_TYPE_INSTANCE_PROTECTED(b_stream_cfg);
B_TYPE_INSTANCE_INIT(stream_init);
B_TYPE_INSTANCE_FINI(stream_fini);
B_TYPE_DEFINITION_END(b_stream)
// ---- b_stream_buffer DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_stream_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_stream_buffer)
B_TYPE_DEFINITION_BEGIN(b_stream_buffer)
B_TYPE_ID(0x575c7be1, 0x665f, 0x41f8, 0xbfed, 0x6269a2985be0);
B_TYPE_CLASS(b_stream_buffer_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stream_buffer_p);
B_TYPE_INSTANCE_INIT(stream_buffer_init);
B_TYPE_INSTANCE_FINI(stream_buffer_fini);
B_TYPE_DEFINITION_END(b_stream_buffer)
// ---- b_stdio_stream DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_stdio_stream)
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) = stdio_seek;
B_INTERFACE_ENTRY(s_tell) = stdio_tell;
B_INTERFACE_ENTRY(s_getc) = NULL;
B_INTERFACE_ENTRY(s_read) = stdio_read;
B_INTERFACE_ENTRY(s_write) = stdio_write;
B_INTERFACE_ENTRY(s_reserve) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)
B_TYPE_CLASS_DEFINITION_END(b_stdio_stream)
B_TYPE_DEFINITION_BEGIN(b_stdio_stream)
B_TYPE_ID(0x67678926, 0xd0b7, 0x4f99, 0xb83c, 0x790927597645);
B_TYPE_EXTENDS(B_TYPE_STREAM);
B_TYPE_CLASS(b_stdio_stream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stdio_stream_p);
B_TYPE_INSTANCE_INIT(stdio_stream_init);
B_TYPE_INSTANCE_FINI(stdio_stream_fini);
B_TYPE_DEFINITION_END(b_stdio_stream)
-232
View File
@@ -1,232 +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_len;
size_t ss_max;
unsigned char ss_alloc;
};
/*** PRIVATE FUNCTIONS ********************************************************/
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_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_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_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) = NULL;
B_INTERFACE_ENTRY(s_read) = NULL;
B_INTERFACE_ENTRY(s_write) = stream_write;
B_INTERFACE_ENTRY(s_reserve) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)
B_TYPE_CLASS_DEFINITION_END(b_stringstream)
B_TYPE_DEFINITION_BEGIN(b_stringstream)
B_TYPE_ID(0x508a609a, 0xfac5, 0x4d31, 0x843a, 0x44b68ad329f3);
B_TYPE_EXTENDS(B_TYPE_STREAM);
B_TYPE_CLASS(b_stringstream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stringstream_p);
B_TYPE_INSTANCE_INIT(stringstream_init);
B_TYPE_INSTANCE_FINI(stringstream_fini);
B_TYPE_DEFINITION_END(b_stringstream)
-319
View File
@@ -1,319 +0,0 @@
#include "type.h"
#include "class.h"
#include "object.h"
#include <blue/core/btree.h>
#include <blue/core/endian.h>
#include <blue/core/object.h>
#include <blue/core/type.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct b_btree type_list = B_BTREE_INIT;
static union b_type zero_id = {0};
struct type_init_ctx {
size_t ctx_class_offset;
size_t ctx_instance_offset;
};
static inline int registration_compare(
const struct b_type_registration *a, const struct b_type_registration *b)
{
return b_type_id_compare(&a->r_info->t_id, &b->r_info->t_id);
}
static inline int component_compare(
const struct b_type_component *a, const struct b_type_component *b)
{
return b_type_id_compare(&a->c_type->r_info->t_id, &b->c_type->r_info->t_id);
}
B_BTREE_DEFINE_INSERT(
struct b_type_registration, r_node, r_info->r_id, put_type,
registration_compare)
B_BTREE_DEFINE_INSERT(
struct b_type_component, c_node, &c_type->r_info->t_id,
put_type_component, component_compare)
static struct b_type_registration *get_type(
const b_btree *tree, const union b_type *key)
{
b_btree_node *cur = tree->b_root;
while (cur) {
struct b_type_registration *cur_node
= b_unbox(struct b_type_registration, cur, r_node);
int cmp = b_type_id_compare(key, &cur_node->r_info->t_id);
if (cmp > 0) {
cur = b_btree_right(cur);
} else if (cmp < 0) {
cur = b_btree_left(cur);
} else {
return cur_node;
}
}
return NULL;
}
struct b_type_component *b_type_get_component(
const b_btree *tree, const union b_type *key)
{
b_btree_node *cur = tree->b_root;
while (cur) {
struct b_type_component *cur_node
= b_unbox(struct b_type_component, cur, c_node);
int cmp = b_type_id_compare(key, &cur_node->c_type->r_info->t_id);
if (cmp > 0) {
cur = b_btree_right(cur);
} else if (cmp < 0) {
cur = b_btree_left(cur);
} else {
return cur_node;
}
}
return NULL;
}
static struct b_type_component *create_type_component(
const struct b_type_registration *type_reg)
{
struct b_type_component *c = malloc(sizeof *c);
if (!c) {
return NULL;
}
memset(c, 0x0, sizeof *c);
c->c_type = type_reg;
return c;
}
void b_type_id_init(
union b_type *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
uint64_t e)
{
b_i32 x_a = b_i32_htob(a);
b_i16 x_b = b_i16_htob(b);
b_i16 x_c = b_i16_htob(c);
b_i16 x_d = b_i16_htob(d);
b_i64 x_e = b_i64_htob(e);
memcpy(&out->b[0], x_a.i_bytes, sizeof x_a.i_bytes);
memcpy(&out->b[4], x_b.i_bytes, sizeof x_b.i_bytes);
memcpy(&out->b[6], x_c.i_bytes, sizeof x_c.i_bytes);
memcpy(&out->b[8], x_d.i_bytes, sizeof x_d.i_bytes);
memcpy(&out->b[10], &x_e.i_bytes[2], sizeof x_e.i_bytes - 2);
}
static void initialise_type_component(
struct b_type_component *comp, const struct b_type_info *info,
struct type_init_ctx *init_ctx)
{
comp->c_class_data_offset = init_ctx->ctx_class_offset;
comp->c_class_data_size = info->t_class_size;
init_ctx->ctx_class_offset += comp->c_class_data_size;
comp->c_instance_private_data_offset = init_ctx->ctx_instance_offset;
comp->c_instance_private_data_size = info->t_instance_private_size;
init_ctx->ctx_instance_offset += comp->c_instance_private_data_size;
comp->c_instance_protected_data_offset = init_ctx->ctx_instance_offset;
comp->c_instance_protected_data_size = info->t_instance_protected_size;
init_ctx->ctx_instance_offset += comp->c_instance_protected_data_size;
}
static b_result locate_interface(
b_type interface_id, struct b_type_registration *dest,
struct type_init_ctx *init_ctx)
{
struct b_type_component *interface_comp
= b_type_get_component(&dest->r_components, interface_id);
if (interface_comp) {
return B_RESULT_SUCCESS;
}
struct b_type_registration *interface_reg
= get_type(&type_list, interface_id);
if (!interface_reg) {
return B_RESULT_ERR(NO_ENTRY);
}
interface_comp = create_type_component(interface_reg);
if (!interface_comp) {
return B_RESULT_ERR(NO_MEMORY);
}
initialise_type_component(interface_comp, interface_reg->r_info, init_ctx);
put_type_component(&dest->r_components, interface_comp);
return B_RESULT_SUCCESS;
}
static b_result locate_interfaces(
const union b_type *interfaces, size_t nr_interfaces,
struct b_type_registration *dest, struct type_init_ctx *init_ctx)
{
b_result result = B_RESULT_SUCCESS;
for (size_t i = 0; i < nr_interfaces; i++) {
b_type interface_id = &interfaces[i];
result = locate_interface(interface_id, dest, init_ctx);
if (b_result_is_error(result)) {
break;
}
}
return result;
}
static b_result find_type_components(struct b_type_registration *reg)
{
const struct b_type_info *current = reg->r_info;
struct b_type_component *comp = create_type_component(reg);
if (!comp) {
return B_RESULT_ERR(NO_MEMORY);
}
struct type_init_ctx init_ctx = {
.ctx_instance_offset = sizeof(struct _b_object),
.ctx_class_offset = sizeof(struct _b_class),
};
put_type_component(&reg->r_components, comp);
b_queue_push_front(&reg->r_class_hierarchy, &comp->c_entry);
b_result result = locate_interfaces(
current->t_interfaces, current->t_nr_interfaces, reg, &init_ctx);
if (b_result_is_error(result)) {
return result;
}
b_type current_id = &current->t_parent_id;
if (!current_id || b_type_id_compare(current_id, &zero_id) == 0) {
goto skip_class_hierarchy;
}
while (1) {
struct b_type_registration *dep_class
= get_type(&type_list, current_id);
if (!dep_class) {
return B_RESULT_ERR(NO_ENTRY);
}
comp = b_type_get_component(&reg->r_components, current_id);
if (comp) {
/* circular class dependency */
// result = B_RESULT_ERR(INVALID_ARGUMENT);
// break;
current_id = &dep_class->r_info->t_parent_id;
continue;
}
comp = create_type_component(dep_class);
result = locate_interfaces(
dep_class->r_info->t_interfaces,
dep_class->r_info->t_nr_interfaces, reg, &init_ctx);
if (b_result_is_error(result)) {
break;
}
put_type_component(&reg->r_components, comp);
b_queue_push_front(&reg->r_class_hierarchy, &comp->c_entry);
if (b_type_id_compare(current_id, B_TYPE_OBJECT) == 0) {
break;
}
current_id = &dep_class->r_info->t_parent_id;
}
b_queue_entry *entry = b_queue_first(&reg->r_class_hierarchy);
while (entry) {
comp = b_unbox(struct b_type_component, entry, c_entry);
initialise_type_component(comp, comp->c_type->r_info, &init_ctx);
entry = b_queue_next(entry);
}
b_btree_node *node = b_btree_first(&reg->r_components);
while (node) {
comp = b_unbox(struct b_type_component, node, c_node);
if (comp->c_type->r_category == B_TYPE_CLASS) {
/* this component was already initialised above */
node = b_btree_next(node);
continue;
}
initialise_type_component(comp, comp->c_type->r_info, &init_ctx);
node = b_btree_next(node);
}
skip_class_hierarchy:
reg->r_instance_size = init_ctx.ctx_instance_offset;
reg->r_class_size = init_ctx.ctx_class_offset;
return result;
}
static bool type_has_base_class(struct b_type_info *info)
{
if (b_type_id_compare(&info->t_id, B_TYPE_OBJECT) == 0) {
return true;
}
return b_type_id_compare(&info->t_parent_id, &zero_id) != 0;
}
b_result b_type_register(struct b_type_info *info)
{
if (!type_has_base_class(info)) {
b_type_id_copy(B_TYPE_OBJECT, &info->t_parent_id);
}
struct b_type_registration *r = get_type(&type_list, &info->t_id);
if (r) {
return B_RESULT_ERR(NAME_EXISTS);
}
r = malloc(sizeof *r);
if (!r) {
return B_RESULT_ERR(NO_MEMORY);
}
memset(r, 0x0, sizeof *r);
r->r_category = B_TYPE_CLASS;
r->r_info = info;
b_result result = find_type_components(r);
if (b_result_is_error(result)) {
free(r);
return b_result_propagate(result);
}
result = b_class_instantiate(r, &r->r_class);
if (!r->r_class) {
free(r);
return b_error_with_msg_template_caused_by_error(
B_ERRORS_BUILTIN, B_ERR_TYPE_REGISTRATION_FAILURE,
result, B_MSG_TYPE_REGISTRATION_FAILURE,
B_ERROR_PARAM("typename", info->t_name));
}
put_type(&type_list, r);
return B_RESULT_SUCCESS;
}
struct b_type_registration *b_type_get_registration(b_type id)
{
return get_type(&type_list, id);
}
-40
View File
@@ -1,40 +0,0 @@
#ifndef _TYPE_H_
#define _TYPE_H_
#include <blue/core/btree.h>
#include <blue/core/queue.h>
#include <blue/core/type.h>
#include <stddef.h>
enum b_type_category {
B_TYPE_NONE = 0,
B_TYPE_CLASS,
B_TYPE_INTERFACE,
};
struct b_type_component {
struct b_btree_node c_node;
struct b_queue_entry c_entry;
const struct b_type_registration *c_type;
size_t c_class_data_offset, c_class_data_size;
size_t c_instance_private_data_offset, c_instance_private_data_size;
size_t c_instance_protected_data_offset, c_instance_protected_data_size;
};
struct b_type_registration {
enum b_type_category r_category;
struct b_btree_node r_node;
const b_type_info *r_info;
struct _b_class *r_class;
struct b_btree r_components;
struct b_queue r_class_hierarchy;
size_t r_instance_size, r_class_size;
};
extern struct b_type_registration *b_type_get_registration(b_type id);
extern struct b_type_component *b_type_get_component(
const b_btree *tree, const union b_type *key);
#endif
-20
View File
@@ -1,20 +0,0 @@
#include <blue/ds/array.h>
#include <blue/ds/number.h>
#include <stdio.h>
int main(void)
{
b_array *array = b_array_create();
b_array_append(array, B_RV_INT(32));
b_array_append(array, B_RV_INT(64));
b_array_append(array, B_RV_INT(128));
b_array_iterator it;
b_array_foreach(&it, array)
{
printf("object %p\n", it.value);
}
b_array_unref(array);
return 0;
}
-50
View File
@@ -1,50 +0,0 @@
#include <CuTest.h>
#include <blue/ds/string.h>
static void test_string_create(CuTest *tc)
{
b_string *str = b_string_create();
CuAssertPtrNotNull(tc, str);
CuAssertIntEquals(tc, 0, b_string_get_size(str, B_STRLEN_NORMAL));
CuAssertStrEquals(tc, "", b_string_ptr(str));
b_string_unref(str);
str = b_string_create_from_c('A', 8);
CuAssertPtrNotNull(tc, str);
CuAssertIntEquals(tc, 8, b_string_get_size(str, B_STRLEN_NORMAL));
CuAssertStrEquals(tc, "AAAAAAAA", b_string_ptr(str));
b_string_unref(str);
str = b_string_create_from_cstr("Hello, world!");
CuAssertPtrNotNull(tc, str);
CuAssertIntEquals(tc, 13, b_string_get_size(str, B_STRLEN_NORMAL));
CuAssertStrEquals(tc, "Hello, world!", b_string_ptr(str));
b_string_unref(str);
}
static void test_string_length(CuTest *tc)
{
const char *cstr = "Hello, \033[91;1mworld!";
b_string *s = b_string_create_from_cstr(cstr);
CuAssertIntEquals(tc, 13, b_string_get_size(s, B_STRLEN_IGNORE_ESC));
CuAssertIntEquals(tc, 20, b_string_get_size(s, B_STRLEN_NORMAL));
b_string_unref(s);
}
CuSuite *get_all_tests(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_string_create);
SUITE_ADD_TEST(suite, test_string_length);
return suite;
}
-11
View File
@@ -1,11 +0,0 @@
#include <blue/ds/number.h>
#include <stdio.h>
int main(void)
{
b_number *number = b_number_create_float(6.8);
printf("number=%zd\n", B_NUMBER_IVAL(number));
b_number_unref(number);
return 0;
}
-11
View File
@@ -1,11 +0,0 @@
#include <blue/ds/string.h>
int main(void)
{
b_string *string = B_CSTR("Hello, world!");
printf("string object = ");
b_object_to_string(string, b_stdout);
printf("\n");
b_string_unref(string);
return 0;
}
-19
View File
@@ -1,19 +0,0 @@
#include <blue/core/stream.h>
#include <blue/core/stringstream.h>
#include <blue/ds/string.h>
#include <stdio.h>
int main(int argc, const char **argv)
{
size_t nr_read = 0;
b_stringstream *dest_stream = b_stringstream_create();
b_stream_buffer *buf = b_stream_buffer_create_dynamic(1024);
b_stream_read_all_bytes_s(b_stdin, dest_stream, buf, &nr_read);
printf("done. read %zu bytes total.\n", nr_read);
printf("%s\n", b_stringstream_ptr(dest_stream));
b_stringstream_unref(dest_stream);
b_stream_buffer_unref(buf);
return 0;
}
-43
View File
@@ -1,43 +0,0 @@
#include <blue/core/stringstream.h>
#include <blue/ds/string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("-------------\n");
b_string *str = b_string_create_from_cstr("Hello, world!\n");
printf("%s\n", b_string_ptr(str));
printf("len:%zu, max:%zu\n", b_string_get_size(str, B_STRLEN_NORMAL),
b_string_get_capacity(str));
b_string_insert_cstr(str, "WOW!", 4);
printf("-------------\n");
printf("%s\n", b_string_ptr(str));
printf("len:%zu, max:%zu\n", b_string_get_size(str, B_STRLEN_NORMAL),
b_string_get_capacity(str));
b_string_replace(str, 4, 4, "+");
printf("-------------\n");
printf("%s\n", b_string_ptr(str));
printf("len:%zu, max:%zu\n", b_string_get_size(str, B_STRLEN_NORMAL),
b_string_get_capacity(str));
printf("-------------\n");
b_string_unref(str);
b_stringstream *strv = b_stringstream_create();
b_stream_write_string(strv, "Hello", NULL);
b_stream_write_string(strv, ", world", NULL);
b_stream_write_string(strv, "!", NULL);
char *s = b_stringstream_steal(strv);
b_stringstream_unref(strv);
printf("%s\n", s);
free(s);
return 0;
}
-119
View File
@@ -1,119 +0,0 @@
#include <blue/core/btree.h>
#include <blue/ds/dict.h>
#include <blue/ds/number.h>
#include <blue/ds/tree.h>
#include <stdio.h>
#define NITEMS 16
struct tree_item {
int value;
b_tree_node node;
};
struct btree_item {
int value;
b_btree_node node;
};
B_BTREE_DEFINE_SIMPLE_GET(struct btree_item, int, node, value, get_node)
B_BTREE_DEFINE_SIMPLE_INSERT(struct btree_item, node, value, put_node)
int main(void)
{
b_dict_item items[]
= {B_DICT_ITEM("hello", B_RV_INT(32)),
B_DICT_ITEM("world", B_RV_INT(64)),
B_DICT_ITEM("more", B_RV_INT(128)),
B_DICT_ITEM("other", B_RV_INT(256)), B_DICT_ITEM_END};
b_dict *dict = b_dict_create_with_items(items);
b_dict_iterator it;
b_dict_foreach(&it, dict)
{
printf("item %zu: %s=%d\n", it.i, b_string_ptr(it.key),
b_number_get_int(it.value));
}
b_tree *tree = b_tree_create();
struct tree_item items2[NITEMS];
for (int i = 0; i < NITEMS; i++) {
items2[i].value = i;
items2[i].node = B_TREE_NODE_INIT;
}
b_tree_set_root(tree, &items2[0].node);
b_tree_node_add_child(&items2[0].node, &items2[1].node);
b_tree_node_add_child(&items2[0].node, &items2[2].node);
b_tree_node_add_child(&items2[0].node, &items2[3].node);
b_tree_node_add_child(&items2[0].node, &items2[7].node);
b_tree_node_add_child(&items2[1].node, &items2[4].node);
b_tree_node_add_child(&items2[1].node, &items2[5].node);
b_tree_node_add_child(&items2[4].node, &items2[6].node);
b_tree_iterator it2;
b_tree_foreach(&it2, tree)
{
struct tree_item *item = b_unbox(struct tree_item, it2.node, node);
for (size_t i = 0; i < it2.depth; i++) {
fputs(" ", stdout);
}
printf("%u\n", item->value);
}
b_btree btree = {0};
struct btree_item items3[NITEMS] = {0};
for (int i = 0; i < NITEMS; i++) {
items3[i].value = i;
put_node(&btree, &items3[i]);
}
printf("\n\n");
b_btree_iterator it3;
b_btree_foreach (&it3, &btree) {
struct btree_item *item
= b_unbox(struct btree_item, it3.node, node);
for (size_t i = 0; i < it3.depth; i++) {
fputs(" ", stdout);
}
printf("%d\n", item->value);
}
b_btree_iterator_begin(&btree, &it3);
while (b_btree_iterator_is_valid(&it3)) {
struct btree_item *item
= b_unbox(struct btree_item, it3.node, node);
if (item->value == 9) {
b_btree_iterator_erase(&it3);
} else {
b_btree_iterator_next(&it3);
}
}
printf("\n\n");
b_btree_foreach (&it3, &btree) {
struct btree_item *item
= b_unbox(struct btree_item, it3.node, node);
for (size_t i = 0; i < it3.depth; i++) {
fputs(" ", stdout);
}
printf("%d\n", item->value);
}
b_tree_unref(tree);
b_dict_unref(dict);
return 0;
}
-26
View File
@@ -1,26 +0,0 @@
#include <blue/core/stringstream.h>
#include <blue/ds/string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("здравс\u26A0твуите\n");
b_string *str = b_string_create_from_cstr("здравствуите");
const char *s = b_string_ptr(str);
printf("%s\n", s);
printf("len: %zu\n", b_string_get_size(str, B_STRLEN_NORMAL));
printf("codepoints: %zu\n", b_string_get_size(str, B_STRLEN_CODEPOINTS));
b_string_iterator it;
const char *delims[] = {"в"};
size_t nr_delims = sizeof delims / sizeof delims[0];
b_string_tokenise(str, delims, nr_delims, 0, &it);
while (b_string_iterator_is_valid(&it)) {
printf("%s\n", it.string_value);
b_string_iterator_next(&it);
}
return 0;
}
-14
View File
@@ -1,14 +0,0 @@
#include <blue/ds/uuid.h>
#include <stdio.h>
int main(void)
{
b_uuid *uuid = b_uuid_create_from_cstr(
"5b80ad1f-367f-4a1f-88f3-b3a6f8d1f63d");
char str[B_UUID_STRING_MAX];
b_uuid_to_cstr(uuid, str);
printf("%s\n", str);
b_uuid_unref(uuid);
return 0;
}
-3
View File
@@ -1,3 +0,0 @@
include(../cmake/Templates.cmake)
add_bluelib_module(NAME ds DEPENDENCIES core)
-519
View File
@@ -1,519 +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 {
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 {
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)
View File
View File
-330
View File
@@ -1,330 +0,0 @@
#include <blue/core/bitop.h>
#include <blue/core/stream.h>
#include <blue/ds/bitmap.h>
#include <string.h>
#define BITS_PER_WORD (8 * sizeof(bitmap_word_t))
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define BITMAP_WORDS(nbits) DIV_ROUND_UP(nbits, BITS_PER_WORD)
/*** PRIVATE DATA *************************************************************/
typedef unsigned long bitmap_word_t;
struct b_bitmap_p {
bitmap_word_t *map_words;
size_t map_nr_words, map_nr_bits;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static void bitmap_set_bit(struct b_bitmap_p *map, size_t bit)
{
unsigned long index = bit / BITS_PER_WORD;
unsigned long offset = (BITS_PER_WORD - bit - 1) & (BITS_PER_WORD - 1);
unsigned long mask = 1ul << offset;
map->map_words[index] |= mask;
}
static void bitmap_clear_bit(struct b_bitmap_p *map, size_t bit)
{
unsigned long index = bit / BITS_PER_WORD;
unsigned long offset = bit & (BITS_PER_WORD - 1);
unsigned long mask = 1ul << offset;
map->map_words[index] &= ~mask;
}
static void bitmap_set_range(struct b_bitmap_p *map, size_t first_bit, size_t nbits)
{
}
static void bitmap_clear_range(struct b_bitmap_p *map, size_t first_bit, size_t nbits)
{
}
static void bitmap_set_all(struct b_bitmap_p *map)
{
memset(map->map_words, 0xFF, map->map_nr_words * sizeof(bitmap_word_t));
}
static void bitmap_clear_all(struct b_bitmap_p *map)
{
memset(map->map_words, 0x00, map->map_nr_words * sizeof(bitmap_word_t));
}
static bool bitmap_check_bit(const struct b_bitmap_p *map, size_t bit)
{
unsigned long index = bit / BITS_PER_WORD;
unsigned long offset = (BITS_PER_WORD - bit - 1) & (BITS_PER_WORD - 1);
unsigned long mask = 1ul << offset;
return (map->map_words[index] & mask) != 0;
}
static size_t bitmap_count_set_bits(const struct b_bitmap_p *map)
{
size_t set_bits = 0;
for (size_t i = 0; i < map->map_nr_words; i++) {
set_bits += b_popcountl(map->map_words[i]);
}
if (set_bits > map->map_nr_bits) {
set_bits = map->map_nr_bits;
}
return set_bits;
}
static size_t bitmap_count_clear_bits(const struct b_bitmap_p *map)
{
size_t clear_bits = 0;
for (size_t i = 0; i < map->map_nr_words; i++) {
clear_bits += b_popcountl(~map->map_words[i]);
}
if (clear_bits > map->map_nr_bits) {
clear_bits = map->map_nr_bits;
}
return clear_bits;
}
static size_t bitmap_highest_set_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = 0;
unsigned long i;
for (i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != 0x00) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
}
}
if (last_word == 0x00) {
return B_NPOS;
}
return bit_index + (BITS_PER_WORD - b_ctzl(last_word) - 1);
}
static size_t bitmap_highest_clear_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = ~(bitmap_word_t)0;
for (unsigned long i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != (~(unsigned long)0)) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
}
}
if (last_word == ~(unsigned long)0) {
return B_NPOS;
}
if (last_word == 0) {
return bit_index + BITS_PER_WORD - 1;
}
return bit_index + (BITS_PER_WORD - b_ctzl(~last_word)) - 1;
}
static size_t bitmap_lowest_set_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = 0;
unsigned long i;
for (i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != 0x00) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
break;
}
}
if (last_word == 0x00) {
return B_NPOS;
}
return bit_index + b_clzl(last_word);
}
static size_t bitmap_lowest_clear_bit(const struct b_bitmap_p *map)
{
unsigned long bit_index = 0;
bitmap_word_t last_word = 0;
unsigned long i;
for (i = 0; i < map->map_nr_words; i++) {
if (map->map_words[i] != (~(unsigned long)0)) {
last_word = map->map_words[i];
bit_index = i * BITS_PER_WORD;
break;
}
}
if (last_word == 0) {
return bit_index;
}
if (last_word == (~(bitmap_word_t)0)) {
return B_NPOS;
}
return bit_index + b_clzl(~last_word);
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_bitmap *b_bitmap_create(size_t nr_bits)
{
b_bitmap *map = b_object_create(B_TYPE_BITMAP);
if (!map) {
return NULL;
}
struct b_bitmap_p *p = b_object_get_private(map, B_TYPE_BITMAP);
p->map_nr_bits = nr_bits;
p->map_nr_words = BITMAP_WORDS(nr_bits);
p->map_words = calloc(p->map_nr_words, sizeof(bitmap_word_t));
if (!p->map_words) {
b_bitmap_unref(map);
return NULL;
}
return map;
}
void b_bitmap_set_bit(b_bitmap *map, size_t bit)
{
B_CLASS_DISPATCH_STATIC_V(B_TYPE_BITMAP, bitmap_set_bit, map, bit);
}
void b_bitmap_clear_bit(b_bitmap *map, size_t bit)
{
B_CLASS_DISPATCH_STATIC_V(B_TYPE_BITMAP, bitmap_clear_bit, map, bit);
}
void b_bitmap_set_range(b_bitmap *map, size_t first_bit, size_t nbits)
{
B_CLASS_DISPATCH_STATIC_V(
B_TYPE_BITMAP, bitmap_set_range, map, first_bit, nbits);
}
void b_bitmap_clear_range(b_bitmap *map, size_t first_bit, size_t nbits)
{
B_CLASS_DISPATCH_STATIC_V(
B_TYPE_BITMAP, bitmap_clear_range, map, first_bit, nbits);
}
void b_bitmap_set_all(b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_V0(B_TYPE_BITMAP, bitmap_set_all, map);
}
void b_bitmap_clear_all(b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_V0(B_TYPE_BITMAP, bitmap_clear_all, map);
}
bool b_bitmap_check_bit(const b_bitmap *map, size_t bit)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BITMAP, bitmap_check_bit, map, bit);
}
size_t b_bitmap_count_set_bits(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_count_set_bits, map);
}
size_t b_bitmap_count_clear_bits(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_count_clear_bits, map);
}
size_t b_bitmap_highest_set_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_highest_set_bit, map);
}
size_t b_bitmap_highest_clear_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_highest_clear_bit, map);
}
size_t b_bitmap_lowest_set_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_lowest_set_bit, map);
}
size_t b_bitmap_lowest_clear_bit(const b_bitmap *map)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BITMAP, bitmap_lowest_clear_bit, map);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void bitmap_init(b_object *obj, void *priv)
{
struct b_bitmap_p *map = priv;
}
static void bitmap_fini(b_object *obj, void *priv)
{
struct b_bitmap_p *map = priv;
}
static void bitmap_to_string(const b_object *obj, b_stream *out)
{
const struct b_bitmap_p *map = b_object_get_private(obj, B_TYPE_BITMAP);
unsigned char *bytes = (unsigned char *)map->map_words;
size_t nr_bytes = map->map_nr_words * sizeof(bitmap_word_t);
unsigned char c = 0;
for (size_t i = 0; i < nr_bytes - 1; i++) {
c = bytes[i];
b_stream_write_fmt(
out, NULL, "%c%c%c%c%c%c%c%c", c & 0x80 ? '1' : '0',
c & 0x40 ? '1' : '0', c & 0x20 ? '1' : '0',
c & 0x10 ? '1' : '0', c & 0x08 ? '1' : '0',
c & 0x04 ? '1' : '0', c & 0x02 ? '1' : '0',
c & 0x01 ? '1' : '0');
}
unsigned char mask = 0x80;
size_t remaining_bits = map->map_nr_bits - ((nr_bytes - 1) * 8);
c = bytes[nr_bytes - 1];
for (size_t i = 0; i < remaining_bits; i++) {
b_stream_write_fmt(out, NULL, "%c", (c & mask) ? '1' : '0');
}
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_bitmap)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = bitmap_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_bitmap)
B_TYPE_DEFINITION_BEGIN(b_bitmap)
B_TYPE_ID(0xea115cef, 0x8a63, 0x445f, 0x9474, 0xba9309d5dde8);
B_TYPE_CLASS(b_bitmap_class);
B_TYPE_INSTANCE_PRIVATE(struct b_bitmap_p);
B_TYPE_INSTANCE_INIT(bitmap_init);
B_TYPE_INSTANCE_FINI(bitmap_fini);
B_TYPE_DEFINITION_END(b_bitmap)
/*** ITERATOR FUNCTIONS *******************************************************/
-441
View File
@@ -1,441 +0,0 @@
#include <blue/core/iterator.h>
#include <blue/ds/buffer.h>
#include <stdlib.h>
#include <string.h>
/*** PRIVATE DATA *************************************************************/
struct b_buffer_p {
/* number of items in buffer */
unsigned int buf_len;
/* maximum number of items that can currently be stored in array */
unsigned int buf_cap;
/* the size of each individual item in the buffer */
unsigned int buf_itemsz;
void *buf_data;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static b_status resize_buffer(struct b_buffer_p *buffer, size_t new_capacity)
{
if (buffer->buf_cap < new_capacity) {
void *new_data = realloc(
buffer->buf_data, new_capacity * buffer->buf_itemsz);
if (!new_data) {
return B_ERR_NO_MEMORY;
}
buffer->buf_data = new_data;
} else {
void *new_data = realloc(
buffer->buf_data, new_capacity * buffer->buf_itemsz);
if (!new_data) {
return B_ERR_NO_MEMORY;
}
buffer->buf_data = new_data;
}
buffer->buf_cap = new_capacity;
if (buffer->buf_len > new_capacity) {
buffer->buf_len = new_capacity;
}
return B_SUCCESS;
}
static void *buffer_steal(struct b_buffer_p *buf)
{
void *p = buf->buf_data;
buf->buf_data = NULL;
buf->buf_len = 0;
buf->buf_cap = 0;
return p;
}
static enum b_status buffer_reserve(struct b_buffer_p *buf, size_t capacity)
{
if (buf->buf_cap >= capacity) {
return B_SUCCESS;
}
return resize_buffer(buf, capacity);
}
static enum b_status buffer_resize(struct b_buffer_p *buf, size_t length)
{
enum b_status status = resize_buffer(buf, length);
if (!B_OK(status)) {
return status;
}
buf->buf_len = length;
return B_SUCCESS;
}
static enum b_status buffer_insert(
struct b_buffer_p *buffer, const void *p, size_t count, size_t at)
{
if (at == B_NPOS) {
at = buffer->buf_len;
}
if (at > buffer->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
b_status status = B_SUCCESS;
if (buffer->buf_len + count > buffer->buf_cap) {
status = resize_buffer(buffer, buffer->buf_cap + count);
if (status != B_SUCCESS) {
return status;
}
}
unsigned char *src
= (unsigned char *)buffer->buf_data + (at * buffer->buf_itemsz);
unsigned char *dest = src + (count * buffer->buf_itemsz);
size_t move_len = (buffer->buf_len - at) * buffer->buf_itemsz;
memmove(dest, src, move_len);
memcpy(src, p, count * buffer->buf_itemsz);
buffer->buf_len += count;
return B_SUCCESS;
}
static enum b_status buffer_remove(struct b_buffer_p *buffer, size_t at, size_t count)
{
if (at >= buffer->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
if (at + count >= buffer->buf_len) {
count = buffer->buf_len - at;
}
unsigned char *dest = buffer->buf_data + (at * buffer->buf_itemsz);
unsigned char *src = dest + (count * buffer->buf_itemsz);
size_t move_len = (buffer->buf_len - at - count) * buffer->buf_itemsz;
memmove(dest, src, move_len);
buffer->buf_len -= count;
return B_SUCCESS;
}
static void *buffer_ptr(const struct b_buffer_p *buffer)
{
return buffer->buf_data;
}
static void *buffer_get(const struct b_buffer_p *buffer, size_t at)
{
if (at >= buffer->buf_len) {
return NULL;
}
return (unsigned char *)buffer->buf_data + (at * buffer->buf_itemsz);
}
static size_t buffer_size(const struct b_buffer_p *buffer)
{
return buffer->buf_len;
}
static size_t buffer_capacity(const struct b_buffer_p *buffer)
{
return buffer->buf_cap;
}
static enum b_status buffer_clear(struct b_buffer_p *buffer)
{
buffer->buf_len = 0;
return B_SUCCESS;
}
static enum b_status buffer_push_back(
struct b_buffer_p *buf, size_t count, void **p)
{
enum b_status status = B_SUCCESS;
if (buf->buf_len + count > buf->buf_cap) {
status = resize_buffer(buf, buf->buf_len + count);
}
if (!B_OK(status)) {
return status;
}
buf->buf_len += count;
*p = buffer_get(buf, buf->buf_len - count);
return B_SUCCESS;
}
static enum b_status buffer_push_front(
struct b_buffer_p *buf, size_t count, void **p)
{
enum b_status status = B_SUCCESS;
if (buf->buf_len + count > buf->buf_cap) {
status = resize_buffer(buf, buf->buf_len + count);
}
if (!B_OK(status)) {
return status;
}
void *src = buf->buf_data;
void *dest = b_buffer_get(buf->buf_data, count);
size_t len = count * buf->buf_itemsz;
memmove(dest, src, len);
buf->buf_len += count;
*p = buffer_get(buf, 0);
return B_SUCCESS;
}
static enum b_status buffer_pop_back(struct b_buffer_p *buf, size_t count)
{
if (count > buf->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
buf->buf_len -= count;
return B_SUCCESS;
}
static enum b_status buffer_pop_front(struct b_buffer_p *buf, size_t count)
{
if (count > buf->buf_len) {
return B_ERR_OUT_OF_BOUNDS;
}
void *src = b_buffer_get(buf->buf_data, count);
void *dest = buf->buf_data;
size_t len = (buf->buf_len - count) * buf->buf_itemsz;
memmove(dest, src, len);
buf->buf_len -= count;
return B_SUCCESS;
}
static size_t buffer_get_size(const struct b_buffer_p *buf)
{
return buf->buf_len;
}
static size_t buffer_get_item_size(const struct b_buffer_p *buf)
{
return buf->buf_itemsz;
}
static size_t buffer_get_capacity(const struct b_buffer_p *buf)
{
return buf->buf_cap;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_buffer *b_buffer_create(size_t item_sz)
{
b_buffer *buffer = b_object_create(B_TYPE_BUFFER);
if (!buffer) {
return NULL;
}
struct b_buffer_p *p = b_object_get_private(buffer, B_TYPE_BUFFER);
p->buf_itemsz = item_sz;
return buffer;
}
b_buffer *b_buffer_create_from_bytes(const void *buf, size_t len)
{
b_buffer *buffer = b_object_create(B_TYPE_BUFFER);
if (!buffer) {
return NULL;
}
struct b_buffer_p *p = b_object_get_private(buffer, B_TYPE_BUFFER);
p->buf_len = len;
p->buf_cap = len;
p->buf_itemsz = 1;
p->buf_data = calloc(len, 1);
if (!p->buf_data) {
b_buffer_unref(buffer);
return NULL;
}
memcpy(p->buf_data, buf, len);
return buffer;
}
b_buffer *b_buffer_create_from_array(const void *buf, size_t item_sz, size_t len)
{
b_buffer *buffer = b_object_create(B_TYPE_BUFFER);
if (!buffer) {
return NULL;
}
struct b_buffer_p *p = b_object_get_private(buffer, B_TYPE_BUFFER);
p->buf_len = len;
p->buf_cap = len;
p->buf_itemsz = item_sz;
p->buf_data = calloc(len, item_sz);
if (!p->buf_data) {
b_buffer_unref(buffer);
return NULL;
}
memcpy(p->buf_data, buf, len * item_sz);
return buffer;
}
void *b_buffer_steal(b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_steal, buf);
}
enum b_status b_buffer_reserve(b_buffer *buf, size_t capacity)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_reserve, buf, capacity);
}
enum b_status b_buffer_resize(b_buffer *buf, size_t length)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_resize, buf, length);
}
enum b_status b_buffer_insert(
b_buffer *buffer, const void *p, size_t count, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_insert, buffer, p, count, at);
}
enum b_status b_buffer_remove(b_buffer *buffer, size_t at, size_t count)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_remove, buffer, at, count);
}
void *b_buffer_ptr(const b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_ptr, buffer);
}
void *b_buffer_get(const b_buffer *buffer, size_t at)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_get, buffer, at);
}
size_t b_buffer_size(const b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_size, buffer);
}
size_t b_buffer_capacity(const b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_capacity, buffer);
}
enum b_status b_buffer_clear(b_buffer *buffer)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_clear, buffer);
}
enum b_status b_buffer_push_back(b_buffer *buf, size_t count, void **p)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_push_back, buf, count, p);
}
enum b_status b_buffer_push_front(b_buffer *buf, size_t count, void **p)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_push_front, buf, count, p);
}
enum b_status b_buffer_pop_back(b_buffer *buf, size_t count)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_pop_back, buf, count);
}
enum b_status b_buffer_pop_front(b_buffer *buf, size_t count)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_BUFFER, buffer_pop_front, buf, count);
}
size_t b_buffer_get_size(const b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_get_size, buf);
}
size_t b_buffer_get_item_size(const b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_get_item_size, buf);
}
size_t b_buffer_get_capacity(const b_buffer *buf)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_BUFFER, buffer_get_capacity, buf);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
enum b_status b_buffer_append(b_buffer *buffer, const void *p, size_t count)
{
return b_buffer_insert(buffer, p, count, B_NPOS);
}
enum b_status b_buffer_prepend(b_buffer *buffer, const void *p, size_t count)
{
return b_buffer_insert(buffer, p, count, 0);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
void buffer_init(b_object *obj, void *priv)
{
struct b_buffer_p *buffer = priv;
}
void buffer_fini(b_object *obj, void *priv)
{
struct b_buffer_p *buffer = priv;
if (buffer->buf_data) {
free(buffer->buf_data);
buffer->buf_data = NULL;
}
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_buffer)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_buffer)
B_TYPE_DEFINITION_BEGIN(b_buffer)
B_TYPE_ID(0x323e6858, 0x7a43, 0x4484, 0xa6fb, 0xe3d1e47ae637);
B_TYPE_CLASS(b_buffer_class);
B_TYPE_INSTANCE_PRIVATE(struct b_buffer_p);
B_TYPE_INSTANCE_INIT(buffer_init);
B_TYPE_INSTANCE_FINI(buffer_fini);
B_TYPE_DEFINITION_END(b_buffer)
-723
View File
@@ -1,723 +0,0 @@
#include <blue/core/status.h>
#include <blue/core/stream.h>
#include <blue/ds/dict.h>
#include <blue/ds/string.h>
#include <stdbool.h>
#include <stdlib.h>
#define HASH_OFFSET_BASIS 0xcbf29ce484222325
#define HASH_PRIME 0x100000001b3
/*** PRIVATE DATA *************************************************************/
struct b_dict_bucket_item {
b_queue_entry bi_entry;
b_string *bi_str;
b_object *bi_value;
};
struct b_dict_bucket {
b_btree_node bk_node;
uint64_t bk_hash;
b_queue bk_items;
};
struct b_dict_p {
b_btree d_buckets;
};
struct b_dict_iterator_p {
size_t i;
b_dict_item item;
b_dict *_d;
struct b_dict_p *_d_p;
b_btree_node *_cbn;
b_queue_entry *_cqe;
};
/*** MISC FUNCTIONS ***********************************************************/
static B_BTREE_DEFINE_SIMPLE_GET(
struct b_dict_bucket, uint64_t, bk_node, bk_hash, get_bucket);
static B_BTREE_DEFINE_SIMPLE_INSERT(
struct b_dict_bucket, bk_node, bk_hash, put_bucket);
uint64_t b_cstr_hash(const char *s)
{
uint64_t hash = HASH_OFFSET_BASIS;
for (size_t i = 0; s[i]; i++) {
hash *= HASH_PRIME;
hash ^= s[i];
}
return hash;
}
/*** PRIVATE FUNCTIONS ********************************************************/
static struct b_dict_bucket *create_bucket(void)
{
struct b_dict_bucket *bucket = malloc(sizeof *bucket);
if (!bucket) {
return NULL;
}
memset(bucket, 0x0, sizeof *bucket);
return bucket;
}
static struct b_dict_bucket_item *create_bucket_item(void)
{
struct b_dict_bucket_item *item = malloc(sizeof *item);
if (!item) {
return NULL;
}
memset(item, 0x0, sizeof *item);
return item;
}
static b_status dict_put(struct b_dict_p *dict, const char *key, b_object *value)
{
uint64_t hash = b_cstr_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
bucket->bk_hash = hash;
put_bucket(&dict->d_buckets, bucket);
}
struct b_dict_bucket_item *item = create_bucket_item();
if (!item) {
return B_ERR_NO_MEMORY;
}
item->bi_str = b_string_create_from_cstr(key);
item->bi_value = b_object_ref(value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
return B_SUCCESS;
}
static b_status dict_put_sk(
struct b_dict_p *dict, const b_string *key, b_object *value)
{
uint64_t hash = b_string_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
bucket->bk_hash = hash;
put_bucket(&dict->d_buckets, bucket);
}
struct b_dict_bucket_item *item = create_bucket_item();
if (!item) {
return B_ERR_NO_MEMORY;
}
item->bi_str = b_string_duplicate(key);
item->bi_value = b_object_ref(value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
return B_SUCCESS;
}
static b_object *dict_at(const struct b_dict_p *dict, const char *key)
{
uint64_t hash = b_cstr_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
return NULL;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item
= b_unbox(struct b_dict_bucket_item, entry, bi_entry);
if (!strcmp(b_string_ptr(item->bi_str), key)) {
return item->bi_value;
}
entry = b_queue_next(entry);
}
return NULL;
}
static b_object *dict_at_sk(const struct b_dict_p *dict, const b_string *key)
{
uint64_t hash = b_string_hash(key);
struct b_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
if (!bucket) {
return NULL;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item
= b_unbox(struct b_dict_bucket_item, entry, bi_entry);
if (b_string_compare(item->bi_str, key)) {
return item->bi_value;
}
entry = b_queue_next(entry);
}
return NULL;
}
static b_object *dict_get(struct b_dict_p *dict, const char *key)
{
b_object *value = dict_at(dict, key);
if (value) {
b_object_ref(value);
}
return value;
}
static b_object *dict_get_sk(struct b_dict_p *dict, const b_string *key)
{
b_object *value = dict_at_sk(dict, key);
if (value) {
b_object_ref(value);
}
return value;
}
static bool dict_has_key(const struct b_dict_p *dict, const char *key)
{
return dict_at(dict, key) != NULL;
}
static bool dict_has_skey(const struct b_dict_p *dict, const b_string *key)
{
return dict_at_sk(dict, key) != NULL;
}
static size_t dict_get_size(const struct b_dict_p *dict)
{
size_t count = 0;
#if 0
b_btree_iterator it1;
b_queue_iterator it2;
b_btree_foreach (&it1, &dict->d_buckets) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, it1.node, bk_node);
b_queue_foreach (&it2, &bucket->bk_items) {
count++;
}
}
#endif
return count;
}
static bool dict_is_empty(const struct b_dict_p *dict)
{
b_btree_node *first_node = b_btree_first(&dict->d_buckets);
struct b_dict_bucket *first_bucket
= b_unbox(struct b_dict_bucket, first_node, bk_node);
if (!first_bucket) {
return true;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_dict_bucket_item *first_item
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
if (!first_item) {
return true;
}
return false;
}
static bool get_next_node(
struct b_btree_node *cur_node, struct b_queue_entry *cur_entry,
struct b_btree_node **out_next_node, struct b_queue_entry **out_next_entry)
{
struct b_dict_bucket *cur_bucket
= b_unbox(struct b_dict_bucket, cur_node, bk_node);
if (!cur_bucket) {
return false;
}
struct b_dict_bucket_item *cur_item
= b_unbox(struct b_dict_bucket_item, cur_entry, bi_entry);
if (!cur_item) {
return false;
}
struct b_btree_node *next_node = cur_node;
struct b_queue_entry *next_entry = b_queue_next(cur_entry);
if (!next_entry) {
next_node = b_btree_next(cur_node);
if (!next_node) {
return false;
}
struct b_dict_bucket *next_bucket
= b_unbox(struct b_dict_bucket, next_node, bk_node);
if (!next_bucket) {
return false;
}
next_entry = b_queue_first(&next_bucket->bk_items);
if (!next_entry) {
return false;
}
}
struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
if (!next_item) {
return false;
}
*out_next_node = next_node;
*out_next_entry = next_entry;
return true;
}
static b_status delete_item(
struct b_dict_p *dict, struct b_dict_bucket *bucket,
struct b_dict_bucket_item *item)
{
b_queue_delete(&bucket->bk_items, &item->bi_entry);
free(item);
if (b_queue_empty(&bucket->bk_items)) {
b_btree_delete(&dict->d_buckets, &bucket->bk_node);
free(bucket);
}
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
#if 0
b_dict *b_dict_create_with_items(const b_dict_item *items)
{
b_dict *dict = b_dict_create();
if (!dict) {
return NULL;
}
struct b_dict_p *p = b_object_get_private(dict, B_TYPE_DICT);
for (size_t i = 0; items[i].key; i++) {
dict_put(p, items[i].key, items[i].value);
}
return dict;
}
#endif
b_status b_dict_put(b_dict *dict, const char *key, b_object *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put, dict, key, value);
}
b_status b_dict_put_sk(b_dict *dict, const b_string *key, b_object *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_put_sk, dict, key, value);
}
b_object *b_dict_at(const b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_at, dict, key);
}
b_object *b_dict_at_sk(const b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_at_sk, dict, key);
}
b_object *b_dict_get(b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_get, dict, key);
}
b_object *b_dict_get_sk(b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_get_sk, dict, key);
}
bool b_dict_has_key(const b_dict *dict, const char *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_has_key, dict, key);
}
bool b_dict_has_skey(const b_dict *dict, const b_string *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_DICT, dict_has_skey, dict, key);
}
size_t b_dict_get_size(const b_dict *dict)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_DICT, dict_get_size, dict);
}
bool b_dict_is_empty(const b_dict *dict)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_DICT, dict_is_empty, dict);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void dict_init(b_object *obj, void *priv)
{
struct b_dict_p *dict = priv;
}
static void dict_fini(b_object *obj, void *priv)
{
struct b_dict_p *dict = priv;
struct b_btree_node *node = b_btree_first(&dict->d_buckets);
while (node) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, node, bk_node);
struct b_btree_node *next_node = b_btree_next(node);
b_btree_delete(&dict->d_buckets, node);
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item = b_unbox(
struct b_dict_bucket_item, entry, bi_entry);
struct b_queue_entry *next_entry = b_queue_next(entry);
b_queue_delete(&bucket->bk_items, entry);
free(item->bi_str);
b_object_unref(item->bi_value);
free(item);
entry = next_entry;
}
free(bucket);
node = next_node;
}
}
static void dict_to_string(const b_object *obj, b_stream *out)
{
struct b_dict_p *dict = b_object_get_private(obj, B_TYPE_DICT);
if (dict_is_empty(dict)) {
b_stream_write_string(out, "{}", NULL);
return;
}
b_stream_write_string(out, "{\n", NULL);
b_stream_push_indent(out, 1);
size_t len = dict_get_size(dict);
size_t i = 0;
struct b_btree_node *node = b_btree_first(&dict->d_buckets);
while (node) {
struct b_dict_bucket *bucket
= b_unbox(struct b_dict_bucket, node, bk_node);
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_dict_bucket_item *item = b_unbox(
struct b_dict_bucket_item, entry, bi_entry);
b_object_to_string(item->bi_str, out);
b_stream_write_string(out, ": ", NULL);
bool is_string
= b_object_is_type(item->bi_value, B_TYPE_STRING);
if (is_string) {
b_stream_write_char(out, '"');
}
b_object_to_string(item->bi_value, out);
if (is_string) {
b_stream_write_char(out, '"');
}
if (i < len - 1) {
b_stream_write_string(out, ",", NULL);
}
b_stream_write_char(out, '\n');
entry = b_queue_next(entry);
i++;
}
node = b_btree_next(node);
}
b_stream_pop_indent(out);
b_stream_write_char(out, '}');
}
/*** ITERATOR FUNCTIONS *******************************************************/
static b_iterator *iterable_begin(b_dict *dict)
{
b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR);
if (!it_obj) {
return NULL;
}
struct b_dict_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR);
it->i = 0;
it->_d = dict;
it->_d_p = b_object_get_private(dict, B_TYPE_DICT);
if (dict_is_empty(it->_d_p)) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets);
struct b_dict_bucket *first_bucket
= b_unbox(struct b_dict_bucket, first_node, bk_node);
if (!first_bucket) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_dict_bucket_item *first_item
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
if (!first_item) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
it->item.key = first_item->bi_str;
it->item.value = first_item->bi_value;
it->_d = dict;
it->_cbn = first_node;
it->_cqe = first_entry;
return it_obj;
}
static const b_iterator *iterable_cbegin(const b_dict *dict)
{
b_iterator *it_obj = b_object_create(B_TYPE_DICT_ITERATOR);
if (!it_obj) {
return NULL;
}
struct b_dict_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_DICT_ITERATOR);
it->i = 0;
it->_d = (b_dict *)dict;
it->_d_p = b_object_get_private(dict, B_TYPE_DICT);
if (dict_is_empty(it->_d_p)) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_btree_node *first_node = b_btree_first(&it->_d_p->d_buckets);
struct b_dict_bucket *first_bucket
= b_unbox(struct b_dict_bucket, first_node, bk_node);
if (!first_bucket) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_dict_bucket_item *first_item
= b_unbox(struct b_dict_bucket_item, first_entry, bi_entry);
if (!first_item) {
it->item.key = NULL;
it->item.value = NULL;
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
it->item.key = first_item->bi_str;
it->item.value = first_item->bi_value;
it->_cbn = first_node;
it->_cqe = first_entry;
return it_obj;
}
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
it->item.key = NULL;
it->item.value = NULL;
return B_ERR_NO_DATA;
}
struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
if (!next_item) {
it->item.key = NULL;
it->item.value = NULL;
return B_ERR_NO_DATA;
}
it->i++;
it->item.key = next_item->bi_str;
it->item.value = next_item->bi_value;
it->_cbn = next_node;
it->_cqe = next_entry;
return B_SUCCESS;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
if ((it->item.key || it->item.value) && !(it->_cbn && it->_cqe)) {
return B_ERR_BAD_STATE;
}
if (!it->item.key || !it->_cqe) {
return B_ERR_NO_DATA;
}
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
it->item.key = NULL;
it->item.value = NULL;
return B_ERR_NO_DATA;
}
struct b_dict_bucket *cur_bucket
= b_unbox(struct b_dict_bucket, it->_cbn, bk_node);
struct b_dict_bucket_item *cur_item
= b_unbox(struct b_dict_bucket_item, it->_cqe, bi_entry);
struct b_dict_bucket_item *next_item
= b_unbox(struct b_dict_bucket_item, next_entry, bi_entry);
b_status status = delete_item(it->_d_p, cur_bucket, cur_item);
if (B_ERR(status)) {
return status;
}
if (next_item) {
it->item.key = next_item->bi_str;
it->item.value = next_item->bi_value;
it->_cbn = next_node;
it->_cqe = next_entry;
} else {
it->item.key = NULL;
it->item.value = NULL;
it->_cbn = NULL;
it->_cqe = NULL;
}
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
return B_ITERATOR_VALUE_PTR(&it->item);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
struct b_dict_iterator_p *it
= b_object_get_private(obj, B_TYPE_DICT_ITERATOR);
return B_ITERATOR_VALUE_CPTR(&it->item);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_dict DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = dict_to_string;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = iterable_begin;
B_INTERFACE_ENTRY(it_cbegin) = iterable_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_dict)
B_TYPE_DEFINITION_BEGIN(b_dict)
B_TYPE_ID(0xd2af61d9, 0xd0be, 0x4960, 0xbe3f, 0x509749814c10);
B_TYPE_CLASS(b_dict_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_dict_p);
B_TYPE_INSTANCE_INIT(dict_init);
B_TYPE_INSTANCE_FINI(dict_fini);
B_TYPE_DEFINITION_END(b_dict)
// ---- b_dict_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_dict_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_dict_iterator)
B_TYPE_DEFINITION_BEGIN(b_dict_iterator)
B_TYPE_ID(0x9ea96701, 0x1713, 0x4a3e, 0xbf63, 0xdc856b456f3b);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_dict_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_dict_iterator_p);
B_TYPE_DEFINITION_END(b_dict_iterator)
-598
View File
@@ -1,598 +0,0 @@
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <blue/ds/hashmap.h>
#include <blue/ds/string.h>
#include <stdbool.h>
#include <stdlib.h>
#define HASH_OFFSET_BASIS 0xcbf29ce484222325
#define HASH_PRIME 0x100000001b3
/*** PRIVATE DATA *************************************************************/
struct b_hashmap_bucket_item {
struct b_queue_entry bi_entry;
struct b_hashmap_key bi_key;
struct b_hashmap_value bi_value;
};
struct b_hashmap_bucket {
struct b_btree_node bk_node;
uint64_t bk_hash;
struct b_queue bk_items;
};
struct b_hashmap_p {
size_t h_count;
struct b_btree h_buckets;
b_hashmap_key_destructor h_key_dtor;
b_hashmap_value_destructor h_value_dtor;
};
struct b_hashmap_iterator_p {
size_t i;
b_hashmap_item item;
b_hashmap *_h;
struct b_hashmap_p *_h_p;
b_btree_node *_cbn;
b_queue_entry *_cqe;
};
/*** PRIVATE FUNCTIONS ********************************************************/
static B_BTREE_DEFINE_SIMPLE_GET(
struct b_hashmap_bucket, uint64_t, bk_node, bk_hash, get_bucket);
static B_BTREE_DEFINE_SIMPLE_INSERT(
struct b_hashmap_bucket, bk_node, bk_hash, put_bucket);
static uint64_t hash_data(const void *p, size_t size)
{
const unsigned char *s = p;
uint64_t hash = HASH_OFFSET_BASIS;
for (size_t i = 0; s[i]; i++) {
hash *= HASH_PRIME;
hash ^= s[i];
}
return hash;
}
static uint64_t hash_key(const struct b_hashmap_key *key)
{
if (key->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
return hash_data(&key->key_data, sizeof key->key_data);
} else {
return hash_data(key->key_data, key->key_size);
}
}
static bool compare_key(
const struct b_hashmap_key *a, const struct b_hashmap_key *b)
{
const void *a_data = NULL, *b_data = NULL;
size_t a_len = 0, b_len = 0;
if (a->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
a_data = &a->key_data;
a_len = sizeof a->key_data;
} else {
a_data = a->key_data;
a_len = a->key_size;
}
if (b->key_flags & B_HASHMAP_KEY_F_INTVALUE) {
b_data = &b->key_data;
b_len = sizeof b->key_data;
} else {
b_data = b->key_data;
b_len = b->key_size;
}
if (a_len != b_len) {
return false;
}
size_t cmp_len = a_len;
return memcmp(a_data, b_data, cmp_len) == 0;
}
static bool get_next_node(
struct b_btree_node *cur_node, struct b_queue_entry *cur_entry,
struct b_btree_node **out_next_node, struct b_queue_entry **out_next_entry)
{
struct b_hashmap_bucket *cur_bucket
= b_unbox(struct b_hashmap_bucket, cur_node, bk_node);
if (!cur_bucket) {
return false;
}
struct b_hashmap_bucket_item *cur_item
= b_unbox(struct b_hashmap_bucket_item, cur_entry, bi_entry);
if (!cur_item) {
return false;
}
struct b_btree_node *next_node = cur_node;
struct b_queue_entry *next_entry = b_queue_next(cur_entry);
if (!next_entry) {
next_node = b_btree_next(cur_node);
if (!next_node) {
return false;
}
struct b_hashmap_bucket *next_bucket
= b_unbox(struct b_hashmap_bucket, next_node, bk_node);
if (!next_bucket) {
return false;
}
next_entry = b_queue_first(&next_bucket->bk_items);
if (!next_entry) {
return false;
}
}
struct b_hashmap_bucket_item *next_item
= b_unbox(struct b_hashmap_bucket_item, next_entry, bi_entry);
if (!next_item) {
return false;
}
*out_next_node = next_node;
*out_next_entry = next_entry;
return true;
}
static struct b_hashmap_bucket *create_bucket(void)
{
struct b_hashmap_bucket *bucket = malloc(sizeof *bucket);
if (!bucket) {
return NULL;
}
memset(bucket, 0x0, sizeof *bucket);
return bucket;
}
static struct b_hashmap_bucket_item *create_bucket_item(void)
{
struct b_hashmap_bucket_item *item = malloc(sizeof *item);
if (!item) {
return NULL;
}
memset(item, 0x0, sizeof *item);
return item;
}
static b_status hashmap_put(
struct b_hashmap_p *hashmap, const b_hashmap_key *key,
const b_hashmap_value *value)
{
uint64_t hash = hash_key(key);
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
if (!bucket) {
bucket = create_bucket();
if (!bucket) {
return B_ERR_NO_MEMORY;
}
bucket->bk_hash = hash;
put_bucket(&hashmap->h_buckets, bucket);
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item
= b_unbox(struct b_hashmap_bucket_item, entry, bi_entry);
if (compare_key(&item->bi_key, key)) {
memcpy(&item->bi_value, value, sizeof *value);
return B_SUCCESS;
}
entry = b_queue_next(entry);
}
struct b_hashmap_bucket_item *item = create_bucket_item();
if (!item) {
return B_ERR_NO_MEMORY;
}
memcpy(&item->bi_key, key, sizeof *key);
memcpy(&item->bi_value, value, sizeof *value);
b_queue_push_back(&bucket->bk_items, &item->bi_entry);
hashmap->h_count++;
return B_SUCCESS;
}
static const struct b_hashmap_value *hashmap_get(
const struct b_hashmap_p *hashmap, const struct b_hashmap_key *key)
{
uint64_t hash = hash_key(key);
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
if (!bucket) {
return NULL;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item
= b_unbox(struct b_hashmap_bucket_item, entry, bi_entry);
if (compare_key(&item->bi_key, key)) {
return &item->bi_value;
}
entry = b_queue_next(entry);
}
return NULL;
}
static bool hashmap_has_key(
const struct b_hashmap_p *hashmap, const b_hashmap_key *key)
{
uint64_t hash = hash_key(key);
struct b_hashmap_bucket *bucket = get_bucket(&hashmap->h_buckets, hash);
if (!bucket) {
return false;
}
struct b_queue_entry *entry = b_queue_first(&bucket->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item
= b_unbox(struct b_hashmap_bucket_item, entry, bi_entry);
if (compare_key(&item->bi_key, key)) {
return true;
}
entry = b_queue_next(entry);
}
return false;
}
static size_t hashmap_get_size(const struct b_hashmap_p *hashmap)
{
return hashmap->h_count;
}
static bool hashmap_is_empty(const struct b_hashmap_p *hashmap)
{
b_btree_node *first_node = b_btree_first(&hashmap->h_buckets);
struct b_hashmap_bucket *first_bucket
= b_unbox(struct b_hashmap_bucket, first_node, bk_node);
if (!first_bucket) {
return true;
}
b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_hashmap_bucket_item *first_item
= b_unbox(struct b_hashmap_bucket_item, first_entry, bi_entry);
if (!first_item) {
return true;
}
return false;
}
static b_status delete_item(
struct b_hashmap_p *hashmap, struct b_hashmap_bucket *bucket,
struct b_hashmap_bucket_item *item)
{
b_queue_delete(&bucket->bk_items, &item->bi_entry);
if (hashmap->h_key_dtor) {
hashmap->h_key_dtor((void *)item->bi_key.key_data);
}
if (hashmap->h_value_dtor) {
hashmap->h_value_dtor((void *)item->bi_value.value_data);
}
free(item);
if (b_queue_empty(&bucket->bk_items)) {
b_btree_delete(&hashmap->h_buckets, &bucket->bk_node);
free(bucket);
}
hashmap->h_count--;
return B_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_hashmap *b_hashmap_create(
b_hashmap_key_destructor key_dtor, b_hashmap_value_destructor value_dtor)
{
b_hashmap *hashmap = b_object_create(B_TYPE_HASHMAP);
if (!hashmap) {
return NULL;
}
return hashmap;
}
b_hashmap *b_hashmap_create_with_items(const b_hashmap_item *items)
{
b_hashmap *hashmap = b_hashmap_create(NULL, NULL);
if (!hashmap) {
return NULL;
}
struct b_hashmap_p *p = b_object_get_private(hashmap, B_TYPE_HASHMAP);
for (size_t i = 0; items[i].key.key_data && items[i].key.key_size; i++) {
hashmap_put(p, &items[i].key, &items[i].value);
}
return hashmap;
}
b_status b_hashmap_put(
b_hashmap *hashmap, const b_hashmap_key *key, const b_hashmap_value *value)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_HASHMAP, hashmap_put, hashmap, key, value);
}
const struct b_hashmap_value *b_hashmap_get(
const b_hashmap *hashmap, const struct b_hashmap_key *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_HASHMAP, hashmap_get, hashmap, key);
}
bool b_hashmap_has_key(const b_hashmap *hashmap, const b_hashmap_key *key)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_HASHMAP, hashmap_has_key, hashmap, key);
}
size_t b_hashmap_get_size(const b_hashmap *hashmap)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_HASHMAP, hashmap_get_size, hashmap);
}
bool b_hashmap_is_empty(const b_hashmap *hashmap)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_HASHMAP, hashmap_is_empty, hashmap);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void hashmap_init(b_object *obj, void *priv)
{
struct b_hashmap_p *map = priv;
}
static void hashmap_fini(b_object *obj, void *priv)
{
struct b_hashmap_p *map = priv;
struct b_btree_node *node = b_btree_first(&map->h_buckets);
while (node) {
struct b_hashmap_bucket *b
= b_unbox(struct b_hashmap_bucket, node, bk_node);
struct b_btree_node *next_node = b_btree_next(node);
b_btree_delete(&map->h_buckets, node);
struct b_queue_entry *entry = b_queue_first(&b->bk_items);
while (entry) {
struct b_hashmap_bucket_item *item = b_unbox(
struct b_hashmap_bucket_item, entry, bi_entry);
struct b_queue_entry *next_entry = b_queue_next(entry);
b_queue_delete(&b->bk_items, entry);
if (map->h_key_dtor) {
map->h_key_dtor((void *)item->bi_key.key_data);
}
if (map->h_value_dtor) {
map->h_value_dtor((void *)item->bi_value.value_data);
}
free(item);
entry = next_entry;
}
free(b);
node = next_node;
}
}
/*** ITERATOR FUNCTIONS *******************************************************/
static b_iterator *iterable_begin(b_hashmap *hashmap)
{
b_hashmap_iterator *it_obj = b_object_create(B_TYPE_HASHMAP_ITERATOR);
struct b_hashmap_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_HASHMAP_ITERATOR);
it->_h = hashmap;
it->_h_p = b_object_get_private(hashmap, B_TYPE_HASHMAP);
it->i = 0;
if (b_hashmap_is_empty(hashmap)) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
struct b_btree_node *first_node = b_btree_first(&it->_h_p->h_buckets);
struct b_hashmap_bucket *first_bucket
= b_unbox(struct b_hashmap_bucket, first_node, bk_node);
if (!first_bucket) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
struct b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_hashmap_bucket_item *first_item
= b_unbox(struct b_hashmap_bucket_item, first_entry, bi_entry);
if (!first_item) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
memcpy(&it->item.key, &first_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &first_item->bi_value, sizeof it->item.value);
it->_cbn = first_node;
it->_cqe = first_entry;
return 0;
}
static const b_iterator *iterable_cbegin(const b_hashmap *hashmap)
{
return iterable_begin((b_hashmap *)hashmap);
}
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
memset(&it->item, 0x0, sizeof it->item);
return B_ERR_NO_DATA;
}
struct b_hashmap_bucket_item *next_item
= b_unbox(struct b_hashmap_bucket_item, next_entry, bi_entry);
if (!next_item) {
memset(&it->item, 0x0, sizeof it->item);
return B_ERR_NO_DATA;
}
it->i++;
memcpy(&it->item.key, &next_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &next_item->bi_value, sizeof it->item.value);
it->_cbn = next_node;
it->_cqe = next_entry;
return true;
}
static enum b_status iterator_erase(b_iterator *obj)
{
struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
if ((it->item.key.key_data || it->item.value.value_data)
&& !(it->_cbn && it->_cqe)) {
return B_ERR_BAD_STATE;
}
if (!it->item.key.key_data || !it->_cqe) {
return B_ERR_NO_DATA;
}
struct b_btree_node *next_node;
struct b_queue_entry *next_entry;
if (!get_next_node(it->_cbn, it->_cqe, &next_node, &next_entry)) {
memset(&it->item, 0x0, sizeof it->item);
return B_ERR_NO_DATA;
}
struct b_hashmap_bucket *cur_bucket
= b_unbox(struct b_hashmap_bucket, it->_cbn, bk_node);
struct b_hashmap_bucket_item *cur_item
= b_unbox(struct b_hashmap_bucket_item, it->_cqe, bi_entry);
struct b_hashmap_bucket_item *next_item
= b_unbox(struct b_hashmap_bucket_item, next_entry, bi_entry);
b_status status = delete_item(it->_h_p, cur_bucket, cur_item);
if (B_ERR(status)) {
return status;
}
if (next_item) {
memcpy(&it->item.key, &next_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &next_item->bi_value,
sizeof it->item.value);
it->_cbn = next_node;
it->_cqe = next_entry;
} else {
memset(&it->item, 0x0, sizeof it->item);
it->_cbn = NULL;
it->_cqe = NULL;
}
return B_SUCCESS;
}
static b_iterator_value iterator_get_value(b_iterator *obj)
{
struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
return B_ITERATOR_VALUE_PTR(&it->item);
}
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
{
const struct b_hashmap_iterator_p *it
= b_object_get_private(obj, B_TYPE_HASHMAP_ITERATOR);
return B_ITERATOR_VALUE_CPTR(&it->item);
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_hashmap DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_hashmap)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterable, B_TYPE_ITERABLE)
B_INTERFACE_ENTRY(it_begin) = 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_hashmap)
B_TYPE_DEFINITION_BEGIN(b_hashmap)
B_TYPE_ID(0x7bf5bcd1, 0x1ff3, 0x4e43, 0xbed8, 0x7c74f28348bf);
B_TYPE_CLASS(b_hashmap_class);
B_TYPE_IMPLEMENTS(B_TYPE_ITERABLE);
B_TYPE_INSTANCE_PRIVATE(struct b_hashmap_p);
B_TYPE_INSTANCE_INIT(hashmap_init);
B_TYPE_INSTANCE_FINI(hashmap_fini);
B_TYPE_DEFINITION_END(b_hashmap)
// ---- b_hashmap_iterator DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_hashmap_iterator)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
B_TYPE_CLASS_DEFINITION_END(b_hashmap_iterator)
B_TYPE_DEFINITION_BEGIN(b_hashmap_iterator)
B_TYPE_ID(0xd9658456, 0xdd80, 0x419a, 0xb23a, 0xb513013e6431);
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
B_TYPE_CLASS(b_hashmap_iterator_class);
B_TYPE_INSTANCE_PRIVATE(struct b_hashmap_iterator_p);
B_TYPE_DEFINITION_END(b_hashmap_iterator)
View File
-218
View File
@@ -1,218 +0,0 @@
/**
* A heterogeneous array of objects. b_array only stores references
* to the objects that it contains, not the object data itself.
*
* b_array stores pointers to objects in a single contiguous array,
* but this is an implementation detail that may change in the future.
* Users of b_array should not rely on this being the case.
*/
#ifndef BLUE_DS_ARRAY_H_
#define BLUE_DS_ARRAY_H_
#include <blue/core/iterator.h>
#include <blue/core/macros.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
B_DECLS_BEGIN;
#define B_TYPE_ARRAY (b_array_get_type())
#define B_TYPE_ARRAY_ITERATOR (b_array_iterator_get_type())
struct b_array_p;
B_DECLARE_TYPE(b_array);
B_DECLARE_TYPE(b_array_iterator);
B_TYPE_CLASS_DECLARATION_BEGIN(b_array)
B_TYPE_CLASS_DECLARATION_END(b_array)
B_TYPE_CLASS_DECLARATION_BEGIN(b_array_iterator)
B_TYPE_CLASS_DECLARATION_END(b_array_iterator)
BLUE_API b_type b_array_get_type(void);
BLUE_API b_type b_array_iterator_get_type(void);
B_TYPE_DEFAULT_CONSTRUCTOR(b_array, B_TYPE_ARRAY);
/**
* Creates an b_array initialised with the contents of the provided
* b_object pointer array. The b_array will take a reference to each
* object specified in `values`, and will increment the reference count.
* The order of objects in the new b_array will be the same as the order
* of objects in `values`. Any NULL pointers in the `values` array will
* be ignored, and will not result in gaps in the created b_array.
* However, `nr_values` should be large enough to cover the final
* non-NULL pointer in `values`, including any NULL pointers in-between.
*
* @param values The list of object pointers which should make up the
* contents of the new b_array.
* @param nr_values The size of the `values` array.
* @return A pointer to the new b_array, or NULL if an error occurred.
*/
BLUE_API b_array *b_array_create_with_values(
b_object *const *values, size_t nr_values);
/**
* Remove all object references from an b_array, resetting the size of the array to zero.
* The reference counts of all objects in the array will be decremented.
*
* @param array The b_array to clear.
*/
BLUE_API void b_array_clear(b_array *array);
/**
* Inserts an object at the end of an b_array. The reference count of
* the object will be incremented.
*
* @param array The b_array to append the object to.
* @param value The object to append.
* @return B_SUCCESS if the object was appended successfully, or an
* error code if an error occurred.
*/
BLUE_API b_status b_array_append(b_array *array, b_object *value);
/**
* Inserts an object at the beginning of an b_array. The reference count
* of the object will be incremented. All other objects in the array
* will be moved to make space for the object being pre-pended.
*
* @param array The b_array to prepend the object to.
* @param value The object to prepend.
* @return B_SUCCESS if the object was prepended successfully, or an
* error code if an error occurred.
*/
BLUE_API b_status b_array_prepend(b_array *array, b_object *value);
/**
* Inserts an object into an b_array at a given index. The reference
* count of the object will be incremented. If the specified index is at
* the beginning or mid-way through the array (i.e. not at the end),
* some or all of the objects already in the array will be moved to make
* space for the object being inserted.
*
* @param array The b_array to insert the object into.
* @param value The object to insert.
* @param at The index to insert the object at. If the index is
* `B_NPOS`, the object will be inserted at the end of the b_array.
* @return B_SUCCESS if the object was inserted, or a status code
* describing any error that occurred.
*/
BLUE_API b_status b_array_insert(b_array *array, b_object *value, size_t at);
/**
* Removes the object at the specified index from an b_array. The
* reference count of the removed object will be decremented. If the
* specified index is at the beginning or mid-way through the array
* (i.e. not at the end), the remaining objects will be moved to fill
* the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @param at The index of the object to be removed.
* @return B_SUCCESS if the object was removed, or a status code
* describing any error that occurred.
*/
BLUE_API b_status b_array_remove(b_array *array, size_t at);
/**
* Removes the object at the beginning of an b_array. The reference count
* of the removed object will be decremented. The remaining objects will be moved
* to fill the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove_front(b_array *array);
/**
* Removes the object at the end of an b_array. The reference count
* of the removed object will be decremented.
*
* @param array The b_array to remove the object from.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove_back(b_array *array);
/**
* Removes the object at the specified index of an b_array, and returns
* a pointer to it. The reference count of the removed object will NOT
* be decremented. The caller becomes the owner of the array's reference
* to the object. If the specified index is at the beginning or mid-way
* through the array (i.e. not at the end), the remaining objects will
* be moved to fill the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @param at The index of the object to be removed.
* @return An pointer to the removed object. This pointer is owned by
* the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop(b_array *array, size_t at);
/**
* Removes the object at the beginning of an b_array, and returns a
* pointer to it. The reference count of the removed object will NOT be
* decremented. The caller becomes the owner of the array's reference to
* the object. The remaining objects in the b_array will be moved to
* fill the empty space left by the removed object.
*
* @param array The b_array to remove the object from.
* @return An pointer to the removed object. This pointer is owned by
* the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop_front(b_array *array);
/**
* Removes the object at the end of an b_array, and returns a pointer to it. The
* reference count of the removed object will NOT be decremented. The caller
* becomes the owner of the array's reference to the object.
*
* @param array The b_array to remove the object from.
* @return An pointer to the removed object. This pointer is owned by the
* caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop_back(b_array *array);
/**
* Returns an unowned pointer to the object at the given index of an b_array.
* The caller does not own the returned pointer, and MUST NOT release it.
*
* @param array The b_array.
* @param at The index of the object to return.
* @return A pointer to the object at the given index. This pointer is NOT owned
* by the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_at(const b_array *array, size_t at);
/**
* Returns an owned pointer to the object at the given index of an
* b_array. The caller owns the returned pointer, and must release it
* when they are finished with it.
*
* @param array The b_array.
* @param at The index of the object to return.
* @return A pointer to the object at the given index. This pointer is
* owned by the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_get(b_array *array, size_t at);
/**
* Returns the number of objects contained in an b_array.
*
* @param array The b_array.
* @return The number of objects contained in the b_array.
*/
BLUE_API size_t b_array_size(const b_array *array);
/**
* Returns the current maximum capacity of an b_array. This represents
* the number of objects that can be stored in an b_array before its
* internal buffer would need to be re-sized.
*
* @param array The b_array.
* @return The maximum capacity of the b_array.
*/
BLUE_API size_t b_array_capacity(const b_array *array);
B_DECLS_END;
#endif
-30
View File
@@ -1,30 +0,0 @@
#ifndef BLUE_OBJECT_BITBUFFER_H_
#define BLUE_OBJECT_BITBUFFER_H_
#include <blue/ds/object.h>
#define B_BITBUFFER(p) ((b_bitbuffer *)(p))
typedef struct b_bitbuffer b_bitbuffer;
BLUE_API b_bitbuffer *b_bitbuffer_create(void);
static inline b_bitbuffer *b_bitbuffer_retain(b_bitbuffer *buf)
{
return B_BITBUFFER(b_retain(B_DSREF(buf)));
}
static inline void b_bitbuffer_release(b_bitbuffer *buf)
{
b_release(B_DSREF(buf));
}
BLUE_API b_status b_bitbuffer_put_bit(b_bitbuffer *buf, int bit);
BLUE_API b_status b_bitbuffer_put_bool(b_bitbuffer *buf, bool b);
BLUE_API b_status b_bitbuffer_put_int(
b_bitbuffer *buf, uint64_t v, unsigned int nr_bits);
BLUE_API b_status b_bitbuffer_put_bytes(
b_bitbuffer *buf, const void *p, size_t len, size_t bits_per_byte);
BLUE_API b_status b_bitbuffer_put_string(
b_bitbuffer *buf, const char *p, size_t len, size_t bits_per_char);
#endif

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