Compare commits

...

20 Commits

Author SHA1 Message Date
146db5f6ef test: add core-mm tests 2026-02-03 17:41:34 +00:00
13136ecbd6 meta: add c++ wrapper of core module 2026-02-03 17:41:25 +00:00
e0efbd1ec4 build: add template for c++-based modules 2026-02-03 17:41:01 +00:00
e0aea0be19 core: slight changes to allow compilation under c++ 2026-02-03 17:40:45 +00:00
84df46489a meta: update clang-format config 2026-02-03 14:47:36 +00:00
0d5a186d80 test: core: add bstr tests; update rope tests 2026-02-03 14:47:25 +00:00
2632feac32 cmd: add support for dynamically generating command options at runtime 2026-02-03 14:46:40 +00:00
f5c4fa561f ds: uuid: convert uuid bytes struct to union 2026-02-03 14:45:30 +00:00
5639aefd61 ds: string: set iterator value to B_WCHAR_INVALID when end of string is reached 2026-02-03 14:44:36 +00:00
30a9db17dc ds: list: update iterator interface 2026-02-03 14:43:35 +00:00
ce50cfd18b ds: hashmap: update iterator interface 2026-02-03 14:43:17 +00:00
9b48fc2b45 ds: convert (stub) bitbuffer implementation to (stub) b_object sub-class 2026-02-03 14:42:05 +00:00
5889426478 core: rope: add bstr support 2026-02-03 14:39:33 +00:00
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
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
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
add05ef478 core: iterator: added inline definition of is_valid() 2026-02-03 14:32:15 +00:00
68ab79fe2a core: hash: add support for hashing the contents of ropes 2026-02-03 14:31:35 +00:00
ce9195c130 core: queue: implement moving queue entries
this works exactly the same as moving btree nodes.
2026-02-03 14:30:53 +00:00
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
55 changed files with 2033 additions and 191 deletions

View File

@@ -4,7 +4,6 @@ IndentWidth: 8
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Right
ReferenceAlignment: Left
ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
@@ -53,9 +52,67 @@ PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- BLUE_API
- BLUELIB_API
ForEachMacros:
- b_btree_foreach
- b_queue_foreach
MacroBlockBegin: "^B_(TYPE|PARAM)_.*_BEGIN$"
MacroBlockEnd: "^B_(TYPE|PARAM)_.*_END$"
MacroBlockBegin: "B_TYPE_.*_BEGIN"
MacroBlockEnd: "B_TYPE_.*_END"
---
Language: ObjC
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 80
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: Right
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
ExperimentalAutoDetectBinPacking: false
BitFieldColonSpacing: Both
BreakBeforeBraces: Linux
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
IncludeBlocks: Regroup
SortIncludes: true
IndentRequires: true
NamespaceIndentation: Inner
ReflowComments: true
SpacesBeforeTrailingComments: 3
TabWidth: 8
UseTab: AlignWithSpaces
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyExcessCharacter: 5
PenaltyBreakOpenParenthesis: 5
PenaltyBreakBeforeFirstCallParameter: 5
PenaltyIndentedWhitespace: 0
AttributeMacros:
- BLUELIB_API
ForEachMacros:
- b_btree_foreach
- b_queue_foreach
MacroBlockBegin: "B_TYPE_.*_BEGIN"
MacroBlockEnd: "B_TYPE_.*_END"

View File

@@ -1,15 +1,19 @@
cmake_minimum_required(VERSION 3.25)
project(bluelib C)
project(bluelib C CXX)
include (TestBigEndian)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(b_modules core ds serial term cmd io compress)
set(b_modules
core ds serial term cmd io compress
core-mm)
set(b_system_name ${CMAKE_SYSTEM_NAME})
string(TOLOWER ${b_system_name} b_system_name)
@@ -37,7 +41,7 @@ foreach (module ${b_modules})
endif ()
file(GLOB test_sources test/${module}/*.c)
file(GLOB test_sources test/${module}/*.c test/${module}/*.cpp)
list(REMOVE_ITEM test_sources "${CMAKE_CURRENT_SOURCE_DIR}/test/${module}/${module}-units.c")
foreach (test_file ${test_sources})

View File

@@ -105,3 +105,118 @@ function(add_bluelib_module)
install(FILES ${root_header} DESTINATION include/blue)
install(FILES ${headers} DESTINATION include/blue/${module_name})
endfunction(add_bluelib_module)
function(add_bluelib_mm_module)
set(options)
set(one_value_args NAME)
set(multi_value_args
DEPENDENCIES
SUBDIRS
EXTRA_SOURCES
LIBS
INCLUDE_DIRS
DEFINES)
cmake_parse_arguments(PARSE_ARGV 0 arg
"${options}"
"${one_value_args}"
"${multi_value_args}")
set(short_module_name ${arg_NAME})
set(module_name ${arg_NAME}-mm)
file(GLOB sources
*.c *.h
*.cpp *.hpp)
foreach (dir ${arg_SUBDIRS})
file(GLOB dir_sources
${dir}/*.c ${dir}/*.h
${dir}/*.cpp ${dir}/*.hpp)
set(sources ${sources} ${dir_sources})
endforeach (dir)
file(GLOB sys_sources
sys/${b_system_name}/*.c sys/${b_system_name}/*.h
sys/${b_system_name}/*.cpp sys/${b_system_name}/*.hpp)
set(root_header include/blue/${short_module_name}.hpp)
file(GLOB headers include/blue/${short_module_name}/*.hpp)
string(REPLACE "-" "_" module_preproc_token ${short_module_name})
string(TOUPPER ${module_preproc_token} module_preproc_token)
set(module_preproc_token BLUELIB_${module_preproc_token})
message(STATUS "Building mm module ${short_module_name} (shared)")
add_library(blue-${module_name} SHARED
${sources}
${sys_sources}
${root_header}
${headers}
${arg_EXTRA_SOURCES})
message(STATUS "Building mm module ${short_module_name} (static)")
add_library(blue-${module_name}-s STATIC
${sources}
${sys_sources}
${root_header}
${headers}
${arg_EXTRA_SOURCES})
target_include_directories(blue-${module_name} PUBLIC include/)
target_include_directories(blue-${module_name}-s PUBLIC include/)
target_compile_definitions(blue-${module_name} PUBLIC
${module_preproc_token}
BLUELIB_EXPORT=1)
target_compile_definitions(blue-${module_name}-s PUBLIC
${module_preproc_token}
BLUELIB_EXPORT=1
BLUELIB_STATIC=1)
set_target_properties(blue-${module_name}
PROPERTIES POSITION_INDEPENDENT_CODE ON)
foreach (dep ${arg_DEPENDENCIES})
target_link_libraries(blue-${module_name} blue-${dep})
target_link_libraries(blue-${module_name}-s blue-${dep}-s)
endforeach (dep)
foreach (lib ${arg_LIBS})
target_link_libraries(blue-${module_name} ${lib})
target_link_libraries(blue-${module_name}-s ${lib})
endforeach (lib)
foreach (dir ${arg_INCLUDE_DIRS})
target_include_directories(blue-${module_name} PRIVATE
${dir})
target_include_directories(blue-${module_name}-s PRIVATE
${dir})
endforeach (dir)
foreach (def ${arg_DEFINES})
target_compile_definitions(blue-${module_name} PRIVATE
${def})
target_compile_definitions(blue-${module_name}-s PRIVATE
${def})
endforeach (def)
set_target_properties(blue-${module_name} PROPERTIES
FOLDER "mm/Shared/${short_module_name}")
set_target_properties(blue-${module_name}-s PROPERTIES
FOLDER "mm/Static/${short_module_name}")
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
target_compile_definitions(blue-${module_name} PRIVATE
BIG_ENDIAN)
target_compile_definitions(blue-${module_name}-s PRIVATE
BIG_ENDIAN)
else()
target_compile_definitions(blue-${module_name} PRIVATE
LITTLE_ENDIAN)
target_compile_definitions(blue-${module_name}-s PRIVATE
LITTLE_ENDIAN)
endif()
install(TARGETS blue-${module_name} blue-${module_name}-s)
install(FILES ${root_header} DESTINATION include/blue)
install(FILES ${headers} DESTINATION include/blue/${short_module_name})
endfunction(add_bluelib_mm_module)

View File

@@ -282,6 +282,24 @@ struct b_command_usage *b_command_add_usage(struct b_command *cmd)
return usage;
}
const struct b_command_option *b_command_get_option(
const struct b_command *cmd, int id)
{
struct b_queue_entry *cur = b_queue_first(&cmd->b_opt);
while (cur) {
const struct b_command_option *opt
= b_unbox(struct b_command_option, cur, opt_entry);
if (opt->opt_id == id) {
return opt;
}
cur = b_queue_next(cur);
}
return NULL;
}
b_status b_command_usage_add_option(
struct b_command_usage *usage, struct b_command_option *opt)
{
@@ -335,9 +353,9 @@ b_status b_command_usage_add_command(b_command_usage *usage, unsigned int cmd_id
static void prepend_command_name(struct b_command *cmd, b_string *out)
{
int nr_names = 0;
cmd->b_name&& nr_names++;
cmd->b_long_name&& nr_names++;
cmd->b_short_name&& nr_names++;
cmd->b_name &&nr_names++;
cmd->b_long_name &&nr_names++;
cmd->b_short_name &&nr_names++;
if (nr_names > 1) {
b_string_prepend_cstr(out, "}");

View File

@@ -61,6 +61,12 @@
this_opt = opt_##id; \
if (this_opt)
#define B_COMMAND_OPTION_GEN(id) \
b_command_option *z__b_unique_name() \
= b_command_add_option(this_cmd, (id)); \
this_opt = z__b_unique_name(); \
if (this_opt)
#define B_COMMAND_HELP_OPTION() \
do { \
b_command_option *opt \
@@ -210,6 +216,11 @@ BLUE_API b_command_option *b_command_add_option(b_command *cmd, int id);
BLUE_API b_command_arg *b_command_add_arg(b_command *cmd, int id);
BLUE_API b_command_usage *b_command_add_usage(b_command *cmd);
BLUE_API const b_command_option *b_command_get_option(const b_command *cmd, int id);
BLUE_API const char *b_command_option_get_long_name(const b_command_option *opt);
BLUE_API char b_command_option_get_short_name(const b_command_option *opt);
BLUE_API const char *b_command_option_get_description(b_command_option *opt);
BLUE_API b_status b_command_option_set_long_name(
b_command_option *opt, const char *name);
BLUE_API b_status b_command_option_set_short_name(b_command_option *opt, char name);

View File

@@ -42,6 +42,21 @@ void b_command_option_destroy(struct b_command_option *opt)
free(opt);
}
const char *b_command_option_get_long_name(const struct b_command_option *opt)
{
return opt->opt_long_name;
}
char b_command_option_get_short_name(const struct b_command_option *opt)
{
return opt->opt_short_name;
}
const char *b_command_option_get_description(struct b_command_option *opt)
{
return opt->opt_description;
}
b_status b_command_option_set_long_name(
struct b_command_option *opt, const char *name)
{

6
core-mm/CMakeLists.txt Normal file
View File

@@ -0,0 +1,6 @@
include(../cmake/Templates.cmake)
add_bluelib_mm_module(
NAME core
DEPENDENCIES core
SUBDIRS hash)

1
core-mm/encoding.cpp Normal file
View File

@@ -0,0 +1 @@
#include <blue/core/encoding.hpp>

View File

@@ -0,0 +1,106 @@
#ifndef BLUE_CORE_ENCODING_HPP_
#define BLUE_CORE_ENCODING_HPP_
#include <blue/core/encoding.h>
#include <cstddef>
#include <cstdint>
namespace blue::core
{
class wchar
{
public:
static const int32_t INVALID = B_WCHAR_INVALID;
wchar();
wchar(std::int32_t v)
: val_(v)
{
}
static wchar decode(const char *s);
operator int32_t() const
{
return val_;
}
bool is_alpha(void) const
{
return b_wchar_is_alpha(val_);
}
bool is_number(void) const
{
return b_wchar_is_number(val_);
}
bool is_bin_digit(void) const
{
return b_wchar_is_bin_digit(val_);
}
bool is_oct_digit(void) const
{
return b_wchar_is_oct_digit(val_);
}
bool is_hex_digit(void) const
{
return b_wchar_is_hex_digit(val_);
}
bool is_space(void) const
{
return b_wchar_is_space(val_);
}
bool is_alnum(void) const
{
return b_wchar_is_alnum(val_);
}
bool is_punct(void) const
{
return b_wchar_is_punct(val_);
}
bool is_valid_utf8_scalar(void) const
{
return b_wchar_utf8_is_valid_scalar(val_);
}
unsigned int get_utf8_codepoint_size(void) const
{
return b_wchar_utf8_codepoint_size(val_);
}
unsigned int encode_utf8(char s[4]) const
{
return b_wchar_utf8_codepoint_encode(val_, s);
}
private:
int32_t val_ = B_WCHAR_INVALID;
};
class utf8
{
public:
static unsigned int decode_header(char c)
{
return b_wchar_utf8_header_decode(c);
}
static unsigned int get_codepoint_stride(const char *s)
{
return b_wchar_utf8_codepoint_stride(s);
}
static std::size_t get_codepoint_count(const char *s, std::size_t nr_bytes)
{
return b_wchar_utf8_codepoint_count(s, nr_bytes);
}
static std::size_t get_string_encoded_size(
const wchar *s, std::size_t nr_codepoints)
{
return b_wchar_utf8_string_encoded_size(
reinterpret_cast<const b_wchar *>(s), nr_codepoints);
}
private:
utf8() = delete;
~utf8() = delete;
};
}
#endif

View File

@@ -0,0 +1,46 @@
#ifndef BLUE_CORE_MISC_HPP_
#define BLUE_CORE_MISC_HPP_
#define Z__B_ENUM_CLASS_BITWISE_OPS(enum_name) \
inline constexpr enum_name operator&(enum_name x, enum_name y) \
{ \
return static_cast<enum_name>( \
static_cast<int>(x) & static_cast<int>(y)); \
} \
\
inline constexpr enum_name operator|(enum_name x, enum_name y) \
{ \
return static_cast<enum_name>( \
static_cast<int>(x) | static_cast<int>(y)); \
} \
\
inline constexpr enum_name operator^(enum_name x, enum_name y) \
{ \
return static_cast<enum_name>( \
static_cast<int>(x) ^ static_cast<int>(y)); \
} \
\
inline constexpr enum_name operator~(enum_name x) \
{ \
return static_cast<enum_name>(~static_cast<int>(x)); \
} \
\
inline enum_name &operator&=(enum_name &x, enum_name y) \
{ \
x = x & y; \
return x; \
} \
\
inline enum_name &operator|=(enum_name &x, enum_name y) \
{ \
x = x | y; \
return x; \
} \
\
inline enum_name &operator^=(enum_name &x, enum_name y) \
{ \
x = x ^ y; \
return x; \
}
#endif

View File

@@ -0,0 +1,40 @@
#ifndef BLUE_CORE_OBJECT_HPP_
#define BLUE_CORE_OBJECT_HPP_
#include <blue/core/object.h>
namespace blue::core
{
class type;
class object
{
public:
static const size_t MAGIC = B_OBJECT_MAGIC;
object(object &) = delete;
object(object &&);
~object();
bool operator!()
{
return ptr_ == nullptr;
}
void to_string(void) const;
bool is_type(const type &type) const;
b_object *ptr(void)
{
return ptr_;
}
const b_object *ptr(void) const
{
return ptr_;
}
protected:
object() = default;
b_object *ptr_ = nullptr;
};
}
#endif

View File

@@ -0,0 +1,62 @@
#ifndef BLUE_CORE_STATUS_HPP_
#define BLUE_CORE_STATUS_HPP_
#include <blue/core/status.h>
namespace blue
{
class status
{
public:
#define __MM_STATUS_ENUM(name) name = B_ERR_##name
enum _status : int {
SUCCESS = B_SUCCESS,
__MM_STATUS_ENUM(NO_MEMORY),
__MM_STATUS_ENUM(OUT_OF_BOUNDS),
__MM_STATUS_ENUM(INVALID_ARGUMENT),
__MM_STATUS_ENUM(NAME_EXISTS),
__MM_STATUS_ENUM(NOT_SUPPORTED),
__MM_STATUS_ENUM(BAD_STATE),
__MM_STATUS_ENUM(NO_ENTRY),
__MM_STATUS_ENUM(NO_DATA),
__MM_STATUS_ENUM(NO_SPACE),
__MM_STATUS_ENUM(UNKNOWN_FUNCTION),
__MM_STATUS_ENUM(BAD_FORMAT),
__MM_STATUS_ENUM(IO_FAILURE),
__MM_STATUS_ENUM(IS_DIRECTORY),
__MM_STATUS_ENUM(NOT_DIRECTORY),
__MM_STATUS_ENUM(PERMISSION_DENIED),
__MM_STATUS_ENUM(BUSY),
__MM_STATUS_ENUM(COMPRESSION_FAILURE),
__MM_STATUS_ENUM(TYPE_REGISTRATION_FAILURE),
__MM_STATUS_ENUM(CLASS_INIT_FAILURE),
};
status() = default;
status(_status v)
: v_(static_cast<b_status>(v))
{
}
status(b_status v)
: v_(v)
{
}
bool operator!() const
{
return v_ != B_SUCCESS;
}
operator b_status() const
{
return v_;
}
const char *to_string(void);
const char *description(void);
private:
b_status v_ = B_SUCCESS;
};
}
#endif

View File

@@ -0,0 +1,135 @@
#ifndef BLUE_CORE_STREAM_HPP_
#define BLUE_CORE_STREAM_HPP_
#include <blue/core/encoding.hpp>
#include <blue/core/misc.hpp>
#include <blue/core/object.hpp>
#include <blue/core/status.hpp>
#include <blue/core/stream.h>
#include <blue/core/type.hpp>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <string>
namespace blue::core
{
class stream_buffer : public object
{
};
class stream : public object
{
public:
enum class mode : int {
READ = B_STREAM_READ,
WRITE = B_STREAM_WRITE,
BINARY = B_STREAM_BINARY,
__STATIC = Z__B_STREAM_STATIC,
};
enum class seek_origin : int {
START = B_STREAM_SEEK_START,
CURRENT = B_STREAM_SEEK_CURRENT,
END = B_STREAM_SEEK_END,
};
static type get_type(void);
static stream &in(void);
static stream &out(void);
static stream &err(void);
stream(stream &) = delete;
stream(std::FILE *fp);
status reserve(std::size_t len);
status seek(long long offset, seek_origin origin);
std::size_t cursor(void) const;
status push_indent(int indent);
status pop_indent(void);
status read_char(wchar &c);
status read_bytes(void *buf, std::size_t count, std::size_t &nr_read);
status read_bytes(void *buf, std::size_t count)
{
std::size_t tmp;
return read_bytes(buf, count, tmp);
}
status read_line(char *s, std::size_t max);
status read_line(std::string &out);
status read_line(stream &dest);
status read_all_bytes(void *p, std::size_t max, std::size_t &nr_read);
status read_all_bytes(
stream &dest, stream_buffer &buf, std::size_t &nr_read);
status read_all_bytes(void *p, std::size_t max)
{
std::size_t tmp;
return read_all_bytes(p, max);
}
status read_all_bytes(stream &dest, stream_buffer &buf)
{
std::size_t tmp;
return read_all_bytes(dest, buf);
}
status write_char(wchar c);
status write_string(const char *s, std::size_t &nr_written);
status write_string(const char *s)
{
std::size_t tmp;
return write_string(s, tmp);
}
status write_string(const std::string &s, std::size_t &nr_written)
{
return write_string(s.c_str(), nr_written);
}
status write_string(const std::string &s)
{
std::size_t tmp;
return write_string(s, tmp);
}
status write_bytes(
const void *buf, std::size_t count, std::size_t &nr_written);
status write_bytes(const void *buf, std::size_t count)
{
std::size_t tmp;
return write_bytes(buf, count, tmp);
}
status write_fmt(std::size_t &nr_written, const char *format, ...);
status write_vfmt(
std::size_t &nr_written, const char *format, std::va_list arg);
status write_fmt(const char *format, ...)
{
std::size_t tmp;
std::va_list arg;
va_start(arg, format);
status s = write_vfmt(tmp, format, arg);
va_end(arg);
return s;
}
status write_vfmt(const char *format, std::va_list arg)
{
std::size_t tmp;
return write_vfmt(tmp, format, arg);
}
protected:
stream() = default;
};
}
Z__B_ENUM_CLASS_BITWISE_OPS(blue::core::stream::mode)
#endif

View File

@@ -0,0 +1,23 @@
#ifndef BLUE_CORE_STRINGSTREAM_HPP_
#define BLUE_CORE_STRINGSTREAM_HPP_
#include <blue/core/stream.hpp>
namespace blue::core
{
class stringstream : public stream
{
public:
stringstream();
stringstream(char *buf, std::size_t max);
status reset();
status reset(char *buf, std::size_t max);
const char *get_ptr() const;
char *steal_ptr();
std::size_t get_length() const;
};
}
#endif

View File

@@ -0,0 +1,24 @@
#ifndef BLUE_CORE_TYPE_HPP_
#define BLUE_CORE_TYPE_HPP_
#include <blue/core/type.h>
namespace blue::core
{
class type
{
public:
type(b_type p)
{
ptr_ = p;
}
~type() = default;
type(type &) = default;
private:
const union b_type_id *ptr_;
};
}
#endif

20
core-mm/object.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include <blue/core/object.hpp>
namespace blue::core
{
object::object(object &&other)
{
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
object::~object()
{
if (ptr_) {
b_object_unref(ptr_);
ptr_ = nullptr;
}
}
}

169
core-mm/stream.cpp Normal file
View File

@@ -0,0 +1,169 @@
#include <blue/core/stream.h>
#include <blue/core/stream.hpp>
namespace blue::core
{
type stream::get_type(void)
{
return b_stream_get_type();
}
stream &stream::in(void)
{
static stream s;
s.ptr_ = b_stdin;
return s;
}
stream &stream::out(void)
{
static stream s;
s.ptr_ = b_stdout;
return s;
}
stream &stream::err(void)
{
static stream s;
s.ptr_ = b_stderr;
return s;
}
stream::stream(std::FILE *fp)
{
ptr_ = b_stream_open_fp(fp);
}
status stream::reserve(std::size_t len)
{
return b_stream_reserve(ptr_, len);
}
status stream::seek(long long offset, seek_origin origin)
{
return b_stream_seek(
ptr_, offset, static_cast<b_stream_seek_origin>(origin));
}
std::size_t stream::cursor(void) const
{
return b_stream_cursor(ptr_);
}
status stream::push_indent(int indent)
{
return b_stream_push_indent(ptr_, indent);
}
status stream::pop_indent(void)
{
return b_stream_pop_indent(ptr_);
}
status stream::read_char(wchar &c)
{
b_wchar tmp;
status s = b_stream_read_char(ptr_, &tmp);
c = tmp;
return s;
}
status stream::read_bytes(void *buf, std::size_t count, std::size_t &nr_read)
{
std::size_t r;
status s = b_stream_read_bytes(ptr_, buf, count, &r);
nr_read = r;
return s;
}
status stream::read_line(char *s, std::size_t max)
{
return b_stream_read_line(ptr_, s, max);
}
status stream::read_line(std::string &out)
{
while (1) {
wchar c = wchar::INVALID;
status s = read_char(c);
if (!s) {
return s;
}
if (c == '\n') {
break;
}
char str[5] = {0};
c.encode_utf8(str);
out.append(str);
}
return status::SUCCESS;
}
status stream::read_line(stream &dest)
{
return b_stream_read_line_s(ptr_, dest.ptr_);
}
status stream::read_all_bytes(void *p, std::size_t max, std::size_t &nr_read)
{
std::size_t tmp;
status s = b_stream_read_all_bytes(ptr_, p, max, &tmp);
nr_read = tmp;
return s;
}
status stream::read_all_bytes(stream &dest, stream_buffer &buf, std::size_t &nr_read)
{
std::size_t tmp;
status s = b_stream_read_all_bytes_s(ptr_, dest.ptr_, buf.ptr(), &tmp);
nr_read = tmp;
return s;
}
status stream::write_char(wchar c)
{
return b_stream_write_char(ptr_, c);
}
status stream::write_string(const char *str, std::size_t &nr_written)
{
std::size_t tmp;
status s = b_stream_write_string(ptr_, str, &tmp);
nr_written = tmp;
return s;
}
status stream::write_bytes(
const void *buf, std::size_t count, std::size_t &nr_written)
{
std::size_t tmp;
status s = b_stream_write_bytes(ptr_, buf, count, &tmp);
nr_written = tmp;
return s;
}
status stream::write_fmt(std::size_t &nr_written, const char *format, ...)
{
size_t tmp;
std::va_list arg;
va_start(arg, format);
status s = b_stream_write_vfmt(ptr_, &tmp, format, arg);
va_end(arg);
nr_written = tmp;
return s;
}
status stream::write_vfmt(std::size_t &nr_written, const char *format, va_list arg)
{
size_t tmp;
status s = b_stream_write_vfmt(ptr_, &tmp, format, arg);
nr_written = tmp;
return s;
}
}

42
core-mm/stringstream.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include <blue/core/stringstream.h>
#include <blue/core/stringstream.hpp>
namespace blue::core
{
stringstream::stringstream()
{
ptr_ = b_stringstream_create();
}
stringstream::stringstream(char *buf, std::size_t max)
{
ptr_ = b_stringstream_create_with_buffer(buf, max);
}
status stringstream::reset()
{
return b_stringstream_reset(ptr_);
}
status stringstream::reset(char *buf, std::size_t max)
{
return b_stringstream_reset_with_buffer(ptr_, buf, max);
}
const char *stringstream::get_ptr() const
{
return b_stringstream_ptr(ptr_);
}
char *stringstream::steal_ptr()
{
return b_stringstream_steal(ptr_);
}
std::size_t stringstream::get_length() const
{
return b_stringstream_get_length(ptr_);
}
}

1
core-mm/type.cpp Normal file
View File

@@ -0,0 +1 @@
#include <blue/core/type.hpp>

375
core/bstr.c Normal file
View File

@@ -0,0 +1,375 @@
#include "printf.h"
#include <blue/core/bstr.h>
#include <blue/core/rope.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHECK_FLAG(str, f) ((((str)->bstr_flags) & (f)) == (f))
#define IS_DYNAMIC(p) (CHECK_FLAG(p, B_BSTR_F_ALLOC))
/* number of bytes that bstr_buf is extended by when required */
#define CAPACITY_STEP 32
void b_bstr_begin(struct b_bstr *str, char *buf, size_t max)
{
memset(str, 0x0, sizeof *str);
str->bstr_magic = B_BSTR_MAGIC;
str->bstr_buf = buf;
str->bstr_capacity = max;
str->bstr_len = 0;
str->bstr_flags = B_BSTR_F_NONE;
}
void b_bstr_begin_dynamic(struct b_bstr *str)
{
memset(str, 0x0, sizeof *str);
str->bstr_magic = B_BSTR_MAGIC;
str->bstr_buf = NULL;
str->bstr_capacity = 0;
str->bstr_len = 0;
str->bstr_flags = B_BSTR_F_ALLOC;
}
static char *truncate_buffer(char *s, size_t len)
{
if (!s || !len) {
return NULL;
}
char *final = realloc(s, len + 1);
if (!final) {
return s;
}
final[len] = '\0';
return final;
}
char *b_bstr_end(struct b_bstr *str)
{
char *out = str->bstr_buf;
size_t len = str->bstr_len;
if (IS_DYNAMIC(str) && str->bstr_capacity - 1 > str->bstr_len) {
/* bstr_buf is larger than required to contain the string.
* re-allocate it so it's only as large as necessary */
out = truncate_buffer(out, len);
}
if (str->bstr_istack) {
free(str->bstr_istack);
}
memset(str, 0x0, sizeof *str);
return out;
}
enum b_status b_bstr_reserve(struct b_bstr *strv, size_t len)
{
if (!IS_DYNAMIC(strv)) {
return B_SUCCESS;
}
if (strv->bstr_capacity > 0 && strv->bstr_capacity - 1 >= len) {
return B_SUCCESS;
}
char *new_buf = realloc(strv->bstr_buf, len + 1);
if (!new_buf) {
return B_ERR_NO_MEMORY;
}
strv->bstr_buf = new_buf;
strv->bstr_capacity = len + 1;
strv->bstr_buf[strv->bstr_len] = '\0';
return B_SUCCESS;
}
static int current_indent(struct b_bstr *str)
{
if (!str->bstr_istack || !str->bstr_istack_size) {
return 0;
}
return str->bstr_istack[str->bstr_istack_ptr];
}
static void __formatter_putchar(struct b_bstr *str, char c)
{
if (str->bstr_capacity > 0 && str->bstr_len < str->bstr_capacity - 1) {
str->bstr_buf[str->bstr_len++] = c;
str->bstr_buf[str->bstr_len] = '\0';
return;
}
if (!CHECK_FLAG(str, B_BSTR_F_ALLOC)) {
return;
}
size_t old_capacity = str->bstr_capacity;
size_t new_capacity = old_capacity + CAPACITY_STEP;
char *new_buf = realloc(str->bstr_buf, new_capacity);
if (!new_buf) {
return;
}
str->bstr_buf = new_buf;
str->bstr_capacity = new_capacity;
str->bstr_buf[str->bstr_len++] = c;
str->bstr_buf[str->bstr_len] = '\0';
}
static void formatter_putchar(struct b_bstr *f, char c)
{
if (f->bstr_add_indent && c != '\n') {
int indent = current_indent(f);
for (int i = 0; i < indent; i++) {
__formatter_putchar(f, ' ');
__formatter_putchar(f, ' ');
}
f->bstr_add_indent = 0;
}
__formatter_putchar(f, c);
if (c == '\n') {
f->bstr_add_indent = 1;
}
}
static void bstr_fctprintf(char c, void *arg)
{
struct b_bstr *str = arg;
formatter_putchar(str, c);
}
static enum b_status bstr_putcs(
struct b_bstr *str, const char *s, size_t len, size_t *nr_written)
{
for (size_t i = 0; i < len; i++) {
formatter_putchar(str, s[i]);
}
if (nr_written) {
*nr_written = len;
}
return B_SUCCESS;
}
static enum b_status bstr_puts(struct b_bstr *str, const char *s, size_t *nr_written)
{
size_t i;
for (i = 0; s[i]; i++) {
formatter_putchar(str, s[i]);
}
if (nr_written) {
*nr_written = i;
}
return B_SUCCESS;
}
enum b_status b_bstr_push_indent(struct b_bstr *str, int indent)
{
if (!str->bstr_istack) {
str->bstr_istack = calloc(4, sizeof(int));
str->bstr_istack_size = 4;
str->bstr_istack_ptr = 0;
}
if (str->bstr_istack_ptr + 1 > str->bstr_istack_size) {
int *buf = realloc(
str->bstr_istack,
(str->bstr_istack_size + 4) * sizeof(int));
if (!buf) {
return B_ERR_NO_MEMORY;
}
str->bstr_istack = buf;
str->bstr_istack_size += 4;
}
int cur_indent = str->bstr_istack[str->bstr_istack_ptr];
str->bstr_istack[++str->bstr_istack_ptr] = cur_indent + indent;
return B_SUCCESS;
}
enum b_status b_bstr_pop_indent(struct b_bstr *strv)
{
if (strv->bstr_istack_ptr > 0) {
strv->bstr_istack_ptr--;
}
return B_SUCCESS;
}
enum b_status b_bstr_write_char(struct b_bstr *str, char c)
{
formatter_putchar(str, c);
return B_SUCCESS;
}
enum b_status b_bstr_write_chars(
struct b_bstr *str, const char *s, size_t len, size_t *nr_written)
{
return bstr_putcs(str, s, len, nr_written);
}
enum b_status b_bstr_write_cstr(struct b_bstr *str, const char *s, size_t *nr_written)
{
return bstr_puts(str, s, nr_written);
}
enum b_status b_bstr_write_cstr_list(
struct b_bstr *str, const char **strs, size_t *nr_written)
{
size_t w = 0;
enum b_status status = B_SUCCESS;
for (size_t i = 0; strs[i]; i++) {
size_t tmp = 0;
status = bstr_puts(str, strs[i], &tmp);
w += tmp;
if (B_ERR(status)) {
break;
}
}
if (nr_written) {
*nr_written = w;
}
return status;
}
enum b_status b_bstr_write_cstr_array(
struct b_bstr *str, const char **strs, size_t count, size_t *nr_written)
{
enum b_status status = B_SUCCESS;
size_t w = 0;
for (size_t i = 0; i < count; i++) {
if (!strs[i]) {
continue;
}
size_t tmp = 0;
status = bstr_puts(str, strs[i], &tmp);
w += tmp;
if (B_ERR(status)) {
break;
}
}
if (nr_written) {
*nr_written = w;
}
return status;
}
enum b_status b_bstr_add_many(struct b_bstr *str, size_t *nr_written, ...)
{
va_list arg;
va_start(arg, nr_written);
const char *s = NULL;
size_t w = 0;
enum b_status status = B_SUCCESS;
while ((s = va_arg(arg, const char *))) {
size_t tmp = 0;
status = bstr_puts(str, s, &tmp);
w += tmp;
if (B_ERR(status)) {
break;
}
}
if (nr_written) {
*nr_written = w;
}
return status;
}
enum b_status b_bstr_write_rope(
b_bstr *strv, const struct b_rope *rope, size_t *nr_written)
{
size_t start = strv->bstr_len;
enum b_status status = b_rope_to_bstr(rope, strv);
size_t end = strv->bstr_len;
if (nr_written) {
*nr_written = end - start;
}
return status;
}
enum b_status b_bstr_write_fmt(
struct b_bstr *str, size_t *nr_written, const char *format, ...)
{
va_list arg;
va_start(arg, format);
enum b_status result = b_bstr_write_vfmt(str, nr_written, format, arg);
va_end(arg);
return result;
}
enum b_status b_bstr_write_vfmt(
struct b_bstr *str, size_t *nr_written, const char *format, va_list arg)
{
size_t start = str->bstr_len;
z__b_fctprintf(bstr_fctprintf, str, format, arg);
size_t end = str->bstr_len;
if (nr_written) {
*nr_written = end - start;
}
/* TODO update z__b_fctprintf to support propagating error codes */
return B_SUCCESS;
}
char *b_bstr_rope(const struct b_rope *rope, size_t *nr_written)
{
struct b_bstr str;
b_bstr_begin_dynamic(&str);
b_bstr_write_rope(&str, rope, nr_written);
return b_bstr_end(&str);
}
char *b_bstr_fmt(size_t *nr_written, const char *format, ...)
{
va_list arg;
va_start(arg, format);
char *s = b_bstr_vfmt(nr_written, format, arg);
va_end(arg);
return s;
}
char *b_bstr_vfmt(size_t *nr_written, const char *format, va_list arg)
{
struct b_bstr str;
b_bstr_begin_dynamic(&str);
b_bstr_write_vfmt(&str, nr_written, format, arg);
return b_bstr_end(&str);
}

View File

@@ -736,6 +736,32 @@ b_btree_node *b_btree_prev(const struct b_btree_node *node)
return prev_node(node, &d);
}
void b_btree_move(
struct b_btree *tree, struct b_btree_node *dest, struct b_btree_node *src)
{
if (src->b_parent) {
if (src->b_parent->b_left == src) {
src->b_parent->b_left = dest;
} else {
src->b_parent->b_right = dest;
}
}
if (src->b_left) {
src->b_left->b_parent = dest;
}
if (src->b_right) {
src->b_right->b_parent = dest;
}
if (tree->b_root == src) {
tree->b_root = dest;
}
memmove(dest, src, sizeof *src);
}
b_iterator *b_btree_begin(struct b_btree *tree)
{
b_iterator *it_obj = b_object_create(B_TYPE_BTREE_ITERATOR);

View File

@@ -28,7 +28,7 @@ const char *b_class_get_name(const struct _b_class *c)
return c->c_type->r_info->t_name;
}
void *b_class_get_interface(const struct _b_class *c, const union b_type *id)
void *b_class_get_interface(const struct _b_class *c, const union b_type_id *id)
{
if (!c) {
return NULL;

View File

@@ -1,6 +1,8 @@
#include "hash.h"
#include <blue/core/hash.h>
#include <blue/core/rope.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@@ -116,6 +118,43 @@ enum b_status b_hash_ctx_update(struct b_hash_ctx *ctx, const void *p, size_t le
return B_SUCCESS;
}
static void update_rope(const b_rope *rope, void *arg)
{
struct b_hash_ctx *ctx = arg;
unsigned int type = B_ROPE_TYPE(rope->r_flags);
char tmp[64];
size_t len = 0;
switch (type) {
case B_ROPE_F_CHAR:
b_hash_ctx_update(ctx, &rope->r_v.v_char, sizeof rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
b_hash_ctx_update(
ctx, rope->r_v.v_cstr.s, strlen(rope->r_v.v_cstr.s));
break;
case B_ROPE_F_INT:
len = snprintf(tmp, sizeof tmp, "%" PRIdPTR, rope->r_v.v_int);
b_hash_ctx_update(ctx, tmp, len);
break;
case B_ROPE_F_UINT:
len = snprintf(tmp, sizeof tmp, "%" PRIuPTR, rope->r_v.v_uint);
b_hash_ctx_update(ctx, tmp, len);
break;
default:
break;
}
}
enum b_status b_hash_ctx_update_rope(
struct b_hash_ctx *ctx, const struct b_rope *rope)
{
b_rope_iterate(rope, update_rope, ctx);
return B_SUCCESS;
}
enum b_status b_hash_ctx_finish(
struct b_hash_ctx *ctx, void *out_digest, size_t out_max)
{

View File

@@ -0,0 +1,71 @@
#ifndef BLUE_CORE_BSTR_H_
#define BLUE_CORE_BSTR_H_
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <stdarg.h>
#include <stddef.h>
#define B_BSTR_MAGIC 0x5005500550055005ULL
struct b_rope;
enum b_bstr_flags {
B_BSTR_F_NONE = 0x00u,
B_BSTR_F_ALLOC = 0x01u,
};
typedef struct b_bstr {
uint64_t bstr_magic;
enum b_bstr_flags bstr_flags;
char *bstr_buf;
/* total number of characters in bstr_buf, not including null terminator */
size_t bstr_len;
/* number of bytes allocated for bstr_buf (includes space for the null
* terminator) */
size_t bstr_capacity;
int *bstr_istack;
int bstr_add_indent;
size_t bstr_istack_ptr, bstr_istack_size;
} b_bstr;
BLUE_API void b_bstr_begin(b_bstr *strv, char *buf, size_t max);
BLUE_API void b_bstr_begin_dynamic(b_bstr *strv);
BLUE_API char *b_bstr_end(b_bstr *strv);
BLUE_API b_status b_bstr_reserve(b_bstr *strv, size_t len);
static inline size_t b_bstr_get_size(const b_bstr *str)
{
return str->bstr_len;
}
static inline size_t b_bstr_get_capacity(const b_bstr *str)
{
return str->bstr_capacity;
}
BLUE_API b_status b_bstr_push_indent(b_bstr *strv, int indent);
BLUE_API b_status b_bstr_pop_indent(b_bstr *strv);
BLUE_API b_status b_bstr_write_char(b_bstr *strv, char c);
BLUE_API b_status b_bstr_write_chars(
b_bstr *strv, const char *cs, size_t len, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr(
b_bstr *strv, const char *str, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr_list(
b_bstr *strv, const char **strs, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr_array(
b_bstr *strv, const char **strs, size_t count, size_t *nr_written);
BLUE_API b_status b_bstr_write_cstr_varg(b_bstr *strv, size_t *nr_written, ...);
BLUE_API b_status b_bstr_write_rope(
b_bstr *strv, const struct b_rope *rope, size_t *nr_written);
BLUE_API b_status b_bstr_write_fmt(
b_bstr *strv, size_t *nr_written, const char *format, ...);
BLUE_API b_status b_bstr_write_vfmt(
b_bstr *strv, size_t *nr_written, const char *format, va_list arg);
BLUE_API char *b_bstr_rope(const struct b_rope *rope, size_t *nr_written);
BLUE_API char *b_bstr_fmt(size_t *nr_written, const char *format, ...);
BLUE_API char *b_bstr_vfmt(size_t *nr_written, const char *format, va_list arg);
#endif

View File

@@ -335,6 +335,8 @@ static inline b_btree_node *b_btree_parent(b_btree_node *node)
return node->b_parent;
}
BLUE_API void b_btree_move(b_btree *tree, b_btree_node *dest, b_btree_node *src);
/* get the height of `node`.
the height of a node is defined as the length of the longest path

View File

@@ -5,6 +5,8 @@
#include <stdbool.h>
#include <stdint.h>
B_DECLS_BEGIN;
#define B_WCHAR_INVALID ((b_wchar) - 1)
typedef int32_t b_wchar;
@@ -38,4 +40,6 @@ BLUE_API size_t b_wchar_utf8_codepoint_count(const char *s, size_t nr_bytes);
BLUE_API size_t b_wchar_utf8_string_encoded_size(
const b_wchar *s, size_t nr_codepoints);
B_DECLS_END;
#endif

View File

@@ -29,6 +29,7 @@
#define B_DIGEST_LENGTH_SHAKE256 B_DIGEST_LENGTH_256
struct b_hash_function_ops;
struct b_rope;
typedef enum b_hash_function {
B_HASH_NONE = 0,
@@ -103,6 +104,7 @@ BLUE_API uint64_t b_hash_cstr_ex(const char *s, size_t *len);
BLUE_API b_status b_hash_ctx_init(b_hash_ctx *ctx, b_hash_function func);
BLUE_API b_status b_hash_ctx_reset(b_hash_ctx *ctx);
BLUE_API b_status b_hash_ctx_update(b_hash_ctx *ctx, const void *p, size_t len);
BLUE_API b_status b_hash_ctx_update_rope(b_hash_ctx *ctx, const struct b_rope *rope);
BLUE_API b_status b_hash_ctx_finish(
b_hash_ctx *ctx, void *out_digest, size_t out_max);

View File

@@ -83,7 +83,10 @@ 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);
static inline bool b_iterator_is_valid(const b_iterator *it)
{
return B_OK(b_iterator_get_status(it));
}
B_DECLS_END;

View File

@@ -2,6 +2,7 @@
#define BLUE_CORE_MACROS_H_
#include <blue/core/class.h>
#include <blue/core/misc.h>
#include <blue/core/object.h>
#include <blue/core/thread.h>
#include <blue/core/type.h>
@@ -10,6 +11,8 @@
#define __B_IFACE_I0(p, x) p##x
#define __B_IFACE_I1(p, x) __B_IFACE_I0(p, x)
#define B_STRUCT_EMPTY char _x
/* Type definitions macros (for use in .c source file) */
#define B_TYPE_CLASS_DEFINITION_BEGIN(type_name) \
@@ -186,12 +189,4 @@
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

View File

@@ -8,6 +8,14 @@
#define _Nonnull
#endif
#ifdef __cplusplus
#define B_DECLS_BEGIN extern "C" {
#define B_DECLS_END }
#else
#define B_DECLS_BEGIN
#define B_DECLS_END
#endif
#define B_NPOS ((size_t)-1)
#define b_min(type, x, y) (z__b_min_##type(x, y))

View File

@@ -4,6 +4,8 @@
#include <blue/core/misc.h>
#include <blue/core/type.h>
B_DECLS_BEGIN;
#define B_OBJECT_MAGIC 0xDECAFC0C0ABEEF13ULL
#define B_OBJECT(p) ((b_object *)(p))
@@ -36,4 +38,6 @@ BLUE_API b_object *b_object_create(b_type type);
BLUE_API void b_object_to_string(const b_object *p, B_TYPE_FWDREF(b_stream) * out);
BLUE_API bool b_object_is_type(const b_object *p, b_type type);
B_DECLS_END;
#endif

View File

@@ -35,24 +35,24 @@ static inline void b_queue_init(b_queue *q)
}
static inline bool b_queue_empty(const b_queue *q)
{
return q->q_first == NULL;
return q ? (q->q_first == NULL) : true;
}
static inline b_queue_entry *b_queue_first(const b_queue *q)
{
return q->q_first;
return q ? q->q_first : NULL;
}
static inline b_queue_entry *b_queue_last(const b_queue *q)
{
return q->q_last;
return q ? q->q_last : NULL;
}
static inline b_queue_entry *b_queue_next(const b_queue_entry *entry)
{
return entry->qe_next;
return entry ? entry->qe_next : NULL;
}
static inline b_queue_entry *b_queue_prev(const b_queue_entry *entry)
{
return entry->qe_prev;
return entry ? entry->qe_prev : NULL;
}
BLUE_API b_type b_queue_iterator_get_type(void);
@@ -70,6 +70,7 @@ BLUE_API void b_queue_push_back(b_queue *q, b_queue_entry *entry);
BLUE_API b_queue_entry *b_queue_pop_front(b_queue *q);
BLUE_API b_queue_entry *b_queue_pop_back(b_queue *q);
BLUE_API void b_queue_move(b_queue *q, b_queue_entry *dest, b_queue_entry *src);
BLUE_API void b_queue_delete(b_queue *q, b_queue_entry *entry);
BLUE_API void b_queue_delete_all(b_queue *q);

View File

@@ -3,10 +3,12 @@
#include <blue/core/hash.h>
#include <blue/core/misc.h>
#include <blue/core/stream.h>
#include <stdint.h>
#include <string.h>
struct b_string;
struct b_bstr;
#define B_ROPE_TYPE(f) ((f) & 0xFF)
@@ -94,10 +96,14 @@ BLUE_API void b_rope_init_uint(b_rope *rope, uintptr_t v);
BLUE_API void b_rope_destroy(b_rope *rope);
BLUE_API void b_rope_iterate(
const b_rope *rope, void (*func)(const b_rope *, void *), void *arg);
BLUE_API size_t b_rope_get_size(const b_rope *rope);
BLUE_API void b_rope_concat(b_rope *result, const b_rope *left, const b_rope *right);
BLUE_API void b_rope_join(b_rope *result, const b_rope **ropes, size_t nr_ropes);
BLUE_API void b_rope_to_cstr(const b_rope *rope, char *out, size_t max);
BLUE_API b_status b_rope_to_cstr(const b_rope *rope, char *out, size_t max);
BLUE_API b_status b_rope_to_bstr(const b_rope *rope, struct b_bstr *str);
BLUE_API b_status b_rope_to_string(const b_rope *rope, b_stream *out);
#endif

View File

@@ -48,6 +48,7 @@ B_TYPE_CLASS_DECLARATION_BEGIN(b_stream)
B_TYPE_CLASS_DECLARATION_END(b_stream)
B_TYPE_CLASS_DECLARATION_BEGIN(b_stream_buffer)
B_STRUCT_EMPTY;
B_TYPE_CLASS_DECLARATION_END(b_stream_buffer)
BLUE_API b_type b_stream_get_type();

View File

@@ -14,6 +14,7 @@ B_DECLS_BEGIN;
B_DECLARE_TYPE(b_stringstream);
B_TYPE_CLASS_DECLARATION_BEGIN(b_stringstream)
B_STRUCT_EMPTY;
B_TYPE_CLASS_DECLARATION_END(b_stringstream)
BLUE_API b_type b_stringstream_get_type(void);
@@ -30,20 +31,6 @@ 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

View File

@@ -7,6 +7,8 @@
#include <stdint.h>
#include <string.h>
B_DECLS_BEGIN;
#define B_TYPE_MAX_INTERFACES 64
struct _b_class;
@@ -16,7 +18,7 @@ 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 {
typedef const union b_type_id {
struct {
uint64_t p00, p01;
} a;
@@ -29,11 +31,11 @@ typedef enum b_type_flags {
} b_type_flags;
typedef struct b_type_info {
union b_type t_id;
union b_type t_parent_id;
union b_type_id t_id;
union b_type_id t_parent_id;
const char *t_name;
b_type_flags t_flags;
union b_type t_interfaces[B_TYPE_MAX_INTERFACES];
union b_type_id t_interfaces[B_TYPE_MAX_INTERFACES];
size_t t_nr_interfaces;
size_t t_class_size;
b_class_init_function t_class_init;
@@ -44,9 +46,9 @@ typedef struct b_type_info {
} 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,
union b_type_id *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
uint64_t e);
static inline void b_type_id_copy(b_type src, union b_type *dest)
static inline void b_type_id_copy(b_type src, union b_type_id *dest)
{
dest->a.p00 = src->a.p00;
dest->a.p01 = src->a.p01;
@@ -58,9 +60,11 @@ static inline int b_type_id_compare(b_type a, b_type b)
return 0;
}
return memcmp(a, b, sizeof(union b_type));
return memcmp(a, b, sizeof(union b_type_id));
}
BLUE_API b_result b_type_register(b_type_info *info);
B_DECLS_END;
#endif

View File

@@ -102,6 +102,27 @@ struct b_queue_entry *b_queue_pop_back(struct b_queue *q)
return x;
}
void b_queue_move(b_queue *q, b_queue_entry *dest, b_queue_entry *src)
{
if (src->qe_next) {
src->qe_next->qe_prev = dest;
}
if (src->qe_prev) {
src->qe_prev->qe_next = dest;
}
if (q->q_first == src) {
q->q_first = dest;
}
if (q->q_last == src) {
q->q_last = dest;
}
memmove(dest, src, sizeof *src);
}
void b_queue_delete(struct b_queue *q, struct b_queue_entry *entry)
{
if (!entry) {

View File

@@ -1,3 +1,4 @@
#include <blue/core/bstr.h>
#include <blue/core/rope.h>
#include <inttypes.h>
#include <stdio.h>
@@ -86,6 +87,23 @@ void b_rope_destroy(struct b_rope *rope)
}
}
void b_rope_iterate(
const struct b_rope *rope, void (*func)(const b_rope *, void *), void *arg)
{
if (B_ROPE_TYPE(rope->r_flags) != B_ROPE_F_COMPOSITE) {
func(rope, arg);
return;
}
if (rope->r_v.v_composite.r_left) {
b_rope_iterate(rope->r_v.v_composite.r_left, func, arg);
}
if (rope->r_v.v_composite.r_right) {
b_rope_iterate(rope->r_v.v_composite.r_right, func, arg);
}
}
size_t b_rope_get_size(const struct b_rope *rope)
{
return rope->r_len_total;
@@ -181,56 +199,77 @@ static void rope_iterate(
}
}
struct to_cstr_args {
char *str;
size_t max;
size_t ptr;
};
static void to_cstr(const struct b_rope *rope, void *arg)
static void to_bstr(const struct b_rope *rope, void *arg)
{
struct to_cstr_args *str = arg;
if (str->ptr >= str->max) {
return;
}
b_bstr *str = arg;
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);
b_bstr_write_char(str, rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
nr_written = snprintf(dest, capacity, "%s", rope->r_v.v_cstr.s);
b_bstr_write_cstr(str, rope->r_v.v_cstr.s, NULL);
break;
case B_ROPE_F_INT:
nr_written
= snprintf(dest, capacity, "%" PRIdPTR, rope->r_v.v_int);
b_bstr_write_fmt(str, NULL, "%" PRIdPTR, rope->r_v.v_int);
break;
case B_ROPE_F_UINT:
nr_written
= snprintf(dest, capacity, "%" PRIuPTR, rope->r_v.v_uint);
b_bstr_write_fmt(str, NULL, "%" 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)
static void to_stream(const struct b_rope *rope, void *arg)
{
struct to_cstr_args args = {
.str = out,
.max = max,
.ptr = 0,
};
b_stream *out = arg;
rope_iterate(rope, to_cstr, &args);
unsigned int type = B_ROPE_TYPE(rope->r_flags);
switch (type) {
case B_ROPE_F_CHAR:
b_stream_write_char(out, rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
b_stream_write_string(out, rope->r_v.v_cstr.s, NULL);
break;
case B_ROPE_F_INT:
b_stream_write_fmt(out, NULL, "%" PRIdPTR, rope->r_v.v_int);
break;
case B_ROPE_F_UINT:
b_stream_write_fmt(out, NULL, "%" PRIuPTR, rope->r_v.v_uint);
break;
default:
break;
}
}
b_status b_rope_to_cstr(const struct b_rope *rope, char *out, size_t max)
{
b_bstr str;
b_bstr_begin(&str, out, max);
rope_iterate(rope, to_bstr, &str);
return B_SUCCESS;
}
b_status b_rope_to_bstr(const struct b_rope *rope, b_bstr *str)
{
rope_iterate(rope, to_bstr, str);
return B_SUCCESS;
}
b_status b_rope_to_string(const struct b_rope *rope, b_stream *out)
{
rope_iterate(rope, to_stream, out);
return B_SUCCESS;
}

View File

@@ -1,10 +1,14 @@
#include "printf.h"
#include <blue/core/bstr.h>
#include <blue/core/stream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define READ_MAGIC(p) (*(uint64_t *)p)
#define IS_BSTR(p) (READ_MAGIC(p) == B_BSTR_MAGIC)
#define B_TYPE_STDIO_STREAM (b_stdio_stream_get_type())
#define STREAM_DISPATCH_VIRTUAL(func, stream, ...) \
@@ -369,6 +373,39 @@ static enum b_status stream_read_line_s(
return status;
}
static enum b_status stream_read_line_to_bstr(
struct stream_data *src, struct b_bstr *dest)
{
if (!(src->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) {
status = stream_read_char(src, &c);
if (status != B_SUCCESS) {
break;
}
b_bstr_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)
{
@@ -469,6 +506,57 @@ static enum b_status stream_read_all_bytes_s(
return status;
}
static enum b_status stream_read_all_bytes_to_bstr_s(
struct stream_data *src, struct b_bstr *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 (!buffer) {
return B_ERR_INVALID_ARGUMENT;
}
if (src->s_ops->s_seek) {
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);
b_bstr_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 = b_bstr_write_chars(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)
{
@@ -642,6 +730,10 @@ b_stream *b_stream_open_fp(FILE *fp)
enum b_status b_stream_reserve(b_stream *stream, size_t len)
{
if (IS_BSTR(stream)) {
return B_ERR_NOT_SUPPORTED;
}
B_CLASS_DISPATCH_VIRTUAL(
b_stream, B_TYPE_STREAM, B_ERR_NOT_SUPPORTED, s_reserve, stream,
len);
@@ -650,6 +742,10 @@ enum b_status b_stream_reserve(b_stream *stream, size_t len)
enum b_status b_stream_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin)
{
if (IS_BSTR(stream)) {
return B_ERR_NOT_SUPPORTED;
}
B_CLASS_DISPATCH_VIRTUAL(
b_stream, B_TYPE_STREAM, B_ERR_NOT_SUPPORTED, s_seek, stream,
offset, origin);
@@ -657,37 +753,65 @@ enum b_status b_stream_seek(
size_t b_stream_cursor(const b_stream *stream)
{
if (IS_BSTR(stream)) {
return b_bstr_get_size((b_bstr *)stream);
}
STREAM_DISPATCH_VIRTUAL_0(stream_cursor, stream);
}
enum b_status b_stream_push_indent(b_stream *strp, int indent)
{
if (IS_BSTR(strp)) {
return b_bstr_push_indent((b_bstr *)strp, indent);
}
STREAM_DISPATCH_VIRTUAL(stream_push_indent, strp, indent);
}
enum b_status b_stream_pop_indent(b_stream *strp)
{
if (IS_BSTR(strp)) {
return b_bstr_pop_indent((b_bstr *)strp);
}
STREAM_DISPATCH_VIRTUAL_0(stream_pop_indent, strp);
}
enum b_status b_stream_read_char(b_stream *strp, int *c)
{
if (IS_BSTR(strp)) {
return B_ERR_NOT_SUPPORTED;
}
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)
{
if (IS_BSTR(strp)) {
return B_ERR_NOT_SUPPORTED;
}
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)
{
if (IS_BSTR(strp)) {
return B_ERR_NOT_SUPPORTED;
}
STREAM_DISPATCH_VIRTUAL(stream_read_line, strp, s, max);
}
enum b_status b_stream_read_line_s(b_stream *src, b_stream *dest)
{
if (IS_BSTR(src)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status;
struct stream_data src_p, dest_p;
@@ -696,6 +820,10 @@ enum b_status b_stream_read_line_s(b_stream *src, b_stream *dest)
return status;
}
if (IS_BSTR(dest)) {
return stream_read_line_to_bstr(&src_p, (b_bstr *)dest);
}
status = stream_get_data(dest, &dest_p);
if (!B_OK(status)) {
return status;
@@ -707,12 +835,20 @@ enum b_status b_stream_read_line_s(b_stream *src, b_stream *dest)
enum b_status b_stream_read_all_bytes(
b_stream *stream, void *p, size_t max, size_t *out_nr_read)
{
if (IS_BSTR(stream)) {
return B_ERR_NOT_SUPPORTED;
}
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)
{
if (IS_BSTR(src)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status;
struct stream_data src_p, dest_p;
struct b_stream_buffer_p *buffer_p;
@@ -722,39 +858,66 @@ enum b_status b_stream_read_all_bytes_s(
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;
}
if (IS_BSTR(dest)) {
return stream_read_all_bytes_to_bstr_s(
&src_p, (b_bstr *)dest, buffer_p, out_nr_read);
}
status = stream_get_data(dest, &dest_p);
if (!B_OK(status)) {
return status;
}
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)
{
if (IS_BSTR(stream)) {
return b_bstr_write_char((b_bstr *)stream, 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)
{
if (IS_BSTR(stream)) {
return b_bstr_write_cstr((b_bstr *)stream, s, 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)
{
if (IS_BSTR(stream)) {
return b_bstr_write_chars((b_bstr *)stream, buf, count, 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, ...)
{
if (IS_BSTR(stream)) {
va_list arg;
va_start(arg, format);
b_status w = b_bstr_write_vfmt(
(b_bstr *)stream, nr_written, format, arg);
va_end(arg);
return w;
}
struct stream_data p;
enum b_status status = stream_get_data(stream, &p);
@@ -773,6 +936,10 @@ enum b_status b_stream_write_fmt(
enum b_status b_stream_write_vfmt(
b_stream *stream, size_t *nr_written, const char *format, va_list arg)
{
if (IS_BSTR(stream)) {
return b_bstr_write_vfmt((b_bstr *)stream, nr_written, format, arg);
}
struct stream_data p;
enum b_status status = stream_get_data(stream, &p);

View File

@@ -10,6 +10,7 @@
struct b_stringstream_p {
char *ss_buf;
size_t ss_ptr;
size_t ss_len;
size_t ss_max;
unsigned char ss_alloc;
@@ -17,6 +18,50 @@ struct b_stringstream_p {
/*** PRIVATE FUNCTIONS ********************************************************/
static enum b_status __getc(struct b_stringstream_p *ss, b_wchar *out)
{
size_t available = ss->ss_len - ss->ss_ptr;
const char *p = ss->ss_buf + ss->ss_ptr;
size_t to_copy = b_wchar_utf8_codepoint_stride(p);
if (to_copy > available) {
return B_ERR_BAD_STATE;
}
b_wchar c = b_wchar_utf8_codepoint_decode(p);
*out = c;
if (c == B_WCHAR_INVALID) {
return B_ERR_BAD_STATE;
}
ss->ss_ptr += to_copy;
return B_SUCCESS;
}
static enum b_status __gets(
struct b_stringstream_p *ss, char *s, size_t len, size_t *nr_read)
{
size_t available = ss->ss_len - ss->ss_ptr;
size_t to_copy = len;
if (available < to_copy) {
to_copy = available;
}
memcpy(s, ss->ss_buf + ss->ss_ptr, to_copy);
ss->ss_ptr += to_copy;
if (nr_read) {
*nr_read = to_copy;
}
return B_SUCCESS;
}
static enum b_status __puts(
struct b_stringstream_p *ss, const char *s, size_t len, size_t *nr_written)
{
@@ -111,7 +156,7 @@ b_stringstream *b_stringstream_create_with_buffer(char *buf, size_t max)
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;
cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE | Z__B_STREAM_STATIC;
p->ss_buf = buf;
p->ss_max = max;
@@ -131,7 +176,7 @@ b_stringstream *b_stringstream_create(void)
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;
cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE | Z__B_STREAM_STATIC;
p->ss_buf = malloc(DEFAULT_CAPACITY + 1);
if (!p->ss_buf) {
@@ -193,6 +238,26 @@ static void stringstream_fini(b_object *obj, void *priv)
}
}
enum b_status stream_getc(b_stream *stream, b_wchar *c)
{
struct b_stringstream_p *s
= b_object_get_private(stream, B_TYPE_STRINGSTREAM);
enum b_status status = __getc(s, c);
return status;
}
enum b_status stream_read(b_stream *stream, void *buf, size_t count, size_t *nr_read)
{
struct b_stringstream_p *s
= b_object_get_private(stream, B_TYPE_STRINGSTREAM);
enum b_status status = __gets(s, buf, count, nr_read);
return status;
}
enum b_status stream_write(
b_stream *stream, const void *buf, size_t count, size_t *nr_written)
{
@@ -215,8 +280,8 @@ B_TYPE_CLASS_DEFINITION_BEGIN(b_stringstream)
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_getc) = stream_getc;
B_INTERFACE_ENTRY(s_read) = stream_read;
B_INTERFACE_ENTRY(s_write) = stream_write;
B_INTERFACE_ENTRY(s_reserve) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)

View File

@@ -12,7 +12,7 @@
#include <string.h>
static struct b_btree type_list = B_BTREE_INIT;
static union b_type zero_id = {0};
static union b_type_id zero_id = {0};
struct type_init_ctx {
size_t ctx_class_offset;
@@ -39,7 +39,7 @@ B_BTREE_DEFINE_INSERT(
put_type_component, component_compare)
static struct b_type_registration *get_type(
const b_btree *tree, const union b_type *key)
const b_btree *tree, const union b_type_id *key)
{
b_btree_node *cur = tree->b_root;
while (cur) {
@@ -60,7 +60,7 @@ static struct b_type_registration *get_type(
}
struct b_type_component *b_type_get_component(
const b_btree *tree, const union b_type *key)
const b_btree *tree, const union b_type_id *key)
{
b_btree_node *cur = tree->b_root;
while (cur) {
@@ -96,7 +96,7 @@ static struct b_type_component *create_type_component(
}
void b_type_id_init(
union b_type *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
union b_type_id *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d,
uint64_t e)
{
b_i32 x_a = b_i32_htob(a);
@@ -157,7 +157,7 @@ static b_result locate_interface(
}
static b_result locate_interfaces(
const union b_type *interfaces, size_t nr_interfaces,
const union b_type_id *interfaces, size_t nr_interfaces,
struct b_type_registration *dest, struct type_init_ctx *init_ctx)
{
b_result result = B_RESULT_SUCCESS;

View File

@@ -35,6 +35,6 @@ struct b_type_registration {
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);
const b_btree *tree, const union b_type_id *key);
#endif

View File

@@ -0,0 +1,38 @@
#include <blue/ds/bitbuffer.h>
/*** PRIVATE DATA *************************************************************/
struct b_bitbuffer_p {
int x;
};
/*** PRIVATE FUNCTIONS ********************************************************/
/*** PUBLIC FUNCTIONS *********************************************************/
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
/*** VIRTUAL FUNCTIONS ********************************************************/
static void bitbuffer_init(b_object *obj, void *priv)
{
struct b_bitbuffer_p *bitbuffer = priv;
}
static void bitbuffer_fini(b_object *obj, void *priv)
{
struct b_bitbuffer_p *bitbuffer = priv;
}
/*** CLASS DEFINITION *********************************************************/
B_TYPE_CLASS_DEFINITION_BEGIN(b_bitbuffer)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_bitbuffer)
B_TYPE_DEFINITION_BEGIN(b_bitbuffer)
B_TYPE_ID(0x628e33da, 0x3109, 0x4a5d, 0x98d5, 0xb0e4cb3ccb65);
B_TYPE_CLASS(b_bitbuffer_class);
B_TYPE_INSTANCE_PRIVATE(struct b_bitbuffer_p);
B_TYPE_INSTANCE_INIT(bitbuffer_init);
B_TYPE_INSTANCE_FINI(bitbuffer_fini);
B_TYPE_DEFINITION_END(b_bitbuffer)

View File

@@ -366,6 +366,54 @@ bool b_hashmap_is_empty(const b_hashmap *hashmap)
B_CLASS_DISPATCH_STATIC_0(B_TYPE_HASHMAP, hashmap_is_empty, hashmap);
}
b_iterator *b_hashmap_begin(b_hashmap *hashmap)
{
b_hashmap_iterator *it_obj = b_object_create(B_TYPE_HASHMAP_ITERATOR);
struct b_hashmap_iterator_p *it
= b_object_get_private(it_obj, B_TYPE_HASHMAP_ITERATOR);
it->_h = hashmap;
it->_h_p = b_object_get_private(hashmap, B_TYPE_HASHMAP);
it->i = 0;
if (b_hashmap_is_empty(hashmap)) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
struct b_btree_node *first_node = b_btree_first(&it->_h_p->h_buckets);
struct b_hashmap_bucket *first_bucket
= b_unbox(struct b_hashmap_bucket, first_node, bk_node);
if (!first_bucket) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
struct b_queue_entry *first_entry = b_queue_first(&first_bucket->bk_items);
struct b_hashmap_bucket_item *first_item
= b_unbox(struct b_hashmap_bucket_item, first_entry, bi_entry);
if (!first_item) {
memset(&it->item, 0x0, sizeof it->item);
b_iterator_set_status(it_obj, B_ERR_NO_DATA);
return it_obj;
}
memcpy(&it->item.key, &first_item->bi_key, sizeof it->item.key);
memcpy(&it->item.value, &first_item->bi_value, sizeof it->item.value);
it->_cbn = first_node;
it->_cqe = first_entry;
return it_obj;
}
const b_iterator *b_hashmap_cbegin(const b_hashmap *hashmap)
{
return b_hashmap_begin((b_hashmap *)hashmap);
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void hashmap_init(b_object *obj, void *priv)
@@ -410,54 +458,6 @@ static void hashmap_fini(b_object *obj, void *priv)
/*** 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
@@ -485,7 +485,7 @@ static enum b_status iterator_move_next(const b_iterator *obj)
it->_cbn = next_node;
it->_cqe = next_entry;
return true;
return B_SUCCESS;
}
static enum b_status iterator_erase(b_iterator *obj)
@@ -562,8 +562,8 @@ B_TYPE_CLASS_DEFINITION_BEGIN(b_hashmap)
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_INTERFACE_ENTRY(it_begin) = b_hashmap_begin;
B_INTERFACE_ENTRY(it_cbegin) = b_hashmap_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_hashmap)

View File

@@ -1,22 +1,15 @@
#ifndef BLUE_OBJECT_BITBUFFER_H_
#define BLUE_OBJECT_BITBUFFER_H_
#ifndef BLUE_DS_BITBUFFER_H_
#define BLUE_DS_BITBUFFER_H_
#include <blue/ds/object.h>
#include <blue/core/macros.h>
#define B_BITBUFFER(p) ((b_bitbuffer *)(p))
B_DECLS_BEGIN;
typedef struct b_bitbuffer b_bitbuffer;
B_DECLARE_TYPE(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));
}
B_TYPE_CLASS_DECLARATION_BEGIN(b_bitbuffer)
;
B_TYPE_CLASS_DECLARATION_END(b_bitbuffer);
BLUE_API b_status b_bitbuffer_put_bit(b_bitbuffer *buf, int bit);
BLUE_API b_status b_bitbuffer_put_bool(b_bitbuffer *buf, bool b);
@@ -27,4 +20,6 @@ BLUE_API b_status b_bitbuffer_put_bytes(
BLUE_API b_status b_bitbuffer_put_string(
b_bitbuffer *buf, const char *p, size_t len, size_t bits_per_char);
B_DECLS_END;
#endif

View File

@@ -75,6 +75,9 @@ BLUE_API bool b_hashmap_has_key(const b_hashmap *hashmap, const b_hashmap_key *k
BLUE_API size_t b_hashmap_get_size(const b_hashmap *hashmap);
BLUE_API bool b_hashmap_is_empty(const b_hashmap *hashmap);
BLUE_API b_iterator *b_hashmap_begin(b_hashmap *hashmap);
BLUE_API const b_iterator *b_hashmap_cbegin(const b_hashmap *hashmap);
B_DECLS_END;
#endif

View File

@@ -56,7 +56,7 @@ BLUE_API void b_list_delete_all(b_list *q);
BLUE_API void *b_list_entry_value(const b_list_entry *entry);
BLUE_API b_iterator *b_list_begin(b_list *q);
BLUE_API b_iterator *b_list_cbegin(const b_list *q);
BLUE_API const b_iterator *b_list_cbegin(const b_list *q);
B_DECLS_END;

View File

@@ -17,8 +17,11 @@ B_DECLARE_TYPE(b_uuid);
B_TYPE_CLASS_DECLARATION_BEGIN(b_uuid)
B_TYPE_CLASS_DECLARATION_END(b_uuid)
typedef struct b_uuid_bytes {
unsigned char uuid_bytes[B_UUID_NBYTES];
typedef union b_uuid_bytes {
uint8_t uuid_bytes[B_UUID_NBYTES];
uint16_t uuid_words[B_UUID_NBYTES / 2];
uint32_t uuid_dwords[B_UUID_NBYTES / 4];
uint64_t uuid_qwords[B_UUID_NBYTES / 8];
} b_uuid_bytes;
BLUE_API b_type b_uuid_get_type(void);

View File

@@ -365,22 +365,7 @@ void *b_list_entry_value(const struct b_list_entry *entry)
return entry ? entry->e_data : NULL;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void list_init(b_object *obj, void *priv)
{
struct b_list_p *list = priv;
}
static void list_fini(b_object *obj, void *priv)
{
struct b_list_p *list = priv;
list_delete_all(list);
}
/*** ITERATOR FUNCTIONS *******************************************************/
static b_iterator *iterable_begin(b_list *q)
b_iterator *b_list_begin(b_list *q)
{
b_list_iterator *it_obj = b_object_create(B_TYPE_LIST_ITERATOR);
struct b_list_iterator_p *it
@@ -399,7 +384,7 @@ static b_iterator *iterable_begin(b_list *q)
return 0;
}
static const b_iterator *iterable_cbegin(const b_list *q)
const b_iterator *b_list_cbegin(const b_list *q)
{
b_list_iterator *it_obj = b_object_create(B_TYPE_LIST_ITERATOR);
struct b_list_iterator_p *it
@@ -418,6 +403,21 @@ static const b_iterator *iterable_cbegin(const b_list *q)
return 0;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void list_init(b_object *obj, void *priv)
{
struct b_list_p *list = priv;
}
static void list_fini(b_object *obj, void *priv)
{
struct b_list_p *list = priv;
list_delete_all(list);
}
/*** ITERATOR FUNCTIONS *******************************************************/
static enum b_status iterator_move_next(const b_iterator *obj)
{
struct b_list_iterator_p *it
@@ -493,8 +493,8 @@ B_TYPE_CLASS_DEFINITION_BEGIN(b_list)
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_INTERFACE_ENTRY(it_begin) = b_list_begin;
B_INTERFACE_ENTRY(it_cbegin) = b_list_cbegin;
B_TYPE_CLASS_INTERFACE_END(b_iterable, B_TYPE_ITERABLE)
B_TYPE_CLASS_DEFINITION_END(b_list)

View File

@@ -8,7 +8,8 @@
#include <stdlib.h>
#include <string.h>
/* maximum length of string that can be stored inline, not including null-terminator */
/* maximum length of string that can be stored inline, not including
* null-terminator */
#define STRING_INLINE_CAPACITY 15
#define IS_VALID_UTF8_SCALAR(x) \
@@ -243,7 +244,8 @@ static int string_change_capacity(struct b_string_p *str, size_t capacity)
bool is_now_inline = capacity == STRING_INLINE_CAPACITY;
if (capacity == old_capacity) {
/* this also handles the case where the old and new capacity both fit into the inline buffer. */
/* this also handles the case where the old and new capacity
* both fit into the inline buffer. */
return 0;
}
@@ -1447,6 +1449,7 @@ static enum b_status chars_iterator_move_next(struct b_string_iterator_p *it)
it->codepoint_index += 1;
if (it->byte_index >= it->_s_p->s_len) {
it->char_value = B_WCHAR_INVALID;
return B_ERR_NO_DATA;
}

View File

@@ -9,7 +9,7 @@
/*** PRIVATE DATA *************************************************************/
struct b_uuid_p {
struct b_uuid_bytes uuid_bytes;
union b_uuid_bytes uuid_bytes;
};
/*** PRIVATE FUNCTIONS ********************************************************/
@@ -39,12 +39,12 @@ static void uuid_get_bytes(
}
static void uuid_get_uuid_bytes(
const struct b_uuid_p *uuid, struct b_uuid_bytes *bytes)
const struct b_uuid_p *uuid, union b_uuid_bytes *bytes)
{
memcpy(bytes, &uuid->uuid_bytes, sizeof *bytes);
}
static struct b_uuid_bytes *uuid_ptr(struct b_uuid_p *uuid)
static union b_uuid_bytes *uuid_ptr(struct b_uuid_p *uuid)
{
return &uuid->uuid_bytes;
}
@@ -101,7 +101,7 @@ b_uuid *b_uuid_create_from_bytev(const unsigned char bytes[B_UUID_NBYTES])
b_uuid *b_uuid_create_from_cstr(const char *str)
{
struct b_uuid_bytes bytes;
union b_uuid_bytes bytes;
bool valid = true;
bool is_guid = false;
@@ -169,19 +169,19 @@ void b_uuid_get_bytes(const b_uuid *uuid, unsigned char bytes[B_UUID_NBYTES])
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_get_bytes, uuid, bytes);
}
void b_uuid_get_uuid_bytes(const b_uuid *uuid, struct b_uuid_bytes *bytes)
void b_uuid_get_uuid_bytes(const b_uuid *uuid, union b_uuid_bytes *bytes)
{
B_CLASS_DISPATCH_STATIC(B_TYPE_UUID, uuid_get_uuid_bytes, uuid, bytes);
}
struct b_uuid_bytes *b_uuid_ptr(b_uuid *uuid)
union b_uuid_bytes *b_uuid_ptr(b_uuid *uuid)
{
B_CLASS_DISPATCH_STATIC_0(B_TYPE_UUID, uuid_ptr, uuid);
}
/*** PUBLIC ALIAS FUNCTIONS ***************************************************/
b_uuid *b_uuid_create_from_uuid_bytes(const struct b_uuid_bytes *bytes)
b_uuid *b_uuid_create_from_uuid_bytes(const union b_uuid_bytes *bytes)
{
return b_uuid_create_from_bytev(bytes->uuid_bytes);
}

18
test/core-mm/streams.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include <blue/core/stream.hpp>
#include <blue/core/stringstream.hpp>
#include <iostream>
using namespace blue::core;
int main(void)
{
stream &out = stream::out();
out.write_fmt("Hello, %d\n", 32);
stringstream s;
s.write_fmt("Hello, %d\n", 64);
std::cout << s.get_ptr();
return 0;
}

View File

@@ -1,6 +1,60 @@
#include <blue/core/rope.h>
#include <inttypes.h>
#include <stdio.h>
static void print_rope(const struct b_rope *rope, int depth)
{
for (int i = 0; i < depth; i++) {
printf(" ");
}
printf("[%x:", rope->r_flags);
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_CHAR) && printf(" CHAR");
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_CSTR) && printf(" CSTR");
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_CSTR_BORROWED)
&& printf(" CSTR_BORROWED");
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_CSTR_STATIC)
&& printf(" CSTR_STATIC");
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_INT) && printf(" INT");
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_UINT) && printf(" UINT");
(B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_COMPOSITE)
&& printf(" COMPOSITE");
(rope->r_flags & B_ROPE_F_MALLOC) && printf(" MALLOC");
printf("] ");
switch (B_ROPE_TYPE(rope->r_flags)) {
case B_ROPE_F_CHAR:
printf("%c", rope->r_v.v_char);
break;
case B_ROPE_F_CSTR:
case B_ROPE_F_CSTR_BORROWED:
case B_ROPE_F_CSTR_STATIC:
printf("%s", rope->r_v.v_cstr.s);
break;
case B_ROPE_F_INT:
printf("%" PRIdPTR, rope->r_v.v_int);
break;
case B_ROPE_F_UINT:
printf("%" PRIuPTR, rope->r_v.v_uint);
break;
default:
break;
}
printf("\n");
if (B_ROPE_TYPE(rope->r_flags) == B_ROPE_F_COMPOSITE) {
if (rope->r_v.v_composite.r_left) {
print_rope(rope->r_v.v_composite.r_left, depth + 1);
}
if (rope->r_v.v_composite.r_right) {
print_rope(rope->r_v.v_composite.r_right, depth + 1);
}
}
}
int main(void)
{
b_rope a = B_ROPE_CHAR('a');
@@ -19,6 +73,8 @@ int main(void)
b_rope_join(&str, ropes, sizeof ropes / sizeof ropes[0]);
print_rope(&str, 0);
char cstr[1024];
b_rope_to_cstr(&str, cstr, sizeof cstr);
b_rope_destroy(&str);

View File

@@ -1,3 +1,4 @@
#include <blue/core/bstr.h>
#include <blue/core/stream.h>
#include <stdio.h>
@@ -6,5 +7,15 @@ int main(void)
b_stream_read_line_s(b_stdin, b_stdout);
b_stream_write_char(b_stdout, '\n');
char s[16];
b_bstr str;
b_bstr_begin(&str, s, sizeof s);
b_stream_read_line_s(b_stdin, (b_stream *)&str);
b_stream_write_char((b_stream *)&str, '\n');
const char *e = b_bstr_end(&str);
fputs(e, stdout);
return 0;
}