From 816f2449b3c77770586411c3ab89e5c00a41517c Mon Sep 17 00:00:00 2001 From: YI Date: Wed, 6 Sep 2023 20:44:32 +0800 Subject: [PATCH 01/18] update ckb-c-stdlib files from upstream --- include/ckb-c-stdlib/Makefile | 18 ++++++++++- include/ckb-c-stdlib/ckb_consts.h | 2 ++ include/ckb-c-stdlib/ckb_dlfcn.h | 32 ++++++++++++++----- include/ckb-c-stdlib/ckb_syscall_apis.h | 18 ++++++----- include/ckb-c-stdlib/ckb_syscalls.h | 42 ++++++++++--------------- include/ckb-c-stdlib/ckb_type_id.h | 11 +++++-- include/ckb-c-stdlib/libc/entry.h | 2 ++ include/ckb-c-stdlib/libc/limits.h | 2 ++ 8 files changed, 85 insertions(+), 42 deletions(-) diff --git a/include/ckb-c-stdlib/Makefile b/include/ckb-c-stdlib/Makefile index 4e73536..78ae9a3 100644 --- a/include/ckb-c-stdlib/Makefile +++ b/include/ckb-c-stdlib/Makefile @@ -1,5 +1,21 @@ +CC := riscv64-unknown-elf-gcc +AR := riscv64-unknown-elf-ar +LIB := libdummylibc.a +CFLAGS := -Wall -Werror -Wextra -Wno-unused-parameter -Wno-dangling-pointer -Wno-nonnull -Wno-nonnull-compare -fno-builtin-printf -fno-builtin-memcmp -O3 -g -fdata-sections -ffunction-sections + +default: fmt + fmt: clang-format -i -style=Google $(wildcard *.h */*.h *.c */*.c libc/*.h libc/src/*.c) git diff --exit-code -.PHONY: fmt +$(LIB): impl.o + $(AR) rcs $@ $^ + +impl.o: libc/src/impl.c + $(CC) $(CFLAGS) -c $< -o $@ -I libc -D__SHARED_LIBRARY__ + +clean: + rm -rf $(LIB) impl.o + +.PHONY: clean default fmt diff --git a/include/ckb-c-stdlib/ckb_consts.h b/include/ckb-c-stdlib/ckb_consts.h index 6fa707c..0b9f380 100644 --- a/include/ckb-c-stdlib/ckb_consts.h +++ b/include/ckb-c-stdlib/ckb_consts.h @@ -22,6 +22,8 @@ #define SYS_ckb_spawn 2101 #define SYS_ckb_get_memory_limit 2102 #define SYS_ckb_set_content 2103 +#define SYS_ckb_load_block_extension 2104 +#define SYS_ckb_current_memory 2105 #define CKB_SUCCESS 0 #define CKB_INDEX_OUT_OF_BOUND 1 diff --git a/include/ckb-c-stdlib/ckb_dlfcn.h b/include/ckb-c-stdlib/ckb_dlfcn.h index 6f43063..3ca4565 100644 --- a/include/ckb-c-stdlib/ckb_dlfcn.h +++ b/include/ckb-c-stdlib/ckb_dlfcn.h @@ -81,6 +81,7 @@ typedef struct { } Elf64_Sym; #define R_RISCV_RELATIVE 3 +#define R_RISCV_JUMP_SLOT 5 typedef struct { uint64_t r_offset; @@ -103,6 +104,7 @@ typedef struct { #define ERROR_MEMORY_NOT_ENOUGH -23 #define ERROR_OUT_OF_BOUND -24 #define ERROR_INVALID_ARGS -25 +#define ERROR_ELF_NOT_ALIGNED -26 typedef struct { Elf64_Sym *dynsyms; @@ -245,8 +247,21 @@ int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type, if (addr2 == 0) { return ERROR_INVALID_ELF; } - ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset, ph->p_filesz, - index, CKB_SOURCE_CELL_DEP); + /* + * There is a slight defect in current syscall: if the padding + * required for memory alignment is bigger than the ELF starting + * offset to load, there is not a way for current syscall to correctly + * load the ELF. We use a check here to guard for the condition, and + * exit when it is not satisfied. A better solution might to explicitly + * ask for page aligned code section in linker, or wait for a fixed + * syscall version. + */ + if (ph->p_offset < prepad) { + return ERROR_ELF_NOT_ALIGNED; + } + ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset - prepad, + ph->p_filesz + prepad, index, + CKB_SOURCE_CELL_DEP); if (ret != CKB_SUCCESS) { return ret; } @@ -358,9 +373,12 @@ int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type, current_offset += load_size * sizeof(Elf64_Rela); for (size_t j = 0; j < load_size; j++) { Elf64_Rela *r = &relocations[j]; - if (r->r_info != R_RISCV_RELATIVE) { - /* Only relative relocation is supported now, we might add more - * later */ + uint32_t t = (uint32_t) r->r_info; + if (t != R_RISCV_RELATIVE && t != R_RISCV_JUMP_SLOT) { + /* + * Only relative and jump slot relocations are supported now, + * we might add more later. + */ return ERROR_INVALID_ELF; } if (r->r_offset >= (aligned_size - sizeof(uint64_t)) || @@ -377,7 +395,7 @@ int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type, return ERROR_INVALID_ELF; } uint8_t *addr2 = - addr_offset_checked(aligned_addr, aligned_size, sh->sh_offset); + addr_offset_checked(aligned_addr, aligned_size, sh->sh_addr); if (addr2 == 0) { return ERROR_INVALID_ELF; } @@ -396,7 +414,7 @@ int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type, const char *current_str = shrtab + sh->sh_name; if (strcmp(DYNSTR, current_str) == 0) { const uint8_t *addr2 = - addr_offset_checked(aligned_addr, aligned_size, sh->sh_offset); + addr_offset_checked(aligned_addr, aligned_size, sh->sh_addr); if (addr2 == 0) { return ERROR_INVALID_ELF; } diff --git a/include/ckb-c-stdlib/ckb_syscall_apis.h b/include/ckb-c-stdlib/ckb_syscall_apis.h index 9566e81..3e7486c 100644 --- a/include/ckb-c-stdlib/ckb_syscall_apis.h +++ b/include/ckb-c-stdlib/ckb_syscall_apis.h @@ -42,13 +42,17 @@ int ckb_dlopen2(const uint8_t* dep_cell_hash, uint8_t hash_type, size_t* consumed_size); void* ckb_dlsym(void* handle, const char* symbol); -int ckb_spawn(uint64_t memory_limit, size_t index, size_t source, size_t bounds, - int argc, const char* argv[], int8_t* exit_code, uint8_t* content, - uint64_t* content_length); -int ckb_spawn_cell(uint64_t memory_limit, const uint8_t* code_hash, - uint8_t hash_type, uint32_t offset, uint32_t length, - int argc, const char* argv[], int8_t* exit_code, - uint8_t* content, uint64_t* content_length); +typedef struct spawn_args_t { + uint64_t memory_limit; + int8_t* exit_code; + uint8_t* content; + uint64_t* content_length; +} spawn_args_t; +int ckb_spawn(size_t index, size_t source, size_t bounds, int argc, + const char* argv[], spawn_args_t* spgs); +int ckb_spawn_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, + uint32_t length, int argc, const char* argv[], + spawn_args_t* spgs); int ckb_get_memory_limit(); int ckb_set_content(uint8_t* content, uint64_t* length); diff --git a/include/ckb-c-stdlib/ckb_syscalls.h b/include/ckb-c-stdlib/ckb_syscalls.h index 92c179c..39a54d7 100644 --- a/include/ckb-c-stdlib/ckb_syscalls.h +++ b/include/ckb-c-stdlib/ckb_syscalls.h @@ -377,37 +377,21 @@ int ckb_exec_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, argv); } -typedef struct { - uint64_t memory_limit; - int8_t* exit_code; - uint8_t* content; - uint64_t* content_length; -} spawn_args; - -int ckb_spawn(uint64_t memory_limit, size_t index, size_t source, size_t bounds, - int argc, const char* argv[], int8_t* exit_code, uint8_t* content, - uint64_t* content_length) { - spawn_args spgs = { - .memory_limit = memory_limit, - .exit_code = exit_code, - .content = content, - .content_length = content_length, - }; - return syscall(SYS_ckb_spawn, index, source, bounds, argc, argv, &spgs); -} - -int ckb_spawn_cell(uint64_t memory_limit, const uint8_t* code_hash, - uint8_t hash_type, uint32_t offset, uint32_t length, - int argc, const char* argv[], int8_t* exit_code, - uint8_t* content, uint64_t* content_length) { +int ckb_spawn(size_t index, size_t source, size_t bounds, int argc, + const char* argv[], spawn_args_t* spgs) { + return syscall(SYS_ckb_spawn, index, source, bounds, argc, argv, spgs); +} + +int ckb_spawn_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, + uint32_t length, int argc, const char* argv[], + spawn_args_t* spgs) { size_t index = SIZE_MAX; int ret = ckb_look_for_dep_with_hash2(code_hash, hash_type, &index); if (ret != CKB_SUCCESS) { return ret; } size_t bounds = ((size_t)offset << 32) | length; - return ckb_spawn(memory_limit, index, CKB_SOURCE_CELL_DEP, bounds, argc, argv, - exit_code, content, content_length); + return ckb_spawn(index, CKB_SOURCE_CELL_DEP, bounds, argc, argv, spgs); } int ckb_get_memory_limit() { @@ -418,6 +402,14 @@ int ckb_set_content(uint8_t* content, uint64_t* length) { return syscall(SYS_ckb_set_content, content, length, 0, 0, 0, 0); } +int ckb_current_memory() { + return syscall(SYS_ckb_current_memory, 0, 0, 0, 0, 0, 0); +} + +int ckb_load_block_extension(void* addr, uint64_t* len, size_t offset, size_t index, size_t source) { + return syscall(SYS_ckb_load_block_extension, addr, len, offset, index, source, 0); +} + #endif /* CKB_STDLIB_NO_SYSCALL_IMPL */ #endif /* CKB_C_STDLIB_CKB_SYSCALLS_H_ */ diff --git a/include/ckb-c-stdlib/ckb_type_id.h b/include/ckb-c-stdlib/ckb_type_id.h index 7c28f2c..897fd90 100644 --- a/include/ckb-c-stdlib/ckb_type_id.h +++ b/include/ckb-c-stdlib/ckb_type_id.h @@ -83,9 +83,16 @@ int _ckb_locate_first_type_id_output_index(uint64_t* index) { len = 32; ret = ckb_load_cell_by_field(buffer, &len, 0, i, CKB_SOURCE_OUTPUT, CKB_CELL_FIELD_TYPE_HASH); + if (ret != CKB_SUCCESS) { - DEBUG("Error fetching output type hash to locate type id index!"); - return ret; + if (ret != CKB_ITEM_MISSING) { + DEBUG("Error fetching output type hash to locate type id index!"); + return ret; + } else { + // type script hash can be missing, it's not error + i += 1; + continue; + } } if (len != 32) { DEBUG("Invalid type hash length!"); diff --git a/include/ckb-c-stdlib/libc/entry.h b/include/ckb-c-stdlib/libc/entry.h index 1293343..1b13464 100644 --- a/include/ckb-c-stdlib/libc/entry.h +++ b/include/ckb-c-stdlib/libc/entry.h @@ -9,9 +9,11 @@ __attribute__((visibility("default"))) __attribute__((naked)) void _start() { asm volatile( ".option push\n" ".option norelax\n" +#ifndef CKB_NO_ENTRY_GP "1:auipc gp, %pcrel_hi(__global_pointer$)\n" "addi gp, gp, %pcrel_lo(1b)\n" ".option pop\n" +#endif /* * By default CKB VM initializes all memory to 0, there's no need * to clear BSS segment again. diff --git a/include/ckb-c-stdlib/libc/limits.h b/include/ckb-c-stdlib/libc/limits.h index fba3ff3..258f6aa 100644 --- a/include/ckb-c-stdlib/libc/limits.h +++ b/include/ckb-c-stdlib/libc/limits.h @@ -86,6 +86,7 @@ #define __LONG_LONG_MAX__ 9223372036854775807LL #endif +#if __ISO_C_VISIBLE >= 1999 /* Minimum and maximum values a `signed long long int' can hold. */ #undef LLONG_MIN #define LLONG_MIN (-LLONG_MAX - 1) @@ -95,6 +96,7 @@ /* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ #undef ULLONG_MAX #define ULLONG_MAX (LLONG_MAX * 2ULL + 1) +#endif #if __GNU_VISIBLE /* Minimum and maximum values a `signed long long int' can hold. */ From 531ed077631bcce56d62e97deb70e17324107626 Mon Sep 17 00:00:00 2001 From: YI Date: Wed, 6 Sep 2023 20:56:36 +0800 Subject: [PATCH 02/18] define __ISO_C_VISIBLE as we need LLONG_MAX in lua --- Makefile | 2 +- lualib/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 77cf7a2..3f3504f 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CC := $(TARGET)-gcc LD := $(TARGET)-gcc OBJCOPY := $(TARGET)-objcopy -CFLAGS := -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I lualib -I include/ckb-c-stdlib -I include/ckb-c-stdlib/libc -I include/ckb-c-stdlib/molecule -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g +CFLAGS := -D__ISO_C_VISIBLE=1999 -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I lualib -I include/ckb-c-stdlib -I include/ckb-c-stdlib/libc -I include/ckb-c-stdlib/molecule -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g LDFLAGS := -nostdlib -nostartfiles -fno-builtin -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections diff --git a/lualib/Makefile b/lualib/Makefile index bcbf47e..30d68ac 100644 --- a/lualib/Makefile +++ b/lualib/Makefile @@ -10,7 +10,7 @@ CC=riscv64-unknown-linux-gnu-gcc # -ULUA_USE_LINUX -ULUA_USE_POSIX to make lua dependencies minimal, # otherwise, we may unable to find various platform dependent symbols, e.g. # setsignal. -CFLAGS= -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) +CFLAGS= -D__ISO_C_VISIBLE=1999 -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) LIBS= -lm $(SYSLIBS) $(MYLIBS) From 10d448e06ee0652accbefe2e35388971835d8e75 Mon Sep 17 00:00:00 2001 From: YI Date: Wed, 6 Sep 2023 21:40:04 +0800 Subject: [PATCH 03/18] use latest spawn api --- examples/spawn.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/spawn.c b/examples/spawn.c index e6ecd2f..4c8f61a 100644 --- a/examples/spawn.c +++ b/examples/spawn.c @@ -6,12 +6,18 @@ int main() { const char *argv[] = {"-e", "local m = arg[2] .. arg[3]; ckb.set_content(m)", "hello", "world"}; - int8_t exit_code = -1; uint8_t content[80] = {}; uint64_t content_length = 80; + int8_t exit_code = -1; + + spawn_args_t spgs = { + .memory_limit = 8, + .exit_code = &exit_code, + .content = content, + .content_length = &content_length, + }; - int success = - ckb_spawn(8, 1, 3, 0, 4, argv, &exit_code, &content[0], &content_length); + int success = ckb_spawn(1, 3, 0, 4, argv, &spgs); if (success != 0) { return 1; } From 2642387ce5bc0f207a0a13e51b72ca1f21ebe8b9 Mon Sep 17 00:00:00 2001 From: YI Date: Wed, 6 Sep 2023 22:04:08 +0800 Subject: [PATCH 04/18] remove vendored ckb-c-stdlib --- include/ckb-c-stdlib/.gitignore | 53 - include/ckb-c-stdlib/.travis.yml | 17 - include/ckb-c-stdlib/LICENSE | 21 - include/ckb-c-stdlib/Makefile | 21 - include/ckb-c-stdlib/README.md | 11 - include/ckb-c-stdlib/blake2b.h | 467 --- include/ckb-c-stdlib/blake3.h | 970 ------ include/ckb-c-stdlib/ckb_consts.h | 56 - include/ckb-c-stdlib/ckb_dlfcn.h | 477 --- include/ckb-c-stdlib/ckb_exec.h | 207 -- include/ckb-c-stdlib/ckb_keccak256.h | 358 --- include/ckb-c-stdlib/ckb_streaming.h | 46 - .../ckb-c-stdlib/ckb_swappable_signatures.h | 55 - include/ckb-c-stdlib/ckb_syscall_apis.h | 59 - include/ckb-c-stdlib/ckb_syscalls.h | 415 --- include/ckb-c-stdlib/ckb_type_id.h | 155 - include/ckb-c-stdlib/ckb_utils.h | 130 - include/ckb-c-stdlib/libc/ctype.h | 5 - include/ckb-c-stdlib/libc/entry.h | 31 - include/ckb-c-stdlib/libc/features.h | 40 - include/ckb-c-stdlib/libc/internal/atomic.h | 37 - include/ckb-c-stdlib/libc/internal/types.h | 24 - include/ckb-c-stdlib/libc/limits.h | 127 - include/ckb-c-stdlib/libc/locale.h | 29 - include/ckb-c-stdlib/libc/math.h | 63 - include/ckb-c-stdlib/libc/memory.h | 2 - include/ckb-c-stdlib/libc/setjmp.h | 46 - include/ckb-c-stdlib/libc/src/errno.h | 18 - include/ckb-c-stdlib/libc/src/impl.c | 2454 --------------- include/ckb-c-stdlib/libc/src/malloc_impl.h | 408 --- include/ckb-c-stdlib/libc/stdarg.h | 10 - include/ckb-c-stdlib/libc/stdbool.h | 9 - include/ckb-c-stdlib/libc/stddef.h | 8 - include/ckb-c-stdlib/libc/stdint.h | 25 - include/ckb-c-stdlib/libc/stdio.h | 59 - include/ckb-c-stdlib/libc/stdlib.h | 22 - include/ckb-c-stdlib/libc/string.h | 26 - include/ckb-c-stdlib/molecule/VERSION | 1 - .../ckb-c-stdlib/molecule/blockchain-api2.h | 1496 --------- include/ckb-c-stdlib/molecule/blockchain.h | 2075 ------------ .../ckb-c-stdlib/molecule/molecule2_reader.h | 700 ----- .../ckb-c-stdlib/molecule/molecule_builder.h | 289 -- .../ckb-c-stdlib/molecule/molecule_reader.h | 253 -- include/ckb-c-stdlib/simulator/README.md | 64 - .../simulator/blake2b_decl_only.h | 39 - include/ckb-c-stdlib/simulator/blake2b_imp.c | 2 - include/ckb-c-stdlib/simulator/cJSON.c | 2780 ----------------- include/ckb-c-stdlib/simulator/cJSON.h | 383 --- .../ckb-c-stdlib/simulator/ckb_syscall_sim.c | 81 - .../ckb-c-stdlib/simulator/ckb_syscall_sim.h | 144 - .../simulator/ckb_syscall_simulator.c | 743 ----- .../simulator/ckb_syscall_simulator.h | 59 - .../simulator/molecule_decl_only.h | 757 ----- .../simulator/rsa_sighash_all_usesim.c | 543 ---- 54 files changed, 17370 deletions(-) delete mode 100644 include/ckb-c-stdlib/.gitignore delete mode 100644 include/ckb-c-stdlib/.travis.yml delete mode 100644 include/ckb-c-stdlib/LICENSE delete mode 100644 include/ckb-c-stdlib/Makefile delete mode 100644 include/ckb-c-stdlib/README.md delete mode 100644 include/ckb-c-stdlib/blake2b.h delete mode 100644 include/ckb-c-stdlib/blake3.h delete mode 100644 include/ckb-c-stdlib/ckb_consts.h delete mode 100644 include/ckb-c-stdlib/ckb_dlfcn.h delete mode 100644 include/ckb-c-stdlib/ckb_exec.h delete mode 100644 include/ckb-c-stdlib/ckb_keccak256.h delete mode 100644 include/ckb-c-stdlib/ckb_streaming.h delete mode 100644 include/ckb-c-stdlib/ckb_swappable_signatures.h delete mode 100644 include/ckb-c-stdlib/ckb_syscall_apis.h delete mode 100644 include/ckb-c-stdlib/ckb_syscalls.h delete mode 100644 include/ckb-c-stdlib/ckb_type_id.h delete mode 100644 include/ckb-c-stdlib/ckb_utils.h delete mode 100644 include/ckb-c-stdlib/libc/ctype.h delete mode 100644 include/ckb-c-stdlib/libc/entry.h delete mode 100644 include/ckb-c-stdlib/libc/features.h delete mode 100644 include/ckb-c-stdlib/libc/internal/atomic.h delete mode 100644 include/ckb-c-stdlib/libc/internal/types.h delete mode 100644 include/ckb-c-stdlib/libc/limits.h delete mode 100644 include/ckb-c-stdlib/libc/locale.h delete mode 100644 include/ckb-c-stdlib/libc/math.h delete mode 100644 include/ckb-c-stdlib/libc/memory.h delete mode 100644 include/ckb-c-stdlib/libc/setjmp.h delete mode 100644 include/ckb-c-stdlib/libc/src/errno.h delete mode 100644 include/ckb-c-stdlib/libc/src/impl.c delete mode 100644 include/ckb-c-stdlib/libc/src/malloc_impl.h delete mode 100644 include/ckb-c-stdlib/libc/stdarg.h delete mode 100644 include/ckb-c-stdlib/libc/stdbool.h delete mode 100644 include/ckb-c-stdlib/libc/stddef.h delete mode 100644 include/ckb-c-stdlib/libc/stdint.h delete mode 100644 include/ckb-c-stdlib/libc/stdio.h delete mode 100644 include/ckb-c-stdlib/libc/stdlib.h delete mode 100644 include/ckb-c-stdlib/libc/string.h delete mode 100644 include/ckb-c-stdlib/molecule/VERSION delete mode 100644 include/ckb-c-stdlib/molecule/blockchain-api2.h delete mode 100644 include/ckb-c-stdlib/molecule/blockchain.h delete mode 100644 include/ckb-c-stdlib/molecule/molecule2_reader.h delete mode 100644 include/ckb-c-stdlib/molecule/molecule_builder.h delete mode 100644 include/ckb-c-stdlib/molecule/molecule_reader.h delete mode 100644 include/ckb-c-stdlib/simulator/README.md delete mode 100644 include/ckb-c-stdlib/simulator/blake2b_decl_only.h delete mode 100644 include/ckb-c-stdlib/simulator/blake2b_imp.c delete mode 100644 include/ckb-c-stdlib/simulator/cJSON.c delete mode 100644 include/ckb-c-stdlib/simulator/cJSON.h delete mode 100644 include/ckb-c-stdlib/simulator/ckb_syscall_sim.c delete mode 100644 include/ckb-c-stdlib/simulator/ckb_syscall_sim.h delete mode 100644 include/ckb-c-stdlib/simulator/ckb_syscall_simulator.c delete mode 100644 include/ckb-c-stdlib/simulator/ckb_syscall_simulator.h delete mode 100644 include/ckb-c-stdlib/simulator/molecule_decl_only.h delete mode 100644 include/ckb-c-stdlib/simulator/rsa_sighash_all_usesim.c diff --git a/include/ckb-c-stdlib/.gitignore b/include/ckb-c-stdlib/.gitignore deleted file mode 100644 index 7a6da4b..0000000 --- a/include/ckb-c-stdlib/.gitignore +++ /dev/null @@ -1,53 +0,0 @@ -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf -simulator/build.simulator diff --git a/include/ckb-c-stdlib/.travis.yml b/include/ckb-c-stdlib/.travis.yml deleted file mode 100644 index bcbc6df..0000000 --- a/include/ckb-c-stdlib/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: c -dist: bionic -sudo: true - -git: - depth: 2 - -addons: - apt: - packages: - - clang-format - -matrix: - include: - - name: Format - script: - - make fmt diff --git a/include/ckb-c-stdlib/LICENSE b/include/ckb-c-stdlib/LICENSE deleted file mode 100644 index 39696f7..0000000 --- a/include/ckb-c-stdlib/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Nervos Network - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/include/ckb-c-stdlib/Makefile b/include/ckb-c-stdlib/Makefile deleted file mode 100644 index 78ae9a3..0000000 --- a/include/ckb-c-stdlib/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -CC := riscv64-unknown-elf-gcc -AR := riscv64-unknown-elf-ar -LIB := libdummylibc.a -CFLAGS := -Wall -Werror -Wextra -Wno-unused-parameter -Wno-dangling-pointer -Wno-nonnull -Wno-nonnull-compare -fno-builtin-printf -fno-builtin-memcmp -O3 -g -fdata-sections -ffunction-sections - -default: fmt - -fmt: - clang-format -i -style=Google $(wildcard *.h */*.h *.c */*.c libc/*.h libc/src/*.c) - git diff --exit-code - -$(LIB): impl.o - $(AR) rcs $@ $^ - -impl.o: libc/src/impl.c - $(CC) $(CFLAGS) -c $< -o $@ -I libc -D__SHARED_LIBRARY__ - -clean: - rm -rf $(LIB) impl.o - -.PHONY: clean default fmt diff --git a/include/ckb-c-stdlib/README.md b/include/ckb-c-stdlib/README.md deleted file mode 100644 index 9cd0db8..0000000 --- a/include/ckb-c-stdlib/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# ckb-c-stdlib - -[![Build Status](https://travis-ci.com/nervosnetwork/ckb-c-stdlib.svg?branch=master)](https://travis-ci.com/nervosnetwork/ckb-c-stdlib) - -In the development of CKB scripts, we discovered many use-cases and patterns that could be really useful in writing CKB scripts. This repo serves as a commonplace for all those useful scripts. This could include but aren't limit to: - -* CKB's data structure definitions -* Utilities for interacting with CKB via syscalls -* A shimmed libc, notice the libc here is tailored for CKB's special needs, implementing everything in POSIX's standard is never a goal. If you do have special requirements, using a more complete libc is always a better choice - -Notice while this repo would focus on C code, it is not limited to scripts written in C. A Rust script might use FFI to leverage the C code here, a higher level language can also use certain glues to use the code here. diff --git a/include/ckb-c-stdlib/blake2b.h b/include/ckb-c-stdlib/blake2b.h deleted file mode 100644 index 28c51fa..0000000 --- a/include/ckb-c-stdlib/blake2b.h +++ /dev/null @@ -1,467 +0,0 @@ -/* - BLAKE2 reference source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE2 hash function can be found at - https://blake2.net. -*/ - -// blake2.h -#ifndef BLAKE2_H -#define BLAKE2_H - -#include -#include - -#if defined(_MSC_VER) -#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) -#else -#define BLAKE2_PACKED(x) x __attribute__((packed)) -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -enum blake2b_constant { - BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, - BLAKE2B_PERSONALBYTES = 16 -}; - -typedef struct blake2b_state__ { - uint64_t h[8]; - uint64_t t[2]; - uint64_t f[2]; - uint8_t buf[BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; -} blake2b_state; - -BLAKE2_PACKED(struct blake2b_param__ { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint32_t xof_length; /* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ -}); - -typedef struct blake2b_param__ blake2b_param; - -/* Padded structs result in a compile-time error */ -enum { BLAKE2_DUMMY_2 = 1 / (sizeof(blake2b_param) == BLAKE2B_OUTBYTES) }; - -/* Streaming API */ - -/* For future code, you should always use ckb_blake2b_init for convenience */ -int ckb_blake2b_init(blake2b_state *S, size_t outlen); -int blake2b_init(blake2b_state *S, size_t outlen); -int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, - size_t keylen); -int blake2b_init_param(blake2b_state *S, const blake2b_param *P); -int blake2b_update(blake2b_state *S, const void *in, size_t inlen); -int blake2b_final(blake2b_state *S, void *out, size_t outlen); - -/* Simple API */ -int blake2b(void *out, size_t outlen, const void *in, size_t inlen, - const void *key, size_t keylen); - -/* This is simply an alias for blake2b */ -int blake2(void *out, size_t outlen, const void *in, size_t inlen, - const void *key, size_t keylen); - -#if defined(__cplusplus) -} -#endif - -#endif - -// blake2-impl.h -#ifndef BLAKE2_IMPL_H -#define BLAKE2_IMPL_H - -#include -#include - -#if !defined(__cplusplus) && \ - (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) -#if defined(_MSC_VER) -#define BLAKE2_INLINE __inline -#elif defined(__GNUC__) -#define BLAKE2_INLINE __inline__ -#else -#define BLAKE2_INLINE -#endif -#else -#define BLAKE2_INLINE inline -#endif - -static BLAKE2_INLINE uint64_t load64(const void *src) { -#if defined(NATIVE_LITTLE_ENDIAN) - uint64_t w; - memcpy(&w, src, sizeof w); - return w; -#else - const uint8_t *p = (const uint8_t *)src; - return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | - ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) | - ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) | - ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56); -#endif -} - -static BLAKE2_INLINE void store32(void *dst, uint32_t w) { -#if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); -#else - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); -#endif -} - -static BLAKE2_INLINE void store64(void *dst, uint64_t w) { -#if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); -#else - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); - p[6] = (uint8_t)(w >> 48); - p[7] = (uint8_t)(w >> 56); -#endif -} - -static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { - return (w >> c) | (w << (64 - c)); -} - -/* prevents compiler optimizing out memset() */ -static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) { - static void *(*const volatile memset_v)(void *, int, size_t) = &memset; - memset_v(v, 0, n); -} - -const char *DEFAULT_PERSONAL = "ckb-default-hash"; -int ckb_blake2b_init(blake2b_state *S, size_t outlen) { - blake2b_param P[1]; - - if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; - - P->digest_length = (uint8_t)outlen; - P->key_length = 0; - P->fanout = 1; - P->depth = 1; - store32(&P->leaf_length, 0); - store32(&P->node_offset, 0); - store32(&P->xof_length, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->reserved, 0, sizeof(P->reserved)); - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - for (int i = 0; i < BLAKE2B_PERSONALBYTES; ++i) { - (P->personal)[i] = DEFAULT_PERSONAL[i]; - } - return blake2b_init_param(S, P); -} - -#endif - -// blake2b-ref.c -#ifndef BLAKE2_REF_C -#define BLAKE2_REF_C - -#include -#include -#include - -static const uint64_t blake2b_IV[8] = { - 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, - 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, - 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}; - -static const uint8_t blake2b_sigma[12][16] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}, - {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4}, - {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}, - {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13}, - {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}, - {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11}, - {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10}, - {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5}, - {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}}; - -static void blake2b_set_lastnode(blake2b_state *S) { S->f[1] = (uint64_t)-1; } - -/* Some helper functions, not necessarily useful */ -static int blake2b_is_lastblock(const blake2b_state *S) { return S->f[0] != 0; } - -static void blake2b_set_lastblock(blake2b_state *S) { - if (S->last_node) blake2b_set_lastnode(S); - - S->f[0] = (uint64_t)-1; -} - -static void blake2b_increment_counter(blake2b_state *S, const uint64_t inc) { - S->t[0] += inc; - S->t[1] += (S->t[0] < inc); -} - -static void blake2b_init0(blake2b_state *S) { - size_t i; - memset(S, 0, sizeof(blake2b_state)); - - for (i = 0; i < 8; ++i) S->h[i] = blake2b_IV[i]; -} - -/* init xors IV with input parameter block */ -int blake2b_init_param(blake2b_state *S, const blake2b_param *P) { - const uint8_t *p = (const uint8_t *)(P); - size_t i; - - blake2b_init0(S); - - /* IV XOR ParamBlock */ - for (i = 0; i < 8; ++i) S->h[i] ^= load64(p + sizeof(S->h[i]) * i); - - S->outlen = P->digest_length; - return 0; -} - -int blake2b_init(blake2b_state *S, size_t outlen) { - blake2b_param P[1]; - - if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; - - P->digest_length = (uint8_t)outlen; - P->key_length = 0; - P->fanout = 1; - P->depth = 1; - store32(&P->leaf_length, 0); - store32(&P->node_offset, 0); - store32(&P->xof_length, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->reserved, 0, sizeof(P->reserved)); - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - for (int i = 0; i < BLAKE2B_PERSONALBYTES; ++i) { - (P->personal)[i] = DEFAULT_PERSONAL[i]; - } - return blake2b_init_param(S, P); -} - -int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, - size_t keylen) { - blake2b_param P[1]; - - if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; - - if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) return -1; - - P->digest_length = (uint8_t)outlen; - P->key_length = (uint8_t)keylen; - P->fanout = 1; - P->depth = 1; - store32(&P->leaf_length, 0); - store32(&P->node_offset, 0); - store32(&P->xof_length, 0); - P->node_depth = 0; - P->inner_length = 0; - memset(P->reserved, 0, sizeof(P->reserved)); - memset(P->salt, 0, sizeof(P->salt)); - memset(P->personal, 0, sizeof(P->personal)); - - if (blake2b_init_param(S, P) < 0) return -1; - - { - uint8_t block[BLAKE2B_BLOCKBYTES]; - memset(block, 0, BLAKE2B_BLOCKBYTES); - memcpy(block, key, keylen); - blake2b_update(S, block, BLAKE2B_BLOCKBYTES); - secure_zero_memory(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */ - } - return 0; -} - -#define G(r, i, a, b, c, d) \ - do { \ - a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ - d = rotr64(d ^ a, 32); \ - c = c + d; \ - b = rotr64(b ^ c, 24); \ - a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ - d = rotr64(d ^ a, 16); \ - c = c + d; \ - b = rotr64(b ^ c, 63); \ - } while (0) - -#define ROUND(r) \ - do { \ - G(r, 0, v[0], v[4], v[8], v[12]); \ - G(r, 1, v[1], v[5], v[9], v[13]); \ - G(r, 2, v[2], v[6], v[10], v[14]); \ - G(r, 3, v[3], v[7], v[11], v[15]); \ - G(r, 4, v[0], v[5], v[10], v[15]); \ - G(r, 5, v[1], v[6], v[11], v[12]); \ - G(r, 6, v[2], v[7], v[8], v[13]); \ - G(r, 7, v[3], v[4], v[9], v[14]); \ - } while (0) - -static void blake2b_compress(blake2b_state *S, - const uint8_t block[BLAKE2B_BLOCKBYTES]) { - uint64_t m[16]; - uint64_t v[16]; - size_t i; - - for (i = 0; i < 16; ++i) { - m[i] = load64(block + i * sizeof(m[i])); - } - - for (i = 0; i < 8; ++i) { - v[i] = S->h[i]; - } - - v[8] = blake2b_IV[0]; - v[9] = blake2b_IV[1]; - v[10] = blake2b_IV[2]; - v[11] = blake2b_IV[3]; - v[12] = blake2b_IV[4] ^ S->t[0]; - v[13] = blake2b_IV[5] ^ S->t[1]; - v[14] = blake2b_IV[6] ^ S->f[0]; - v[15] = blake2b_IV[7] ^ S->f[1]; - - ROUND(0); - ROUND(1); - ROUND(2); - ROUND(3); - ROUND(4); - ROUND(5); - ROUND(6); - ROUND(7); - ROUND(8); - ROUND(9); - ROUND(10); - ROUND(11); - - for (i = 0; i < 8; ++i) { - S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; - } -} - -#undef G -#undef ROUND - -int blake2b_update(blake2b_state *S, const void *pin, size_t inlen) { - const unsigned char *in = (const unsigned char *)pin; - if (inlen > 0) { - size_t left = S->buflen; - size_t fill = BLAKE2B_BLOCKBYTES - left; - if (inlen > fill) { - S->buflen = 0; - memcpy(S->buf + left, in, fill); /* Fill buffer */ - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress(S, S->buf); /* Compress */ - in += fill; - inlen -= fill; - while (inlen > BLAKE2B_BLOCKBYTES) { - blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); - blake2b_compress(S, in); - in += BLAKE2B_BLOCKBYTES; - inlen -= BLAKE2B_BLOCKBYTES; - } - } - memcpy(S->buf + S->buflen, in, inlen); - S->buflen += inlen; - } - return 0; -} - -int blake2b_final(blake2b_state *S, void *out, size_t outlen) { - uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; - size_t i; - - if (out == NULL || outlen < S->outlen) return -1; - - if (blake2b_is_lastblock(S)) return -1; - - blake2b_increment_counter(S, S->buflen); - blake2b_set_lastblock(S); - memset(S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */ - blake2b_compress(S, S->buf); - - for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */ - store64(buffer + sizeof(S->h[i]) * i, S->h[i]); - - memcpy(out, buffer, S->outlen); - secure_zero_memory(buffer, sizeof(buffer)); - return 0; -} - -/* inlen, at least, should be uint64_t. Others can be size_t. */ -int blake2b(void *out, size_t outlen, const void *in, size_t inlen, - const void *key, size_t keylen) { - blake2b_state S[1]; - - /* Verify parameters */ - if (NULL == in && inlen > 0) return -1; - - if (NULL == out) return -1; - - if (NULL == key && keylen > 0) return -1; - - if (!outlen || outlen > BLAKE2B_OUTBYTES) return -1; - - if (keylen > BLAKE2B_KEYBYTES) return -1; - - if (keylen > 0) { - if (blake2b_init_key(S, outlen, key, keylen) < 0) return -1; - } else { - if (blake2b_init(S, outlen) < 0) return -1; - } - - blake2b_update(S, (const uint8_t *)in, inlen); - blake2b_final(S, out, outlen); - return 0; -} - -int blake2(void *out, size_t outlen, const void *in, size_t inlen, - const void *key, size_t keylen) { - return blake2b(out, outlen, in, inlen, key, keylen); -} - -#if defined(SUPERCOP) -int crypto_hash(unsigned char *out, unsigned char *in, - unsigned long long inlen) { - return blake2b(out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0); -} -#endif - -#endif diff --git a/include/ckb-c-stdlib/blake3.h b/include/ckb-c-stdlib/blake3.h deleted file mode 100644 index c3ad141..0000000 --- a/include/ckb-c-stdlib/blake3.h +++ /dev/null @@ -1,970 +0,0 @@ -/* - BLAKE3 source code package - reference C implementations - - Copyright 2012, Samuel Neves . You may use this under the - terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at - your option. The terms of these licenses can be found at: - - - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - - OpenSSL license : https://www.openssl.org/source/license.html - - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 - - More information about the BLAKE3 hash function can be found at - https://blake3.net. -*/ - -// blake3.h -#ifndef BLAKE3_H -#define BLAKE3_H - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLAKE3_KEY_LEN 32 -#define BLAKE3_OUT_LEN 32 -#define BLAKE3_BLOCK_LEN 64 -#define BLAKE3_CHUNK_LEN 1024 -#define BLAKE3_MAX_DEPTH 54 -#define BLAKE3_MAX_SIMD_DEGREE 16 - -// This struct is a private implementation detail. It has to be here because -// it's part of blake3_hasher below. -typedef struct { - uint32_t cv[8]; - uint64_t chunk_counter; - uint8_t buf[BLAKE3_BLOCK_LEN]; - uint8_t buf_len; - uint8_t blocks_compressed; - uint8_t flags; -} blake3_chunk_state; - -typedef struct { - uint32_t key[8]; - blake3_chunk_state chunk; - uint8_t cv_stack_len; - // The stack size is MAX_DEPTH + 1 because we do lazy merging. For example, - // with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk - // requires a 4th entry, rather than merging everything down to 1, because we - // don't know whether more input is coming. This is different from how the - // reference implementation does things. - uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN]; -} blake3_hasher; - -/* Streaming API */ -void blake3_hasher_init(blake3_hasher *self); -void blake3_hasher_init_keyed(blake3_hasher *self, - const uint8_t key[BLAKE3_KEY_LEN]); -void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context); -void blake3_hasher_update(blake3_hasher *self, const void *input, - size_t input_len); -void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, - size_t out_len); -void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, - uint8_t *out, size_t out_len); - -#ifdef __cplusplus -} -#endif - -// internal flags -enum blake3_flags { - CHUNK_START = 1 << 0, - CHUNK_END = 1 << 1, - PARENT = 1 << 2, - ROOT = 1 << 3, - KEYED_HASH = 1 << 4, - DERIVE_KEY_CONTEXT = 1 << 5, - DERIVE_KEY_MATERIAL = 1 << 6, -}; - -#define INLINE static inline __attribute__((always_inline)) -#define MAX_SIMD_DEGREE 1 - -// There are some places where we want a static size that's equal to the -// MAX_SIMD_DEGREE, but also at least 2. -#define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2) - -static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, - 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, - 0x1F83D9ABUL, 0x5BE0CD19UL}; - -static const uint8_t MSG_SCHEDULE[7][16] = { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, - {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8}, - {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1}, - {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6}, - {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4}, - {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7}, - {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13}, -}; - -/* Find index of the highest set bit */ -/* x is assumed to be nonzero. */ -static unsigned int highest_one(uint64_t x) { -#if defined(__GNUC__) || defined(__clang__) - return 63 ^ __builtin_clzll(x); -#else - unsigned int c = 0; - if (x & 0xffffffff00000000ULL) { - x >>= 32; - c += 32; - } - if (x & 0x00000000ffff0000ULL) { - x >>= 16; - c += 16; - } - if (x & 0x000000000000ff00ULL) { - x >>= 8; - c += 8; - } - if (x & 0x00000000000000f0ULL) { - x >>= 4; - c += 4; - } - if (x & 0x000000000000000cULL) { - x >>= 2; - c += 2; - } - if (x & 0x0000000000000002ULL) { - c += 1; - } - return c; -#endif -} - -// Count the number of 1 bits. -INLINE unsigned int popcnt(uint64_t x) { -#if defined(__GNUC__) || defined(__clang__) - return __builtin_popcountll(x); -#else - unsigned int count = 0; - while (x != 0) { - count += 1; - x &= x - 1; - } - return count; -#endif -} - -// Largest power of two less than or equal to x. As a special case, returns 1 -// when x is 0. -INLINE uint64_t round_down_to_power_of_2(uint64_t x) { - return 1ULL << highest_one(x | 1); -} - -INLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; } - -INLINE uint32_t counter_high(uint64_t counter) { - return (uint32_t)(counter >> 32); -} - -INLINE uint32_t load32(const void *src) { - const uint8_t *p = (const uint8_t *)src; - return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | - ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); -} - -INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN], - uint32_t key_words[8]) { - key_words[0] = load32(&key[0 * 4]); - key_words[1] = load32(&key[1 * 4]); - key_words[2] = load32(&key[2 * 4]); - key_words[3] = load32(&key[3 * 4]); - key_words[4] = load32(&key[4 * 4]); - key_words[5] = load32(&key[5 * 4]); - key_words[6] = load32(&key[6 * 4]); - key_words[7] = load32(&key[7 * 4]); -} - -INLINE void store32(void *dst, uint32_t w) { - uint8_t *p = (uint8_t *)dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); -} - -INLINE uint32_t rotr32(uint32_t w, uint32_t c) { - return (w >> c) | (w << (32 - c)); -} - -INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, - uint32_t x, uint32_t y) { - state[a] = state[a] + state[b] + x; - state[d] = rotr32(state[d] ^ state[a], 16); - state[c] = state[c] + state[d]; - state[b] = rotr32(state[b] ^ state[c], 12); - state[a] = state[a] + state[b] + y; - state[d] = rotr32(state[d] ^ state[a], 8); - state[c] = state[c] + state[d]; - state[b] = rotr32(state[b] ^ state[c], 7); -} - -INLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) { - // Select the message schedule based on the round. - const uint8_t *schedule = MSG_SCHEDULE[round]; - - // Mix the columns. - g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]); - g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]); - g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]); - g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]); - - // Mix the rows. - g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]); - g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]); - g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]); - g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]); -} - -INLINE void compress_pre(uint32_t state[16], const uint32_t cv[8], - const uint8_t block[BLAKE3_BLOCK_LEN], - uint8_t block_len, uint64_t counter, uint8_t flags) { - uint32_t block_words[16]; - block_words[0] = load32(block + 4 * 0); - block_words[1] = load32(block + 4 * 1); - block_words[2] = load32(block + 4 * 2); - block_words[3] = load32(block + 4 * 3); - block_words[4] = load32(block + 4 * 4); - block_words[5] = load32(block + 4 * 5); - block_words[6] = load32(block + 4 * 6); - block_words[7] = load32(block + 4 * 7); - block_words[8] = load32(block + 4 * 8); - block_words[9] = load32(block + 4 * 9); - block_words[10] = load32(block + 4 * 10); - block_words[11] = load32(block + 4 * 11); - block_words[12] = load32(block + 4 * 12); - block_words[13] = load32(block + 4 * 13); - block_words[14] = load32(block + 4 * 14); - block_words[15] = load32(block + 4 * 15); - - state[0] = cv[0]; - state[1] = cv[1]; - state[2] = cv[2]; - state[3] = cv[3]; - state[4] = cv[4]; - state[5] = cv[5]; - state[6] = cv[6]; - state[7] = cv[7]; - state[8] = IV[0]; - state[9] = IV[1]; - state[10] = IV[2]; - state[11] = IV[3]; - state[12] = counter_low(counter); - state[13] = counter_high(counter); - state[14] = (uint32_t)block_len; - state[15] = (uint32_t)flags; - - round_fn(state, &block_words[0], 0); - round_fn(state, &block_words[0], 1); - round_fn(state, &block_words[0], 2); - round_fn(state, &block_words[0], 3); - round_fn(state, &block_words[0], 4); - round_fn(state, &block_words[0], 5); - round_fn(state, &block_words[0], 6); -} - -void blake3_compress_in_place_portable(uint32_t cv[8], - const uint8_t block[BLAKE3_BLOCK_LEN], - uint8_t block_len, uint64_t counter, - uint8_t flags) { - uint32_t state[16]; - compress_pre(state, cv, block, block_len, counter, flags); - cv[0] = state[0] ^ state[8]; - cv[1] = state[1] ^ state[9]; - cv[2] = state[2] ^ state[10]; - cv[3] = state[3] ^ state[11]; - cv[4] = state[4] ^ state[12]; - cv[5] = state[5] ^ state[13]; - cv[6] = state[6] ^ state[14]; - cv[7] = state[7] ^ state[15]; -} - -void blake3_compress_xof_portable(const uint32_t cv[8], - const uint8_t block[BLAKE3_BLOCK_LEN], - uint8_t block_len, uint64_t counter, - uint8_t flags, uint8_t out[64]) { - uint32_t state[16]; - compress_pre(state, cv, block, block_len, counter, flags); - - store32(&out[0 * 4], state[0] ^ state[8]); - store32(&out[1 * 4], state[1] ^ state[9]); - store32(&out[2 * 4], state[2] ^ state[10]); - store32(&out[3 * 4], state[3] ^ state[11]); - store32(&out[4 * 4], state[4] ^ state[12]); - store32(&out[5 * 4], state[5] ^ state[13]); - store32(&out[6 * 4], state[6] ^ state[14]); - store32(&out[7 * 4], state[7] ^ state[15]); - store32(&out[8 * 4], state[8] ^ cv[0]); - store32(&out[9 * 4], state[9] ^ cv[1]); - store32(&out[10 * 4], state[10] ^ cv[2]); - store32(&out[11 * 4], state[11] ^ cv[3]); - store32(&out[12 * 4], state[12] ^ cv[4]); - store32(&out[13 * 4], state[13] ^ cv[5]); - store32(&out[14 * 4], state[14] ^ cv[6]); - store32(&out[15 * 4], state[15] ^ cv[7]); -} - -INLINE void hash_one_portable(const uint8_t *input, size_t blocks, - const uint32_t key[8], uint64_t counter, - uint8_t flags, uint8_t flags_start, - uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { - uint32_t cv[8]; - memcpy(cv, key, BLAKE3_KEY_LEN); - uint8_t block_flags = flags | flags_start; - while (blocks > 0) { - if (blocks == 1) { - block_flags |= flags_end; - } - blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter, - block_flags); - input = &input[BLAKE3_BLOCK_LEN]; - blocks -= 1; - block_flags = flags; - } - memcpy(out, cv, 32); -} - -// The dynamically detected SIMD degree of the current platform. -size_t blake3_simd_degree(void) { return 1; } - -void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, - size_t blocks, const uint32_t key[8], - uint64_t counter, bool increment_counter, - uint8_t flags, uint8_t flags_start, - uint8_t flags_end, uint8_t *out) { - while (num_inputs > 0) { - hash_one_portable(inputs[0], blocks, key, counter, flags, flags_start, - flags_end, out); - if (increment_counter) { - counter += 1; - } - inputs += 1; - num_inputs -= 1; - out = &out[BLAKE3_OUT_LEN]; - } -} - -void blake3_compress_in_place(uint32_t cv[8], - const uint8_t block[BLAKE3_BLOCK_LEN], - uint8_t block_len, uint64_t counter, - uint8_t flags) { - blake3_compress_in_place_portable(cv, block, block_len, counter, flags); -} - -void blake3_compress_xof(const uint32_t cv[8], - const uint8_t block[BLAKE3_BLOCK_LEN], - uint8_t block_len, uint64_t counter, uint8_t flags, - uint8_t out[64]) { - blake3_compress_xof_portable(cv, block, block_len, counter, flags, out); -} - -void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, - size_t blocks, const uint32_t key[8], uint64_t counter, - bool increment_counter, uint8_t flags, - uint8_t flags_start, uint8_t flags_end, uint8_t *out) { - blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter, - increment_counter, flags, flags_start, flags_end, - out); -} - -INLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8], - uint8_t flags) { - memcpy(self->cv, key, BLAKE3_KEY_LEN); - self->chunk_counter = 0; - memset(self->buf, 0, BLAKE3_BLOCK_LEN); - self->buf_len = 0; - self->blocks_compressed = 0; - self->flags = flags; -} - -INLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8], - uint64_t chunk_counter) { - memcpy(self->cv, key, BLAKE3_KEY_LEN); - self->chunk_counter = chunk_counter; - self->blocks_compressed = 0; - memset(self->buf, 0, BLAKE3_BLOCK_LEN); - self->buf_len = 0; -} - -INLINE size_t chunk_state_len(const blake3_chunk_state *self) { - return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) + - ((size_t)self->buf_len); -} - -INLINE size_t chunk_state_fill_buf(blake3_chunk_state *self, - const uint8_t *input, size_t input_len) { - size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len); - if (take > input_len) { - take = input_len; - } - uint8_t *dest = self->buf + ((size_t)self->buf_len); - memcpy(dest, input, take); - self->buf_len += (uint8_t)take; - return take; -} - -INLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) { - if (self->blocks_compressed == 0) { - return CHUNK_START; - } else { - return 0; - } -} - -typedef struct { - uint32_t input_cv[8]; - uint64_t counter; - uint8_t block[BLAKE3_BLOCK_LEN]; - uint8_t block_len; - uint8_t flags; -} output_t; - -INLINE output_t make_output(const uint32_t input_cv[8], - const uint8_t block[BLAKE3_BLOCK_LEN], - uint8_t block_len, uint64_t counter, - uint8_t flags) { - output_t ret; - memcpy(ret.input_cv, input_cv, 32); - memcpy(ret.block, block, BLAKE3_BLOCK_LEN); - ret.block_len = block_len; - ret.counter = counter; - ret.flags = flags; - return ret; -} - -// Chaining values within a given chunk (specifically the compress_in_place -// interface) are represented as words. This avoids unnecessary bytes<->words -// conversion overhead in the portable implementation. However, the hash_many -// interface handles both user input and parent node blocks, so it accepts -// bytes. For that reason, chaining values in the CV stack are represented as -// bytes. -INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) { - uint32_t cv_words[8]; - memcpy(cv_words, self->input_cv, 32); - blake3_compress_in_place(cv_words, self->block, self->block_len, - self->counter, self->flags); - memcpy(cv, cv_words, 32); -} - -INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out, - size_t out_len) { - uint64_t output_block_counter = seek / 64; - size_t offset_within_block = seek % 64; - uint8_t wide_buf[64]; - while (out_len > 0) { - blake3_compress_xof(self->input_cv, self->block, self->block_len, - output_block_counter, self->flags | ROOT, wide_buf); - size_t available_bytes = 64 - offset_within_block; - size_t memcpy_len; - if (out_len > available_bytes) { - memcpy_len = available_bytes; - } else { - memcpy_len = out_len; - } - memcpy(out, wide_buf + offset_within_block, memcpy_len); - out += memcpy_len; - out_len -= memcpy_len; - output_block_counter += 1; - offset_within_block = 0; - } -} - -INLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input, - size_t input_len) { - if (self->buf_len > 0) { - size_t take = chunk_state_fill_buf(self, input, input_len); - input += take; - input_len -= take; - if (input_len > 0) { - blake3_compress_in_place( - self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter, - self->flags | chunk_state_maybe_start_flag(self)); - self->blocks_compressed += 1; - self->buf_len = 0; - memset(self->buf, 0, BLAKE3_BLOCK_LEN); - } - } - - while (input_len > BLAKE3_BLOCK_LEN) { - blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN, - self->chunk_counter, - self->flags | chunk_state_maybe_start_flag(self)); - self->blocks_compressed += 1; - input += BLAKE3_BLOCK_LEN; - input_len -= BLAKE3_BLOCK_LEN; - } - - size_t take = chunk_state_fill_buf(self, input, input_len); - input += take; - input_len -= take; -} - -INLINE output_t chunk_state_output(const blake3_chunk_state *self) { - uint8_t block_flags = - self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END; - return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter, - block_flags); -} - -INLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN], - const uint32_t key[8], uint8_t flags) { - return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT); -} - -// Given some input larger than one chunk, return the number of bytes that -// should go in the left subtree. This is the largest power-of-2 number of -// chunks that leaves at least 1 byte for the right subtree. -INLINE size_t left_len(size_t content_len) { - // Subtract 1 to reserve at least one byte for the right side. content_len - // should always be greater than BLAKE3_CHUNK_LEN. - size_t full_chunks = (content_len - 1) / BLAKE3_CHUNK_LEN; - return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN; -} - -// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time -// on a single thread. Write out the chunk chaining values and return the -// number of chunks hashed. These chunks are never the root and never empty; -// those cases use a different codepath. -INLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len, - const uint32_t key[8], - uint64_t chunk_counter, uint8_t flags, - uint8_t *out) { -#if defined(BLAKE3_TESTING) - assert(0 < input_len); - assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN); -#endif - - const uint8_t *chunks_array[MAX_SIMD_DEGREE]; - size_t input_position = 0; - size_t chunks_array_len = 0; - while (input_len - input_position >= BLAKE3_CHUNK_LEN) { - chunks_array[chunks_array_len] = &input[input_position]; - input_position += BLAKE3_CHUNK_LEN; - chunks_array_len += 1; - } - - blake3_hash_many(chunks_array, chunks_array_len, - BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter, - true, flags, CHUNK_START, CHUNK_END, out); - - // Hash the remaining partial chunk, if there is one. Note that the empty - // chunk (meaning the empty message) is a different codepath. - if (input_len > input_position) { - uint64_t counter = chunk_counter + (uint64_t)chunks_array_len; - blake3_chunk_state chunk_state; - chunk_state_init(&chunk_state, key, flags); - chunk_state.chunk_counter = counter; - chunk_state_update(&chunk_state, &input[input_position], - input_len - input_position); - output_t output = chunk_state_output(&chunk_state); - output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]); - return chunks_array_len + 1; - } else { - return chunks_array_len; - } -} - -// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time -// on a single thread. Write out the parent chaining values and return the -// number of parents hashed. (If there's an odd input chaining value left over, -// return it as an additional output.) These parents are never the root and -// never empty; those cases use a different codepath. -INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values, - size_t num_chaining_values, - const uint32_t key[8], uint8_t flags, - uint8_t *out) { -#if defined(BLAKE3_TESTING) - assert(2 <= num_chaining_values); - assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2); -#endif - - const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2]; - size_t parents_array_len = 0; - while (num_chaining_values - (2 * parents_array_len) >= 2) { - parents_array[parents_array_len] = - &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN]; - parents_array_len += 1; - } - - blake3_hash_many(parents_array, parents_array_len, 1, key, - 0, // Parents always use counter 0. - false, flags | PARENT, - 0, // Parents have no start flags. - 0, // Parents have no end flags. - out); - - // If there's an odd child left over, it becomes an output. - if (num_chaining_values > 2 * parents_array_len) { - memcpy(&out[parents_array_len * BLAKE3_OUT_LEN], - &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN], - BLAKE3_OUT_LEN); - return parents_array_len + 1; - } else { - return parents_array_len; - } -} - -// The wide helper function returns (writes out) an array of chaining values -// and returns the length of that array. The number of chaining values returned -// is the dyanmically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer, -// if the input is shorter than that many chunks. The reason for maintaining a -// wide array of chaining values going back up the tree, is to allow the -// implementation to hash as many parents in parallel as possible. -// -// As a special case when the SIMD degree is 1, this function will still return -// at least 2 outputs. This guarantees that this function doesn't perform the -// root compression. (If it did, it would use the wrong flags, and also we -// wouldn't be able to implement exendable ouput.) Note that this function is -// not used when the whole input is only 1 chunk long; that's a different -// codepath. -// -// Why not just have the caller split the input on the first update(), instead -// of implementing this special rule? Because we don't want to limit SIMD or -// multi-threading parallelism for that update(). -static size_t blake3_compress_subtree_wide(const uint8_t *input, - size_t input_len, - const uint32_t key[8], - uint64_t chunk_counter, - uint8_t flags, uint8_t *out) { - // Note that the single chunk case does *not* bump the SIMD degree up to 2 - // when it is 1. If this implementation adds multi-threading in the future, - // this gives us the option of multi-threading even the 2-chunk case, which - // can help performance on smaller platforms. - if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) { - return compress_chunks_parallel(input, input_len, key, chunk_counter, flags, - out); - } - - // With more than simd_degree chunks, we need to recurse. Start by dividing - // the input into left and right subtrees. (Note that this is only optimal - // as long as the SIMD degree is a power of 2. If we ever get a SIMD degree - // of 3 or something, we'll need a more complicated strategy.) - size_t left_input_len = left_len(input_len); - size_t right_input_len = input_len - left_input_len; - const uint8_t *right_input = &input[left_input_len]; - uint64_t right_chunk_counter = - chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN); - - // Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to - // account for the special case of returning 2 outputs when the SIMD degree - // is 1. - uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; - size_t degree = blake3_simd_degree(); - if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) { - // The special case: We always use a degree of at least two, to make - // sure there are two outputs. Except, as noted above, at the chunk - // level, where we allow degree=1. (Note that the 1-chunk-input case is - // a different codepath.) - degree = 2; - } - uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN]; - - // Recurse! If this implementation adds multi-threading support in the - // future, this is where it will go. - size_t left_n = blake3_compress_subtree_wide(input, left_input_len, key, - chunk_counter, flags, cv_array); - size_t right_n = blake3_compress_subtree_wide( - right_input, right_input_len, key, right_chunk_counter, flags, right_cvs); - - // The special case again. If simd_degree=1, then we'll have left_n=1 and - // right_n=1. Rather than compressing them into a single output, return - // them directly, to make sure we always have at least two outputs. - if (left_n == 1) { - memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); - return 2; - } - - // Otherwise, do one layer of parent node compression. - size_t num_chaining_values = left_n + right_n; - return compress_parents_parallel(cv_array, num_chaining_values, key, flags, - out); -} - -// Hash a subtree with compress_subtree_wide(), and then condense the resulting -// list of chaining values down to a single parent node. Don't compress that -// last parent node, however. Instead, return its message bytes (the -// concatenated chaining values of its children). This is necessary when the -// first call to update() supplies a complete subtree, because the topmost -// parent node of that subtree could end up being the root. It's also necessary -// for extended output in the general case. -// -// As with compress_subtree_wide(), this function is not used on inputs of 1 -// chunk or less. That's a different codepath. -INLINE void compress_subtree_to_parent_node( - const uint8_t *input, size_t input_len, const uint32_t key[8], - uint64_t chunk_counter, uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN]) { -#if defined(BLAKE3_TESTING) - assert(input_len > BLAKE3_CHUNK_LEN); -#endif - - uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; - size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key, - chunk_counter, flags, cv_array); - - // If MAX_SIMD_DEGREE is greater than 2 and there's enough input, - // compress_subtree_wide() returns more than 2 chaining values. Condense - // them into 2 by forming parent nodes repeatedly. - uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2]; - while (num_cvs > 2) { - num_cvs = - compress_parents_parallel(cv_array, num_cvs, key, flags, out_array); - memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN); - } - memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); -} - -// As described in hasher_push_cv() below, we do "lazy merging", delaying -// merges until right before the next CV is about to be added. This is -// different from the reference implementation. Another difference is that we -// aren't always merging 1 chunk at a time. Instead, each CV might represent -// any power-of-two number of chunks, as long as the smaller-above-larger stack -// order is maintained. Instead of the "count the trailing 0-bits" algorithm -// described in the spec, we use a "count the total number of 1-bits" variant -// that doesn't require us to retain the subtree size of the CV on top of the -// stack. The principle is the same: each CV that should remain in the stack is -// represented by a 1-bit in the total number of chunks (or bytes) so far. -INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) { - size_t post_merge_stack_len = (size_t)popcnt(total_len); - while (self->cv_stack_len > post_merge_stack_len) { - uint8_t *parent_node = - &self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN]; - output_t output = parent_output(parent_node, self->key, self->chunk.flags); - output_chaining_value(&output, parent_node); - self->cv_stack_len -= 1; - } -} - -// In reference_impl.rs, we merge the new CV with existing CVs from the stack -// before pushing it. We can do that because we know more input is coming, so -// we know none of the merges are root. -// -// This setting is different. We want to feed as much input as possible to -// compress_subtree_wide(), without setting aside anything for the chunk_state. -// If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once -// as a single subtree, if at all possible. -// -// This leads to two problems: -// 1) This 64 KiB input might be the only call that ever gets made to update. -// In this case, the root node of the 64 KiB subtree would be the root node -// of the whole tree, and it would need to be ROOT finalized. We can't -// compress it until we know. -// 2) This 64 KiB input might complete a larger tree, whose root node is -// similarly going to be the the root of the whole tree. For example, maybe -// we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the -// node at the root of the 256 KiB subtree until we know how to finalize it. -// -// The second problem is solved with "lazy merging". That is, when we're about -// to add a CV to the stack, we don't merge it with anything first, as the -// reference impl does. Instead we do merges using the *previous* CV that was -// added, which is sitting on top of the stack, and we put the new CV -// (unmerged) on top of the stack afterwards. This guarantees that we never -// merge the root node until finalize(). -// -// Solving the first problem requires an additional tool, -// compress_subtree_to_parent_node(). That function always returns the top -// *two* chaining values of the subtree it's compressing. We then do lazy -// merging with each of them separately, so that the second CV will always -// remain unmerged. (That also helps us support extendable output when we're -// hashing an input all-at-once.) -INLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN], - uint64_t chunk_counter) { - hasher_merge_cv_stack(self, chunk_counter); - memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv, - BLAKE3_OUT_LEN); - self->cv_stack_len += 1; -} - -INLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8], - uint8_t flags) { - memcpy(self->key, key, BLAKE3_KEY_LEN); - chunk_state_init(&self->chunk, key, flags); - self->cv_stack_len = 0; -} - -void blake3_hasher_update(blake3_hasher *self, const void *input, - size_t input_len) { - // Explicitly checking for zero avoids causing UB by passing a null pointer - // to memcpy. This comes up in practice with things like: - // std::vector v; - // blake3_hasher_update(&hasher, v.data(), v.size()); - if (input_len == 0) { - return; - } - - const uint8_t *input_bytes = (const uint8_t *)input; - - // If we have some partial chunk bytes in the internal chunk_state, we need - // to finish that chunk first. - if (chunk_state_len(&self->chunk) > 0) { - size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk); - if (take > input_len) { - take = input_len; - } - chunk_state_update(&self->chunk, input_bytes, take); - input_bytes += take; - input_len -= take; - // If we've filled the current chunk and there's more coming, finalize this - // chunk and proceed. In this case we know it's not the root. - if (input_len > 0) { - output_t output = chunk_state_output(&self->chunk); - uint8_t chunk_cv[32]; - output_chaining_value(&output, chunk_cv); - hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter); - chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1); - } else { - return; - } - } - - // Now the chunk_state is clear, and we have more input. If there's more than - // a single chunk (so, definitely not the root chunk), hash the largest whole - // subtree we can, with the full benefits of SIMD (and maybe in the future, - // multi-threading) parallelism. Two restrictions: - // - The subtree has to be a power-of-2 number of chunks. Only subtrees along - // the right edge can be incomplete, and we don't know where the right edge - // is going to be until we get to finalize(). - // - The subtree must evenly divide the total number of chunks up until this - // point (if total is not 0). If the current incomplete subtree is only - // waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have - // to complete the current subtree first. - // Because we might need to break up the input to form powers of 2, or to - // evenly divide what we already have, this part runs in a loop. - while (input_len > BLAKE3_CHUNK_LEN) { - size_t subtree_len = round_down_to_power_of_2(input_len); - uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN; - // Shrink the subtree_len until it evenly divides the count so far. We know - // that subtree_len itself is a power of 2, so we can use a bitmasking - // trick instead of an actual remainder operation. (Note that if the caller - // consistently passes power-of-2 inputs of the same size, as is hopefully - // typical, this loop condition will always fail, and subtree_len will - // always be the full length of the input.) - // - // An aside: We don't have to shrink subtree_len quite this much. For - // example, if count_so_far is 1, we could pass 2 chunks to - // compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still - // get the right answer in the end, and we might get to use 2-way SIMD - // parallelism. The problem with this optimization, is that it gets us - // stuck always hashing 2 chunks. The total number of chunks will remain - // odd, and we'll never graduate to higher degrees of parallelism. See - // https://github.com/BLAKE3-team/BLAKE3/issues/69. - while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) { - subtree_len /= 2; - } - // The shrunken subtree_len might now be 1 chunk long. If so, hash that one - // chunk by itself. Otherwise, compress the subtree into a pair of CVs. - uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN; - if (subtree_len <= BLAKE3_CHUNK_LEN) { - blake3_chunk_state chunk_state; - chunk_state_init(&chunk_state, self->key, self->chunk.flags); - chunk_state.chunk_counter = self->chunk.chunk_counter; - chunk_state_update(&chunk_state, input_bytes, subtree_len); - output_t output = chunk_state_output(&chunk_state); - uint8_t cv[BLAKE3_OUT_LEN]; - output_chaining_value(&output, cv); - hasher_push_cv(self, cv, chunk_state.chunk_counter); - } else { - // This is the high-performance happy path, though getting here depends - // on the caller giving us a long enough input. - uint8_t cv_pair[2 * BLAKE3_OUT_LEN]; - compress_subtree_to_parent_node(input_bytes, subtree_len, self->key, - self->chunk.chunk_counter, - self->chunk.flags, cv_pair); - hasher_push_cv(self, cv_pair, self->chunk.chunk_counter); - hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN], - self->chunk.chunk_counter + (subtree_chunks / 2)); - } - self->chunk.chunk_counter += subtree_chunks; - input_bytes += subtree_len; - input_len -= subtree_len; - } - - // If there's any remaining input less than a full chunk, add it to the chunk - // state. In that case, also do a final merge loop to make sure the subtree - // stack doesn't contain any unmerged pairs. The remaining input means we - // know these merges are non-root. This merge loop isn't strictly necessary - // here, because hasher_push_chunk_cv already does its own merge loop, but it - // simplifies blake3_hasher_finalize below. - if (input_len > 0) { - chunk_state_update(&self->chunk, input_bytes, input_len); - hasher_merge_cv_stack(self, self->chunk.chunk_counter); - } -} - -void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, - uint8_t *out, size_t out_len) { - // Explicitly checking for zero avoids causing UB by passing a null pointer - // to memcpy. This comes up in practice with things like: - // std::vector v; - // blake3_hasher_finalize(&hasher, v.data(), v.size()); - if (out_len == 0) { - return; - } - - // If the subtree stack is empty, then the current chunk is the root. - if (self->cv_stack_len == 0) { - output_t output = chunk_state_output(&self->chunk); - output_root_bytes(&output, seek, out, out_len); - return; - } - // If there are any bytes in the chunk state, finalize that chunk and do a - // roll-up merge between that chunk hash and every subtree in the stack. In - // this case, the extra merge loop at the end of blake3_hasher_update - // guarantees that none of the subtrees in the stack need to be merged with - // each other first. Otherwise, if there are no bytes in the chunk state, - // then the top of the stack is a chunk hash, and we start the merge from - // that. - output_t output; - size_t cvs_remaining; - if (chunk_state_len(&self->chunk) > 0) { - cvs_remaining = self->cv_stack_len; - output = chunk_state_output(&self->chunk); - } else { - // There are always at least 2 CVs in the stack in this case. - cvs_remaining = self->cv_stack_len - 2; - output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key, - self->chunk.flags); - } - while (cvs_remaining > 0) { - cvs_remaining -= 1; - uint8_t parent_block[BLAKE3_BLOCK_LEN]; - memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32); - output_chaining_value(&output, &parent_block[32]); - output = parent_output(parent_block, self->key, self->chunk.flags); - } - output_root_bytes(&output, seek, out, out_len); -} - -void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, - size_t out_len) { - blake3_hasher_finalize_seek(self, 0, out, out_len); -} - -void blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); } - -void blake3_hasher_init_keyed(blake3_hasher *self, - const uint8_t key[BLAKE3_KEY_LEN]) { - uint32_t key_words[8]; - load_key_words(key, key_words); - hasher_init_base(self, key_words, KEYED_HASH); -} - -void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) { - blake3_hasher context_hasher; - hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT); - blake3_hasher_update(&context_hasher, context, strlen(context)); - uint8_t context_key[BLAKE3_KEY_LEN]; - blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN); - uint32_t context_key_words[8]; - load_key_words(context_key, context_key_words); - hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL); -} - -#endif /* BLAKE3_H */ diff --git a/include/ckb-c-stdlib/ckb_consts.h b/include/ckb-c-stdlib/ckb_consts.h deleted file mode 100644 index 0b9f380..0000000 --- a/include/ckb-c-stdlib/ckb_consts.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_CONSTS_H_ -#define CKB_C_STDLIB_CKB_CONSTS_H_ - -#define SYS_exit 93 -#define SYS_ckb_vm_version 2041 -#define SYS_ckb_current_cycles 2042 -#define SYS_ckb_exec 2043 -#define SYS_ckb_load_transaction 2051 -#define SYS_ckb_load_script 2052 -#define SYS_ckb_load_tx_hash 2061 -#define SYS_ckb_load_script_hash 2062 -#define SYS_ckb_load_cell 2071 -#define SYS_ckb_load_header 2072 -#define SYS_ckb_load_input 2073 -#define SYS_ckb_load_witness 2074 -#define SYS_ckb_load_cell_by_field 2081 -#define SYS_ckb_load_header_by_field 2082 -#define SYS_ckb_load_input_by_field 2083 -#define SYS_ckb_load_cell_data_as_code 2091 -#define SYS_ckb_load_cell_data 2092 -#define SYS_ckb_debug 2177 -#define SYS_ckb_spawn 2101 -#define SYS_ckb_get_memory_limit 2102 -#define SYS_ckb_set_content 2103 -#define SYS_ckb_load_block_extension 2104 -#define SYS_ckb_current_memory 2105 - -#define CKB_SUCCESS 0 -#define CKB_INDEX_OUT_OF_BOUND 1 -#define CKB_ITEM_MISSING 2 -#define CKB_LENGTH_NOT_ENOUGH 3 -#define CKB_INVALID_DATA 4 - -#define CKB_SOURCE_INPUT 1 -#define CKB_SOURCE_OUTPUT 2 -#define CKB_SOURCE_CELL_DEP 3 -#define CKB_SOURCE_HEADER_DEP 4 -#define CKB_SOURCE_GROUP_INPUT 0x0100000000000001 -#define CKB_SOURCE_GROUP_OUTPUT 0x0100000000000002 - -#define CKB_CELL_FIELD_CAPACITY 0 -#define CKB_CELL_FIELD_DATA_HASH 1 -#define CKB_CELL_FIELD_LOCK 2 -#define CKB_CELL_FIELD_LOCK_HASH 3 -#define CKB_CELL_FIELD_TYPE 4 -#define CKB_CELL_FIELD_TYPE_HASH 5 -#define CKB_CELL_FIELD_OCCUPIED_CAPACITY 6 - -#define CKB_HEADER_FIELD_EPOCH_NUMBER 0 -#define CKB_HEADER_FIELD_EPOCH_START_BLOCK_NUMBER 1 -#define CKB_HEADER_FIELD_EPOCH_LENGTH 2 - -#define CKB_INPUT_FIELD_OUT_POINT 0 -#define CKB_INPUT_FIELD_SINCE 1 - -#endif /* CKB_C_STDLIB_CKB_CONSTS_H_ */ diff --git a/include/ckb-c-stdlib/ckb_dlfcn.h b/include/ckb-c-stdlib/ckb_dlfcn.h deleted file mode 100644 index 3ca4565..0000000 --- a/include/ckb-c-stdlib/ckb_dlfcn.h +++ /dev/null @@ -1,477 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_DLFCN_H_ -#define CKB_C_STDLIB_CKB_DLFCN_H_ - -#include "ckb_syscalls.h" - -int ckb_dlopen(const uint8_t *dep_cell_data_hash, uint8_t *aligned_addr, - size_t aligned_size, void **handle, size_t *consumed_size) { - return ckb_dlopen2(dep_cell_data_hash, 0, aligned_addr, aligned_size, handle, - consumed_size); -} - -#ifndef CKB_STDLIB_NO_SYSCALL_IMPL - -int _ckb_load_cell_code(void *addr, size_t memory_size, size_t content_offset, - size_t content_size, size_t index, size_t source) { - return syscall(SYS_ckb_load_cell_data_as_code, addr, memory_size, - content_offset, content_size, index, source); -} - -/* - * The ELF parsing code here is inspired from - * https://github.com/riscv/riscv-pk/blob/master/pk/elf.h, original code is in - * BSD license. - */ - -typedef struct { - uint8_t e_ident[16]; - uint16_t e_type; - uint16_t e_machine; - uint32_t e_version; - uint64_t e_entry; - uint64_t e_phoff; - uint64_t e_shoff; - uint32_t e_flags; - uint16_t e_ehsize; - uint16_t e_phentsize; - uint16_t e_phnum; - uint16_t e_shentsize; - uint16_t e_shnum; - uint16_t e_shstrndx; -} Elf64_Ehdr; - -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_DYNSYM 11 - -typedef struct { - uint32_t sh_name; - uint32_t sh_type; - uint64_t sh_flags; - uint64_t sh_addr; - uint64_t sh_offset; - uint64_t sh_size; - uint32_t sh_link; - uint32_t sh_info; - uint64_t sh_addralign; - uint64_t sh_entsize; -} Elf64_Shdr; - -#define PT_LOAD 1 -#define PF_X 1 - -typedef struct { - uint32_t p_type; - uint32_t p_flags; - uint64_t p_offset; - uint64_t p_vaddr; - uint64_t p_paddr; - uint64_t p_filesz; - uint64_t p_memsz; - uint64_t p_align; -} Elf64_Phdr; - -typedef struct { - uint32_t st_name; - uint8_t st_info; - uint8_t st_other; - uint16_t st_shndx; - uint64_t st_value; - uint64_t st_size; -} Elf64_Sym; - -#define R_RISCV_RELATIVE 3 -#define R_RISCV_JUMP_SLOT 5 - -typedef struct { - uint64_t r_offset; - uint64_t r_info; - int64_t r_addend; -} Elf64_Rela; - -#define RISCV_PGSIZE 4096 - -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#define ERROR_CONTEXT_FAILURE -21 -#define ERROR_INVALID_ELF -22 -#define ERROR_MEMORY_NOT_ENOUGH -23 -#define ERROR_OUT_OF_BOUND -24 -#define ERROR_INVALID_ARGS -25 -#define ERROR_ELF_NOT_ALIGNED -26 - -typedef struct { - Elf64_Sym *dynsyms; - const char *dynstr; - size_t dynsym_size; - uint8_t *base_addr; - size_t size; -} CkbDlfcnContext; - -int check_in_range(const void *p, const CkbDlfcnContext *context) { - uint64_t end; - - void *begin = context->base_addr; - if (__builtin_uaddl_overflow((uint64_t)context->base_addr, context->size, - &end)) { - return 0; - } - if (begin <= p && p < (void *)end) { - return 1; - } else { - return 0; - } -} - -int roundup(uint64_t a, uint64_t b, uint64_t *value) { - if (a == 0) { - *value = 0; - return 0; - } - uint64_t d = (a - 1) / b; - return __builtin_umull_overflow(d + 1, b, value); -} - -uint8_t *addr_offset_checked(uint8_t *aligned_addr, uint64_t aligned_size, - uint64_t offset) { - uint64_t target = 0; - if (offset < aligned_size) { - if (__builtin_uaddl_overflow((uint64_t)aligned_addr, offset, &target)) { - return 0; - } else { - return (uint8_t *)target; - } - } else { - return 0; - } -} - -void *addr_offset_with_context(const void *addr, uint64_t offset, - const CkbDlfcnContext *context) { - uint64_t target = 0; - if (__builtin_uaddl_overflow((uint64_t)addr, offset, &target)) { - return 0; - } else { - if (!check_in_range((const void *)target, context)) { - return 0; - } else { - return (void *)target; - } - } -} - -int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type, - uint8_t *aligned_addr, size_t aligned_size, void **handle, - size_t *consumed_size) { - if (sizeof(CkbDlfcnContext) > RISCV_PGSIZE || aligned_size < RISCV_PGSIZE) { - return ERROR_CONTEXT_FAILURE; - } - if (((uint64_t)aligned_addr) < 8) { - return ERROR_CONTEXT_FAILURE; - } - - if (dep_cell_hash == 0 || aligned_size == 0 || aligned_addr == 0 || - handle == 0 || consumed_size == 0) { - return ERROR_INVALID_ARGS; - } - uint64_t _end = 0; - if (__builtin_uaddl_overflow((uint64_t)aligned_addr, aligned_size, &_end)) { - return ERROR_OUT_OF_BOUND; - } - - CkbDlfcnContext *context = (CkbDlfcnContext *)aligned_addr; - memset(context, 0, sizeof(CkbDlfcnContext)); - aligned_addr += RISCV_PGSIZE; - aligned_size -= RISCV_PGSIZE; - context->base_addr = aligned_addr; - context->size = aligned_size; - - size_t index = SIZE_MAX; - int ret = ckb_look_for_dep_with_hash2(dep_cell_hash, hash_type, &index); - if (ret != CKB_SUCCESS) { - return ret; - } - - /* Basic ELF header parsing */ - Elf64_Ehdr header; - uint64_t len = sizeof(header); - ret = - ckb_load_cell_data((void *)&header, &len, 0, index, CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - if (len < sizeof(header)) { - return ERROR_INVALID_ELF; - } - if ((header.e_phentsize != sizeof(Elf64_Phdr)) || - (header.e_shentsize != sizeof(Elf64_Shdr)) || (header.e_phnum > 16) || - (header.e_shnum > 32)) { - return ERROR_INVALID_ELF; - } - /* Parse program headers and load relevant parts */ - Elf64_Phdr program_headers[16]; - len = sizeof(Elf64_Phdr) * header.e_phnum; - ret = ckb_load_cell_data((void *)program_headers, &len, header.e_phoff, index, - CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - if (len < sizeof(Elf64_Phdr) * header.e_phnum) { - return ERROR_INVALID_ELF; - } - uint64_t max_consumed_size = 0; - for (int i = 0; i < header.e_phnum; i++) { - const Elf64_Phdr *ph = &program_headers[i]; - if (ph->p_type == PT_LOAD && ph->p_memsz > 0) { - if ((ph->p_flags & PF_X) != 0) { - uint64_t prepad = ph->p_vaddr % RISCV_PGSIZE; - uint64_t vaddr = ph->p_vaddr - prepad; - uint64_t memsz = 0; - if (roundup(prepad + ph->p_memsz, RISCV_PGSIZE, &memsz)) { - return ERROR_INVALID_ELF; - } - unsigned long size = 0; - if (__builtin_uaddl_overflow(vaddr, memsz, &size)) { - return ERROR_INVALID_ELF; - } - if (size > aligned_size) { - return ERROR_MEMORY_NOT_ENOUGH; - } - uint8_t *addr2 = addr_offset_checked(aligned_addr, aligned_size, vaddr); - if (addr2 == 0) { - return ERROR_INVALID_ELF; - } - /* - * There is a slight defect in current syscall: if the padding - * required for memory alignment is bigger than the ELF starting - * offset to load, there is not a way for current syscall to correctly - * load the ELF. We use a check here to guard for the condition, and - * exit when it is not satisfied. A better solution might to explicitly - * ask for page aligned code section in linker, or wait for a fixed - * syscall version. - */ - if (ph->p_offset < prepad) { - return ERROR_ELF_NOT_ALIGNED; - } - ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset - prepad, - ph->p_filesz + prepad, index, - CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - max_consumed_size = MAX(max_consumed_size, vaddr + memsz); - } else { - uint64_t filesz = ph->p_filesz; - uint64_t memsz = ph->p_memsz; - uint64_t size = 0; - uint64_t gap_len = 0; - if (filesz > memsz) { - return ERROR_INVALID_ELF; - } - gap_len = memsz - filesz; - - if (__builtin_uaddl_overflow(ph->p_vaddr, memsz, &size)) { - return ERROR_INVALID_ELF; - } - uint64_t consumed_end = 0; - if (roundup(size, RISCV_PGSIZE, &consumed_end)) { - return ERROR_INVALID_ELF; - } - if (consumed_end > aligned_size) { - return ERROR_MEMORY_NOT_ENOUGH; - } - uint8_t *addr2 = - addr_offset_checked(aligned_addr, aligned_size, ph->p_vaddr); - if (addr2 == 0) { - return ERROR_INVALID_ELF; - } - uint64_t read_len = filesz; - ret = ckb_load_cell_data(addr2, &read_len, ph->p_offset, index, - CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - if (read_len < filesz) { - return ERROR_INVALID_ELF; - } - if (gap_len > 0) { - uint8_t *addr3 = addr_offset_with_context(addr2, filesz, context); - uint8_t *addr4 = - addr_offset_with_context(addr3, gap_len - 1, context); - if (addr3 != 0 && addr4 != 0) { - memset(addr3, 0, gap_len); - } else { - return ERROR_INVALID_ELF; - } - } - max_consumed_size = MAX(max_consumed_size, consumed_end); - } - } - } - /* - * Parse sectioin header & relocation headers, - * Perform necessary relocations. - */ - Elf64_Shdr section_headers[32]; - len = sizeof(Elf64_Shdr) * header.e_shnum; - ret = ckb_load_cell_data((void *)section_headers, &len, header.e_shoff, index, - CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - if (len < sizeof(Elf64_Shdr) * header.e_shnum) { - return ERROR_INVALID_ELF; - } - if (header.e_shstrndx >= 32 || header.e_shstrndx >= header.e_shnum) { - return ERROR_INVALID_ELF; - } - /* - * First load shstrtab tab, this is temporary code only needed in ELF loading - * phase here. - */ - Elf64_Shdr *shshrtab = §ion_headers[header.e_shstrndx]; - char shrtab[4096]; - if (shshrtab->sh_size > 4096) { - return ERROR_INVALID_ELF; - } - uint64_t shrtab_len = shshrtab->sh_size; - ret = ckb_load_cell_data((void *)shrtab, &shrtab_len, shshrtab->sh_offset, - index, CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - if (shrtab_len < shshrtab->sh_size) { - return ERROR_INVALID_ELF; - } - for (int i = 0; i < header.e_shnum; i++) { - const Elf64_Shdr *sh = §ion_headers[i]; - if (sh->sh_type == SHT_RELA) { - if (sh->sh_entsize != sizeof(Elf64_Rela)) { - return ERROR_INVALID_ELF; - } - size_t relocation_size = sh->sh_size / sh->sh_entsize; - uint64_t current_offset = sh->sh_offset; - while (relocation_size > 0) { - Elf64_Rela relocations[64]; - size_t load_size = MIN(relocation_size, 64); - uint64_t load_length = load_size * sizeof(Elf64_Rela); - ret = ckb_load_cell_data((void *)relocations, &load_length, - current_offset, index, CKB_SOURCE_CELL_DEP); - if (ret != CKB_SUCCESS) { - return ret; - } - if (load_length < load_size * sizeof(Elf64_Rela)) { - return ERROR_INVALID_ELF; - } - relocation_size -= load_size; - current_offset += load_size * sizeof(Elf64_Rela); - for (size_t j = 0; j < load_size; j++) { - Elf64_Rela *r = &relocations[j]; - uint32_t t = (uint32_t) r->r_info; - if (t != R_RISCV_RELATIVE && t != R_RISCV_JUMP_SLOT) { - /* - * Only relative and jump slot relocations are supported now, - * we might add more later. - */ - return ERROR_INVALID_ELF; - } - if (r->r_offset >= (aligned_size - sizeof(uint64_t)) || - r->r_addend >= (int64_t)(aligned_size) || r->r_addend < 0) { - return ERROR_INVALID_ELF; - } - uint64_t temp = (uint64_t)(aligned_addr + r->r_addend); - memcpy(aligned_addr + r->r_offset, &temp, sizeof(uint64_t)); - } - } - } else if (sh->sh_type == SHT_DYNSYM) { - /* We assume one ELF file only has one DYNSYM section now */ - if (sh->sh_entsize != sizeof(Elf64_Sym)) { - return ERROR_INVALID_ELF; - } - uint8_t *addr2 = - addr_offset_checked(aligned_addr, aligned_size, sh->sh_addr); - if (addr2 == 0) { - return ERROR_INVALID_ELF; - } - context->dynsyms = (Elf64_Sym *)addr2; - context->dynsym_size = sh->sh_size / sh->sh_entsize; - - uint8_t *addr3 = addr_offset_with_context(addr2, sh->sh_size, context); - if (addr3 == 0) { - return ERROR_INVALID_ELF; - } - } else if (sh->sh_type == SHT_STRTAB) { - static char DYNSTR[] = ".dynstr"; - if (sh->sh_name < (4096 - sizeof(DYNSTR)) && - shshrtab->sh_size >= sizeof(DYNSTR) && - sh->sh_name < (shshrtab->sh_size - sizeof(DYNSTR))) { - const char *current_str = shrtab + sh->sh_name; - if (strcmp(DYNSTR, current_str) == 0) { - const uint8_t *addr2 = - addr_offset_checked(aligned_addr, aligned_size, sh->sh_addr); - if (addr2 == 0) { - return ERROR_INVALID_ELF; - } - context->dynstr = (const char *)addr2; - } - } - } - } - if (context->dynsyms == NULL || context->dynstr == NULL) { - return ERROR_INVALID_ELF; - } - *handle = (void *)context; - *consumed_size = max_consumed_size + RISCV_PGSIZE; - return CKB_SUCCESS; -} - -void *ckb_dlsym(void *handle, const char *symbol) { - if (handle == NULL || symbol == NULL) { - return NULL; - } - CkbDlfcnContext *context = (CkbDlfcnContext *)handle; - - if (context->base_addr == NULL || context->size == 0 || - context->dynstr == NULL || context->dynsym_size == 0 || - context->dynsyms == NULL) { - return NULL; - } - if (!check_in_range(context->dynstr, context)) { - return NULL; - } - uint64_t _end = 0; - if (__builtin_uaddl_overflow((uint64_t)context->base_addr, context->size, - &_end)) { - return NULL; - } - - for (uint64_t i = 0; i < context->dynsym_size; i++) { - Elf64_Sym *sym = &context->dynsyms[i]; - const char *str = - addr_offset_with_context(context->dynstr, sym->st_name, context); - const void *str_end = - addr_offset_with_context(str, strlen(symbol), context); - if ((str == 0) || (str_end == 0)) return NULL; - if (strcmp(str, symbol) == 0) { - void *p = - addr_offset_with_context(context->base_addr, sym->st_value, context); - if (p == 0) { - return 0; - } else { - return p; - } - } - } - - return NULL; -} - -#endif /* CKB_STDLIB_NO_SYSCALL_IMPL */ - -#endif /* CKB_C_STDLIB_CKB_DLFCN_H_ */ diff --git a/include/ckb-c-stdlib/ckb_exec.h b/include/ckb-c-stdlib/ckb_exec.h deleted file mode 100644 index c4bb3e0..0000000 --- a/include/ckb-c-stdlib/ckb_exec.h +++ /dev/null @@ -1,207 +0,0 @@ -#ifndef _CBK_C_STDLIB_CKB_EXEC_H_ -#define _CBK_C_STDLIB_CKB_EXEC_H_ -#include -#include - -#ifndef CKB_EXEC_MAX_ARGS_COUNT -#define CKB_EXEC_MAX_ARGS_COUNT 64 -#endif - -#ifndef CKB_EXEC_MAX_BUFF_LEN -#define CKB_EXEC_MAX_BUFF_LEN (32 * 1024) -#endif - -#ifndef CKB_EXEC_MAX_PARAM_LEN -#define CKB_EXEC_MAX_PARAM_LEN (32 * 1024) -#endif - -enum CkbExecErrorCodeType { - ERROR_EXEC_OUT_OF_BOUNDS = 30, - ERROR_EXEC_INVALID_HEX, -}; - -typedef struct CkbBinaryArgsType { - uint32_t count; - uint32_t len[CKB_EXEC_MAX_ARGS_COUNT]; - uint8_t* params[CKB_EXEC_MAX_ARGS_COUNT]; - - uint32_t used_buff; - uint8_t buff[CKB_EXEC_MAX_BUFF_LEN]; -} CkbBinaryArgsType; - -typedef struct CkbHexArgsType { - uint32_t used_buff; - char buff[CKB_EXEC_MAX_BUFF_LEN]; -} CkbHexArgsType; - -static int _exec_getbin(uint8_t x, uint8_t* out) { - if (x >= '0' && x <= '9') { - *out = x - '0'; - } else if (x >= 'A' && x <= 'F') { - *out = x - 'A' + 10; - } else if (x >= 'a' && x <= 'f') { - *out = x - 'a' + 10; - } else { - return ERROR_EXEC_INVALID_HEX; - } - return 0; -} - -static void _exec_gethex(uint8_t x, char* out) { - static char s_mapping[] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - out[0] = s_mapping[(x >> 4) & 0x0F]; - out[1] = s_mapping[x & 0x0F]; -} - -int _exec_safe_strlen(const char* s, uint32_t limit, uint32_t* length) { - if (s == NULL) return ERROR_EXEC_OUT_OF_BOUNDS; - - uint32_t count = 0; - for (; *s; s++) { - count++; - if (count > limit) return ERROR_EXEC_OUT_OF_BOUNDS; - } - *length = count; - return 0; -} - -// the string length of "hex" should be no more than bin_len*2 -// "length" returns the bytes count written in "bin" -static int _exec_hex2bin(const char* hex, uint8_t* bin, uint32_t bin_len, - uint32_t* length) { - uint32_t limit = 2 * bin_len; - uint32_t hex_len; - int err = _exec_safe_strlen(hex, limit, &hex_len); - if (err != 0) return err; - if (hex_len % 2 != 0) return ERROR_EXEC_INVALID_HEX; - *length = hex_len / 2; - if (*length > bin_len) { - return ERROR_EXEC_OUT_OF_BOUNDS; - } - for (uint32_t i = 0; i < *length; i++) { - uint8_t high, low; - err = _exec_getbin(hex[i * 2], &high); - if (err != 0) return err; - err = _exec_getbin(hex[i * 2 + 1], &low); - if (err != 0) return err; - bin[i] = high << 4 | low; - } - return 0; -} - -static int _exec_bin2hex(const uint8_t* bin, uint32_t bin_len, char* hex, - uint32_t hex_len, uint32_t* length, bool last_field) { - if (hex_len < (bin_len * 2 + 1)) { - return ERROR_EXEC_OUT_OF_BOUNDS; - } - for (uint32_t i = 0; i < bin_len; i++) { - _exec_gethex(bin[i], hex + 2 * i); - } - if (last_field) - *(hex + bin_len * 2) = 0; - else - *(hex + bin_len * 2) = ':'; - - *length = 2 * bin_len + 1; - return 0; -} - -// use ckb_exec_reset and ckb_exec_append to generate CkbBinaryArgsType from -// scratch -void ckb_exec_reset(CkbBinaryArgsType* args) { - args->count = 0; - args->used_buff = 0; -} - -int ckb_exec_append(CkbBinaryArgsType* args, uint8_t* data, uint32_t len) { - if (args->count >= CKB_EXEC_MAX_ARGS_COUNT) { - return ERROR_EXEC_INVALID_HEX; - } - uint8_t* p = args->buff + args->used_buff; - args->used_buff += len; - if (args->used_buff > CKB_EXEC_MAX_BUFF_LEN) { - return ERROR_EXEC_OUT_OF_BOUNDS; - } - - memcpy(p, data, len); - args->params[args->count] = p; - args->len[args->count] = len; - - args->count++; - - return 0; -} - -int ckb_exec_encode_params(CkbBinaryArgsType* in, CkbHexArgsType* out) { - int err = 0; - - if (in->count > CKB_EXEC_MAX_ARGS_COUNT || in->count == 0) { - return ERROR_EXEC_OUT_OF_BOUNDS; - } - - out->used_buff = 0; - - for (uint32_t i = 0; i < in->count; i++) { - uint8_t* p = in->params[i]; - uint32_t len = in->len[i]; - uint32_t length; - if (out->used_buff >= CKB_EXEC_MAX_BUFF_LEN) { - return ERROR_EXEC_OUT_OF_BOUNDS; - } - bool last_field = (i == (in->count - 1)); - err = _exec_bin2hex(p, len, out->buff + out->used_buff, - CKB_EXEC_MAX_BUFF_LEN - out->used_buff, &length, - last_field); - if (err != 0) return err; - out->used_buff += length; - } - return 0; -} - -int ckb_exec_decode_params(char* argv, uint8_t** param_ptr, uint32_t* param_len, - char** next_iterator_argv) { - int err = 0; - *param_len = 0; - *param_ptr = NULL; - if (argv == NULL) { - return ERROR_EXEC_INVALID_HEX; - } - uint8_t* cur = (uint8_t*)argv; - uint8_t* write_ptr = cur; - *param_ptr = cur; - *param_len = 0; - - uint32_t count = 0; - - uint8_t high, low; - while (true) { - if (*cur == '\0') { - *next_iterator_argv = NULL; - break; - } - if (*cur == ':') { - *next_iterator_argv = (char*)(cur + 1); - break; - } - err = _exec_getbin(*cur, &high); - if (err != 0) return err; - cur++; - err = _exec_getbin(*cur, &low); - if (err != 0) return err; - cur++; - - (*write_ptr) = high << 4 | low; - write_ptr++; - (*param_len)++; - - // prevent infinite loop when no ":" or "\0" is detected - count++; - if (count > CKB_EXEC_MAX_PARAM_LEN) { - return ERROR_EXEC_OUT_OF_BOUNDS; - } - } - return 0; -} - -#endif // _CBK_C_STDLIB_CKB_EXEC_H_ diff --git a/include/ckb-c-stdlib/ckb_keccak256.h b/include/ckb-c-stdlib/ckb_keccak256.h deleted file mode 100644 index c42a936..0000000 --- a/include/ckb-c-stdlib/ckb_keccak256.h +++ /dev/null @@ -1,358 +0,0 @@ -/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak). - * based on the - * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 - * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche - * - * Copyright: 2013 Aleksey Kravchenko - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! - */ - -#ifndef __KECCAK256_H_ -#define __KECCAK256_H_ - -#include -#include - -#define sha3_max_permutation_size 25 -#define sha3_max_rate_in_qwords 24 - -typedef struct SHA3_CTX { - /* 1600 bits algorithm hashing state */ - uint64_t hash[sha3_max_permutation_size]; - /* 1536-bit buffer for leftovers */ - uint64_t message[sha3_max_rate_in_qwords]; - /* count of bytes in the message[] buffer */ - uint16_t rest; - /* size of a message block processed at once */ - // unsigned block_size; -} SHA3_CTX; - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -void keccak_init(SHA3_CTX *ctx); -void keccak_update(SHA3_CTX *ctx, unsigned char *msg, uint16_t size); -void keccak_final(SHA3_CTX *ctx, unsigned char *result); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -// keccak256 implementation - -#define BLOCK_SIZE ((1600 - 256 * 2) / 8) - -#define I64(x) x##LL -#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) -#define le2me_64(x) (x) -#define IS_ALIGNED_64(p) (0 == (7 & ((const char *)(p) - (const char *)0))) -#define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) - -/* constants */ - -// const uint8_t round_constant_info[] PROGMEM = { -// const uint8_t constants[] PROGMEM = { -const uint8_t constants[] = { - - 1, - 26, - 94, - 112, - 31, - 33, - 121, - 85, - 14, - 12, - 53, - 38, - 63, - 79, - 93, - 83, - 82, - 72, - 22, - 102, - 121, - 88, - 33, - 116, - //}; - - // const uint8_t pi_transform[] PROGMEM = { - 1, - 6, - 9, - 22, - 14, - 20, - 2, - 12, - 13, - 19, - 23, - 15, - 4, - 24, - 21, - 8, - 16, - 5, - 3, - 18, - 17, - 11, - 7, - 10, - //}; - - // const uint8_t rhoTransforms[] PROGMEM = { - 1, - 62, - 28, - 27, - 36, - 44, - 6, - 55, - 20, - 3, - 10, - 43, - 25, - 39, - 41, - 45, - 15, - 21, - 8, - 18, - 2, - 61, - 56, - 14, -}; - -#define TYPE_ROUND_INFO 0 -#define TYPE_PI_TRANSFORM 24 -#define TYPE_RHO_TRANSFORM 48 - -uint8_t getConstant(uint8_t type, uint8_t index) { - return constants[type + index]; - // return pgm_read_byte(&constants[type + index]); -} - -static uint64_t get_round_constant(uint8_t round) { - uint64_t result = 0; - - // uint8_t roundInfo = pgm_read_byte(&round_constant_info[round]); - uint8_t roundInfo = getConstant(TYPE_ROUND_INFO, round); - if (roundInfo & (1 << 6)) { - result |= ((uint64_t)1 << 63); - } - if (roundInfo & (1 << 5)) { - result |= ((uint64_t)1 << 31); - } - if (roundInfo & (1 << 4)) { - result |= ((uint64_t)1 << 15); - } - if (roundInfo & (1 << 3)) { - result |= ((uint64_t)1 << 7); - } - if (roundInfo & (1 << 2)) { - result |= ((uint64_t)1 << 3); - } - if (roundInfo & (1 << 1)) { - result |= ((uint64_t)1 << 1); - } - if (roundInfo & (1 << 0)) { - result |= ((uint64_t)1 << 0); - } - - return result; -} - -/* Initializing a sha3 context for given number of output bits */ -void keccak_init(SHA3_CTX *ctx) { - /* NB: The Keccak capacity parameter = bits * 2 */ - - memset(ctx, 0, sizeof(SHA3_CTX)); -} - -/* Keccak theta() transformation */ -static void keccak_theta(uint64_t *A) { - uint64_t C[5], D[5]; - - for (uint8_t i = 0; i < 5; i++) { - C[i] = A[i]; - for (uint8_t j = 5; j < 25; j += 5) { - C[i] ^= A[i + j]; - } - } - - for (uint8_t i = 0; i < 5; i++) { - D[i] = ROTL64(C[(i + 1) % 5], 1) ^ C[(i + 4) % 5]; - } - - for (uint8_t i = 0; i < 5; i++) { - // for (uint8_t j = 0; j < 25; j += 5) { - for (uint8_t j = 0; j < 25; j += 5) { - A[i + j] ^= D[i]; - } - } -} - -/* Keccak pi() transformation */ -static void keccak_pi(uint64_t *A) { - uint64_t A1 = A[1]; - // for (uint8_t i = 1; i < sizeof(pi_transform); i++) { - for (uint8_t i = 1; i < 24; i++) { - // A[pgm_read_byte(&pi_transform[i - 1])] = - // A[pgm_read_byte(&pi_transform[i])]; - A[getConstant(TYPE_PI_TRANSFORM, i - 1)] = - A[getConstant(TYPE_PI_TRANSFORM, i)]; - } - A[10] = A1; - /* note: A[ 0] is left as is */ -} - -/* -ketch uses 30084 bytes (93%) of program storage space. Maximum is 32256 bytes. -Global variables use 743 bytes (36%) of dynamic memory, leaving 1305 bytes for -local variables. Maximum is 2048 bytes. -*/ -/* Keccak chi() transformation */ -static void keccak_chi(uint64_t *A) { - for (uint8_t i = 0; i < 25; i += 5) { - uint64_t A0 = A[0 + i], A1 = A[1 + i]; - A[0 + i] ^= ~A1 & A[2 + i]; - A[1 + i] ^= ~A[2 + i] & A[3 + i]; - A[2 + i] ^= ~A[3 + i] & A[4 + i]; - A[3 + i] ^= ~A[4 + i] & A0; - A[4 + i] ^= ~A0 & A1; - } -} - -static void sha3_permutation(uint64_t *state) { - // for (uint8_t round = 0; round < sizeof(round_constant_info); round++) { - for (uint8_t round = 0; round < 24; round++) { - keccak_theta(state); - - /* apply Keccak rho() transformation */ - for (uint8_t i = 1; i < 25; i++) { - // state[i] = ROTL64(state[i], pgm_read_byte(&rhoTransforms[i - 1])); - state[i] = ROTL64(state[i], getConstant(TYPE_RHO_TRANSFORM, i - 1)); - } - - keccak_pi(state); - keccak_chi(state); - - /* apply iota(state, round) */ - *state ^= get_round_constant(round); - } -} - -/** - * The core transformation. Process the specified block of data. - * - * @param hash the algorithm state - * @param block the message block to process - * @param block_size the size of the processed block in bytes - */ -static void sha3_process_block(uint64_t hash[25], const uint64_t *block) { - for (uint8_t i = 0; i < 17; i++) { - hash[i] ^= le2me_64(block[i]); - } - - /* make a permutation of the hash */ - sha3_permutation(hash); -} - -//#define SHA3_FINALIZED 0x80000000 -//#define SHA3_FINALIZED 0x8000 - -/** - * Calculate message hash. - * Can be called repeatedly with chunks of the message to be hashed. - * - * @param ctx the algorithm context containing current hashing state - * @param msg message chunk - * @param size length of the message chunk - */ -void keccak_update(SHA3_CTX *ctx, unsigned char *msg, uint16_t size) { - uint16_t idx = (uint16_t)ctx->rest; - - // if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ - ctx->rest = (unsigned)((ctx->rest + size) % BLOCK_SIZE); - - /* fill partial block */ - if (idx) { - uint16_t left = BLOCK_SIZE - idx; - memcpy((char *)ctx->message + idx, msg, (size < left ? size : left)); - if (size < left) return; - - /* process partial block */ - sha3_process_block(ctx->hash, ctx->message); - msg += left; - size -= left; - } - - while (size >= BLOCK_SIZE) { - uint64_t *aligned_message_block; - if (IS_ALIGNED_64(msg)) { - // the most common case is processing of an already aligned message - // without copying it - aligned_message_block = (uint64_t *)(void *)msg; - } else { - memcpy(ctx->message, msg, BLOCK_SIZE); - aligned_message_block = ctx->message; - } - - sha3_process_block(ctx->hash, aligned_message_block); - msg += BLOCK_SIZE; - size -= BLOCK_SIZE; - } - - if (size) { - memcpy(ctx->message, msg, size); /* save leftovers */ - } -} - -/** - * Store calculated hash into the given array. - * - * @param ctx the algorithm context containing current hashing state - * @param result calculated hash in binary form - */ -void keccak_final(SHA3_CTX *ctx, unsigned char *result) { - uint16_t digest_length = 100 - BLOCK_SIZE / 2; - - // if (!(ctx->rest & SHA3_FINALIZED)) { - /* clear the rest of the data queue */ - memset((char *)ctx->message + ctx->rest, 0, BLOCK_SIZE - ctx->rest); - ((char *)ctx->message)[ctx->rest] |= 0x01; - ((char *)ctx->message)[BLOCK_SIZE - 1] |= 0x80; - - /* process final block */ - sha3_process_block(ctx->hash, ctx->message); - // ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ - // } - - if (result) { - me64_to_le_str(result, ctx->hash, digest_length); - } -} - -#endif /* __KECCAK256_H_ */ diff --git a/include/ckb-c-stdlib/ckb_streaming.h b/include/ckb-c-stdlib/ckb_streaming.h deleted file mode 100644 index 7dc1094..0000000 --- a/include/ckb-c-stdlib/ckb_streaming.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_STREAMING_H_ -#define CKB_C_STDLIB_CKB_STREAMING_H_ - -#ifndef CKB_ONE_BATCH_SIZE -#define CKB_ONE_BATCH_SIZE 16384 -#endif /* CKB_ONE_BATCH_SIZE */ - -#include "blake2b.h" -#include "ckb_syscalls.h" - -typedef int (*load_function)(void *, uint64_t *, size_t, size_t, size_t); - -int ckb_load_and_hash(blake2b_state *ctx, size_t start, size_t index, - size_t source, load_function f) { - uint8_t temp[CKB_ONE_BATCH_SIZE]; - uint64_t len = CKB_ONE_BATCH_SIZE; - int ret = f(temp, &len, start, index, source); - if (ret != CKB_SUCCESS) { - return ret; - } - blake2b_update(ctx, (char *)&len, sizeof(uint64_t)); - uint64_t offset = (len > CKB_ONE_BATCH_SIZE) ? CKB_ONE_BATCH_SIZE : len; - blake2b_update(ctx, temp, offset); - while (offset < len) { - uint64_t current_len = CKB_ONE_BATCH_SIZE; - ret = f(temp, ¤t_len, start + offset, index, source); - if (ret != CKB_SUCCESS) { - return ret; - } - uint64_t current_read = - (current_len > CKB_ONE_BATCH_SIZE) ? CKB_ONE_BATCH_SIZE : current_len; - blake2b_update(ctx, temp, current_read); - offset += current_read; - } - return CKB_SUCCESS; -} - -int ckb_hash_cell(blake2b_state *ctx, size_t index_code, size_t source) { - return ckb_load_and_hash(ctx, 0, index_code, source, ckb_load_cell); -} - -int ckb_hash_input(blake2b_state *ctx, size_t index_code, size_t source) { - return ckb_load_and_hash(ctx, 0, index_code, source, ckb_load_input); -} - -#endif /* CKB_C_STDLIB_CKB_STREAMING_H_ */ diff --git a/include/ckb-c-stdlib/ckb_swappable_signatures.h b/include/ckb-c-stdlib/ckb_swappable_signatures.h deleted file mode 100644 index 4e81efd..0000000 --- a/include/ckb-c-stdlib/ckb_swappable_signatures.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_SWAPPABLE_SIGNATURES_H_ -#define CKB_C_STDLIB_CKB_SWAPPABLE_SIGNATURES_H_ - -#include "ckb_dlfcn.h" - -#ifdef CKB_SWAPPABLE_SIGNATURES_DEBUG -#define DEBUG(s) ckb_debug(s) -#else -#define DEBUG(s) -#endif /* CKB_SWAPPABLE_SIGNATURES_DEBUG */ - -typedef int (*verify_function)(void *, const uint8_t *, size_t, const uint8_t *, - size_t, uint8_t *, size_t *); - -typedef struct { - uint8_t *code_buffer; - uint64_t code_buffer_size; - uint8_t *prefilled_data_buffer; - size_t prefilled_buffer_size; - verify_function verify_func; -} CkbSwappableSignatureInstance; - -int ckb_initialize_swappable_signature( - const uint8_t *code_hash, uint8_t hash_type, - CkbSwappableSignatureInstance *instance) { - void *handle = NULL; - size_t consumed_size = 0; - int ret = ckb_dlopen2(code_hash, hash_type, instance->code_buffer, - instance->code_buffer_size, &handle, &consumed_size); - if (ret != CKB_SUCCESS) { - return ret; - } - instance->code_buffer_size = consumed_size; - int (*load_prefilled_data_func)(void *, size_t *); - *(void **)(&load_prefilled_data_func) = - ckb_dlsym(handle, "load_prefilled_data"); - if (load_prefilled_data_func == NULL) { - DEBUG("Error loading load prefilled data func!"); - return CKB_INVALID_DATA; - } - ret = load_prefilled_data_func(instance->prefilled_data_buffer, - &instance->prefilled_buffer_size); - if (ret != CKB_SUCCESS) { - DEBUG("Error loading prefilled data!"); - return ret; - } - *(void **)(&instance->verify_func) = ckb_dlsym(handle, "validate_signature"); - if (instance->verify_func == NULL) { - DEBUG("Error loading validate signature func!"); - return CKB_INVALID_DATA; - } - return CKB_SUCCESS; -} - -#endif /* CKB_C_STDLIB_CKB_SWAPPABLE_SIGNATURES_H_ */ diff --git a/include/ckb-c-stdlib/ckb_syscall_apis.h b/include/ckb-c-stdlib/ckb_syscall_apis.h deleted file mode 100644 index 3e7486c..0000000 --- a/include/ckb-c-stdlib/ckb_syscall_apis.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_SYSCALL_APIS_H_ -#define CKB_C_STDLIB_CKB_SYSCALL_APIS_H_ - -/* - * Syscall related APIs that will be shared and used in all CKB - * smart contract environments - */ - -#include -#include - -int ckb_exit(int8_t code); -int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset); -int ckb_load_transaction(void* addr, uint64_t* len, size_t offset); -int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset); -int ckb_load_script(void* addr, uint64_t* len, size_t offset); -int ckb_debug(const char* s); - -int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); -int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); -int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); -int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); -int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); -int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); -int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); -int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); -int ckb_vm_version(); -uint64_t ckb_current_cycles(); -int ckb_exec_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, - uint32_t length, int argc, const char* argv[]); - -int ckb_dlopen2(const uint8_t* dep_cell_hash, uint8_t hash_type, - uint8_t* aligned_addr, size_t aligned_size, void** handle, - size_t* consumed_size); -void* ckb_dlsym(void* handle, const char* symbol); - -typedef struct spawn_args_t { - uint64_t memory_limit; - int8_t* exit_code; - uint8_t* content; - uint64_t* content_length; -} spawn_args_t; -int ckb_spawn(size_t index, size_t source, size_t bounds, int argc, - const char* argv[], spawn_args_t* spgs); -int ckb_spawn_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, - uint32_t length, int argc, const char* argv[], - spawn_args_t* spgs); -int ckb_get_memory_limit(); -int ckb_set_content(uint8_t* content, uint64_t* length); - -#endif /* CKB_C_STDLIB_CKB_SYSCALL_APIS_H_ */ diff --git a/include/ckb-c-stdlib/ckb_syscalls.h b/include/ckb-c-stdlib/ckb_syscalls.h deleted file mode 100644 index 39a54d7..0000000 --- a/include/ckb-c-stdlib/ckb_syscalls.h +++ /dev/null @@ -1,415 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_SYSCALLS_H_ -#define CKB_C_STDLIB_CKB_SYSCALLS_H_ - -#include -#include -#include - -#include "ckb_consts.h" -#include "ckb_syscall_apis.h" - -int ckb_checked_load_tx_hash(void* addr, uint64_t* len, size_t offset) { - uint64_t old_len = *len; - int ret = ckb_load_tx_hash(addr, len, offset); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_script_hash(void* addr, uint64_t* len, size_t offset) { - uint64_t old_len = *len; - int ret = ckb_load_script_hash(addr, len, offset); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_cell(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source) { - uint64_t old_len = *len; - int ret = ckb_load_cell(addr, len, offset, index, source); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_input(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source) { - uint64_t old_len = *len; - int ret = ckb_load_input(addr, len, offset, index, source); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_header(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source) { - uint64_t old_len = *len; - int ret = ckb_load_header(addr, len, offset, index, source); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_witness(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source) { - uint64_t old_len = *len; - int ret = ckb_load_witness(addr, len, offset, index, source); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_script(void* addr, uint64_t* len, size_t offset) { - uint64_t old_len = *len; - int ret = ckb_load_script(addr, len, offset); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_transaction(void* addr, uint64_t* len, size_t offset) { - uint64_t old_len = *len; - int ret = ckb_load_transaction(addr, len, offset); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - uint64_t old_len = *len; - int ret = ckb_load_cell_by_field(addr, len, offset, index, source, field); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, - size_t field) { - uint64_t old_len = *len; - int ret = ckb_load_header_by_field(addr, len, offset, index, source, field); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - uint64_t old_len = *len; - int ret = ckb_load_input_by_field(addr, len, offset, index, source, field); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_checked_load_cell_data(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source) { - uint64_t old_len = *len; - int ret = ckb_load_cell_data(addr, len, offset, index, source); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -/* load the actual witness for the current type verify group. - use this instead of ckb_load_witness if type contract needs args to verify - input/output. - */ -int ckb_load_actual_type_witness(uint8_t* buf, uint64_t* len, size_t index, - size_t* type_source) { - *type_source = CKB_SOURCE_GROUP_INPUT; - uint64_t tmp_len = 0; - if (ckb_load_cell_by_field(NULL, &tmp_len, 0, 0, CKB_SOURCE_GROUP_INPUT, - CKB_CELL_FIELD_CAPACITY) == - CKB_INDEX_OUT_OF_BOUND) { - *type_source = CKB_SOURCE_GROUP_OUTPUT; - } - - return ckb_checked_load_witness(buf, len, 0, index, *type_source); -} - -/* calculate inputs length */ -int ckb_calculate_inputs_len() { - uint64_t len = 0; - /* lower bound, at least tx has one input */ - int lo = 0; - /* higher bound */ - int hi = 4; - int ret; - /* try to load input until failing to increase lo and hi */ - while (1) { - ret = ckb_load_input_by_field(NULL, &len, 0, hi, CKB_SOURCE_INPUT, - CKB_INPUT_FIELD_SINCE); - if (ret == CKB_SUCCESS) { - lo = hi; - hi *= 2; - } else { - break; - } - } - - /* now we get our lower bound and higher bound, - count number of inputs by binary search */ - int i; - while (lo + 1 != hi) { - i = (lo + hi) / 2; - ret = ckb_load_input_by_field(NULL, &len, 0, i, CKB_SOURCE_INPUT, - CKB_INPUT_FIELD_SINCE); - if (ret == CKB_SUCCESS) { - lo = i; - } else { - hi = i; - } - } - /* now lo is last input index and hi is length of inputs */ - return hi; -} - -/* - * Look for a dep cell with specific code hash, code_hash should be a buffer - * with 32 bytes. - */ -int ckb_look_for_dep_with_hash2(const uint8_t* code_hash, uint8_t hash_type, - size_t* index) { - size_t current = 0; - size_t field = - (hash_type == 1) ? CKB_CELL_FIELD_TYPE_HASH : CKB_CELL_FIELD_DATA_HASH; - while (current < SIZE_MAX) { - uint64_t len = 32; - uint8_t hash[32]; - - int ret = ckb_load_cell_by_field(hash, &len, 0, current, - CKB_SOURCE_CELL_DEP, field); - switch (ret) { - case CKB_ITEM_MISSING: - break; - case CKB_SUCCESS: - if (memcmp(code_hash, hash, 32) == 0) { - /* Found a match */ - *index = current; - return CKB_SUCCESS; - } - break; - default: - return CKB_INDEX_OUT_OF_BOUND; - } - current++; - } - return CKB_INDEX_OUT_OF_BOUND; -} - -int ckb_look_for_dep_with_hash(const uint8_t* data_hash, size_t* index) { - return ckb_look_for_dep_with_hash2(data_hash, 0, index); -} - -#ifndef CKB_STDLIB_NO_SYSCALL_IMPL - -#define memory_barrier() asm volatile("fence" ::: "memory") - -static inline long __internal_syscall(long n, long _a0, long _a1, long _a2, - long _a3, long _a4, long _a5) { - register long a0 asm("a0") = _a0; - register long a1 asm("a1") = _a1; - register long a2 asm("a2") = _a2; - register long a3 asm("a3") = _a3; - register long a4 asm("a4") = _a4; - register long a5 asm("a5") = _a5; - -#ifdef __riscv_32e - register long syscall_id asm("t0") = n; -#else - register long syscall_id asm("a7") = n; -#endif - - asm volatile("scall" - : "+r"(a0) - : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(syscall_id)); - /* - * Syscalls might modify memory sent as pointer, adding a barrier here ensures - * gcc won't do incorrect optimization. - */ - memory_barrier(); - - return a0; -} - -#define syscall(n, a, b, c, d, e, f) \ - __internal_syscall(n, (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), \ - (long)(f)) - -int ckb_exit(int8_t code) { return syscall(SYS_exit, code, 0, 0, 0, 0, 0); } - -int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset) { - volatile uint64_t inner_len = *len; - int ret = syscall(SYS_ckb_load_tx_hash, addr, &inner_len, offset, 0, 0, 0); - *len = inner_len; - return ret; -} - -int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset) { - volatile uint64_t inner_len = *len; - int ret = - syscall(SYS_ckb_load_script_hash, addr, &inner_len, offset, 0, 0, 0); - *len = inner_len; - return ret; -} - -int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - volatile uint64_t inner_len = *len; - int ret = - syscall(SYS_ckb_load_cell, addr, &inner_len, offset, index, source, 0); - *len = inner_len; - return ret; -} - -int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - volatile uint64_t inner_len = *len; - int ret = - syscall(SYS_ckb_load_input, addr, &inner_len, offset, index, source, 0); - *len = inner_len; - return ret; -} - -int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - volatile uint64_t inner_len = *len; - int ret = - syscall(SYS_ckb_load_header, addr, &inner_len, offset, index, source, 0); - *len = inner_len; - return ret; -} - -int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - volatile uint64_t inner_len = *len; - int ret = - syscall(SYS_ckb_load_witness, addr, &inner_len, offset, index, source, 0); - *len = inner_len; - return ret; -} - -int ckb_load_script(void* addr, uint64_t* len, size_t offset) { - volatile uint64_t inner_len = *len; - int ret = syscall(SYS_ckb_load_script, addr, &inner_len, offset, 0, 0, 0); - *len = inner_len; - return ret; -} - -int ckb_load_transaction(void* addr, uint64_t* len, size_t offset) { - volatile uint64_t inner_len = *len; - int ret = - syscall(SYS_ckb_load_transaction, addr, &inner_len, offset, 0, 0, 0); - *len = inner_len; - return ret; -} - -int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - volatile uint64_t inner_len = *len; - int ret = syscall(SYS_ckb_load_cell_by_field, addr, &inner_len, offset, index, - source, field); - *len = inner_len; - return ret; -} - -int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - volatile uint64_t inner_len = *len; - int ret = syscall(SYS_ckb_load_header_by_field, addr, &inner_len, offset, - index, source, field); - *len = inner_len; - return ret; -} - -int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - volatile uint64_t inner_len = *len; - int ret = syscall(SYS_ckb_load_input_by_field, addr, &inner_len, offset, - index, source, field); - *len = inner_len; - return ret; -} - -int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - volatile uint64_t inner_len = *len; - int ret = syscall(SYS_ckb_load_cell_data, addr, &inner_len, offset, index, - source, 0); - *len = inner_len; - return ret; -} - -int ckb_debug(const char* s) { - return syscall(SYS_ckb_debug, s, 0, 0, 0, 0, 0); -} - -int ckb_vm_version() { return syscall(SYS_ckb_vm_version, 0, 0, 0, 0, 0, 0); } - -uint64_t ckb_current_cycles() { - return syscall(SYS_ckb_current_cycles, 0, 0, 0, 0, 0, 0); -} - -int ckb_exec_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, - uint32_t length, int argc, const char* argv[]) { - size_t index = SIZE_MAX; - int ret = ckb_look_for_dep_with_hash2(code_hash, hash_type, &index); - if (ret != CKB_SUCCESS) { - return ret; - } - size_t bounds = ((size_t)offset << 32) | length; - return syscall(SYS_ckb_exec, index, CKB_SOURCE_CELL_DEP, 0, bounds, argc, - argv); -} - -int ckb_spawn(size_t index, size_t source, size_t bounds, int argc, - const char* argv[], spawn_args_t* spgs) { - return syscall(SYS_ckb_spawn, index, source, bounds, argc, argv, spgs); -} - -int ckb_spawn_cell(const uint8_t* code_hash, uint8_t hash_type, uint32_t offset, - uint32_t length, int argc, const char* argv[], - spawn_args_t* spgs) { - size_t index = SIZE_MAX; - int ret = ckb_look_for_dep_with_hash2(code_hash, hash_type, &index); - if (ret != CKB_SUCCESS) { - return ret; - } - size_t bounds = ((size_t)offset << 32) | length; - return ckb_spawn(index, CKB_SOURCE_CELL_DEP, bounds, argc, argv, spgs); -} - -int ckb_get_memory_limit() { - return syscall(SYS_ckb_get_memory_limit, 0, 0, 0, 0, 0, 0); -} - -int ckb_set_content(uint8_t* content, uint64_t* length) { - return syscall(SYS_ckb_set_content, content, length, 0, 0, 0, 0); -} - -int ckb_current_memory() { - return syscall(SYS_ckb_current_memory, 0, 0, 0, 0, 0, 0); -} - -int ckb_load_block_extension(void* addr, uint64_t* len, size_t offset, size_t index, size_t source) { - return syscall(SYS_ckb_load_block_extension, addr, len, offset, index, source, 0); -} - -#endif /* CKB_STDLIB_NO_SYSCALL_IMPL */ - -#endif /* CKB_C_STDLIB_CKB_SYSCALLS_H_ */ diff --git a/include/ckb-c-stdlib/ckb_type_id.h b/include/ckb-c-stdlib/ckb_type_id.h deleted file mode 100644 index 897fd90..0000000 --- a/include/ckb-c-stdlib/ckb_type_id.h +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef CKB_C_STDLIB_CKB_TYPE_ID_H_ -#define CKB_C_STDLIB_CKB_TYPE_ID_H_ - -#include - -#include "blake2b.h" -#include "blockchain.h" -#include "ckb_syscalls.h" - -// Given a 32-byte type id, this function validates if -// current transaction confronts to the type ID rules. -int ckb_validate_type_id(const uint8_t type_id[32]); -// Loading type ID from current script args, type_id must be at least 32 byte -// long. -int ckb_load_type_id_from_script_args(size_t offset, uint8_t type_id[32]); - -#ifndef CKB_TYPE_ID_DECLARATION_ONLY - -#ifdef CKB_TYPE_ID_DEBUG -#define DEBUG(s) ckb_debug(s) -#else -#define DEBUG(s) -#endif /* CKB_TYPE_ID_DEBUG */ - -int ckb_load_type_id_from_script_args(size_t offset, uint8_t type_id[32]) { - // TODO: it is possible to simply load the script header, then only load the - // 32 byte requested data based on offsets. - uint8_t current_script[32768]; - uint64_t len = 32768; - int ret = ckb_load_script(current_script, &len, 0); - if (ret != CKB_SUCCESS) { - DEBUG("Cannot load current script!"); - return CKB_INVALID_DATA; - } - if (len > 32768) { - DEBUG("Current script is too large!"); - return CKB_INVALID_DATA; - } - - mol_seg_t script_seg; - script_seg.ptr = (uint8_t*)current_script; - script_seg.size = len; - if (MolReader_Script_verify(&script_seg, false) != MOL_OK) { - DEBUG("Corrupted data!"); - return CKB_INVALID_DATA; - } - - mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); - mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); - if (offset + 32 > args_bytes_seg.size) { - DEBUG("Length of type id is incorrect!"); - return CKB_INVALID_DATA; - } - memcpy(type_id, &args_bytes_seg.ptr[offset], 32); - return CKB_SUCCESS; -} - -// 1 for true, 0 for false -int _ckb_has_type_id_cell(size_t index, int is_input) { - uint64_t len = 0; - size_t source = - is_input == 1 ? CKB_SOURCE_GROUP_INPUT : CKB_SOURCE_GROUP_OUTPUT; - int ret = ckb_load_cell(NULL, &len, 0, index, source); - return ret == CKB_SUCCESS ? 1 : 0; -} - -int _ckb_locate_first_type_id_output_index(uint64_t* index) { - uint8_t current_script_hash[32]; - uint64_t len = 32; - int ret = ckb_load_script_hash(current_script_hash, &len, 0); - if (ret != CKB_SUCCESS) { - DEBUG("Error loading current script hash!"); - return ret; - } - if (len != 32) { - DEBUG("Invalid script hash length!"); - return CKB_INVALID_DATA; - } - - uint64_t i = 0; - while (1) { - uint8_t buffer[32]; - len = 32; - ret = ckb_load_cell_by_field(buffer, &len, 0, i, CKB_SOURCE_OUTPUT, - CKB_CELL_FIELD_TYPE_HASH); - - if (ret != CKB_SUCCESS) { - if (ret != CKB_ITEM_MISSING) { - DEBUG("Error fetching output type hash to locate type id index!"); - return ret; - } else { - // type script hash can be missing, it's not error - i += 1; - continue; - } - } - if (len != 32) { - DEBUG("Invalid type hash length!"); - return CKB_INVALID_DATA; - } - if (memcmp(buffer, current_script_hash, 32) == 0) { - break; - } - i += 1; - } - *index = i; - return CKB_SUCCESS; -} - -int ckb_validate_type_id(const uint8_t type_id[32]) { - int has_second_type_id_input = _ckb_has_type_id_cell(1, 1); - int has_second_type_id_output = _ckb_has_type_id_cell(1, 0); - if (has_second_type_id_input || has_second_type_id_output) { - DEBUG( - "There can only be at most one input and at most one output type ID " - "cell!"); - return CKB_INVALID_DATA; - } - - int has_first_type_id_input = _ckb_has_type_id_cell(0, 1); - if (!has_first_type_id_input) { - // We are creating a new type ID cell here. Additional checkings are needed - // to ensure the type ID is legit. - uint64_t index = 0xFFFFFFFFFFFFFFFF; - int ret = _ckb_locate_first_type_id_output_index(&index); - if (ret != CKB_SUCCESS) { - return ret; - } - // The type ID is calculated as the blake2b (with CKB's personalization) of - // the first CellInput in current transaction, and the created output cell - // index(in 64-bit little endian unsigned integer). - uint8_t buffer[128]; - uint64_t len = 128; - ret = ckb_checked_load_input(buffer, &len, 0, 0, CKB_SOURCE_INPUT); - if (ret != CKB_SUCCESS) { - DEBUG("Cannot load the first input of the transaction!"); - return ret; - } - blake2b_state blake2b_ctx; - ckb_blake2b_init(&blake2b_ctx, 32); - blake2b_update(&blake2b_ctx, buffer, len); - blake2b_update(&blake2b_ctx, (uint8_t*)(&index), sizeof(index)); - uint8_t expected_type_id[32]; - blake2b_final(&blake2b_ctx, expected_type_id, 32); - if (memcmp(expected_type_id, type_id, 32) != 0) { - DEBUG("Invalid type ID!"); - return CKB_INVALID_DATA; - } - } - return CKB_SUCCESS; -} - -#endif /* CKB_TYPE_ID_DECLARATION_ONLY */ - -#endif /* CKB_C_STDLIB_CKB_TYPE_ID_H_ */ diff --git a/include/ckb-c-stdlib/ckb_utils.h b/include/ckb-c-stdlib/ckb_utils.h deleted file mode 100644 index 99971ce..0000000 --- a/include/ckb-c-stdlib/ckb_utils.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -utils.h - -Defines basic utility functions. -*/ - -#ifndef CKB_C_STDLIB_CKB_UTILS_H_ -#define CKB_C_STDLIB_CKB_UTILS_H_ - -#include "stddef.h" - -/* a and b are since value, - return 0 if a is equals to b, - return -1 if a is less than b, - return 1 if a is greater than b */ -int ckb_epoch_number_with_fraction_cmp(uint64_t a, uint64_t b) { - static const size_t NUMBER_OFFSET = 0; - static const size_t NUMBER_BITS = 24; - static const uint64_t NUMBER_MAXIMUM_VALUE = (1 << NUMBER_BITS); - static const uint64_t NUMBER_MASK = (NUMBER_MAXIMUM_VALUE - 1); - static const size_t INDEX_OFFSET = NUMBER_BITS; - static const size_t INDEX_BITS = 16; - static const uint64_t INDEX_MAXIMUM_VALUE = (1 << INDEX_BITS); - static const uint64_t INDEX_MASK = (INDEX_MAXIMUM_VALUE - 1); - static const size_t LENGTH_OFFSET = NUMBER_BITS + INDEX_BITS; - static const size_t LENGTH_BITS = 16; - static const uint64_t LENGTH_MAXIMUM_VALUE = (1 << LENGTH_BITS); - static const uint64_t LENGTH_MASK = (LENGTH_MAXIMUM_VALUE - 1); - - /* extract a epoch */ - uint64_t a_epoch = (a >> NUMBER_OFFSET) & NUMBER_MASK; - uint64_t a_index = (a >> INDEX_OFFSET) & INDEX_MASK; - uint64_t a_len = (a >> LENGTH_OFFSET) & LENGTH_MASK; - - /* extract b epoch */ - uint64_t b_epoch = (b >> NUMBER_OFFSET) & NUMBER_MASK; - uint64_t b_index = (b >> INDEX_OFFSET) & INDEX_MASK; - uint64_t b_len = (b >> LENGTH_OFFSET) & LENGTH_MASK; - - if (a_epoch < b_epoch) { - return -1; - } else if (a_epoch > b_epoch) { - return 1; - } else { - /* a and b is in the same epoch, - compare a_index / a_len <=> b_index / b_len - */ - uint64_t a_block = a_index * b_len; - uint64_t b_block = b_index * a_len; - /* compare block */ - if (a_block < b_block) { - return -1; - } else if (a_block > b_block) { - return 1; - } else { - return 0; - } - } -} - -#define CKB_SINCE_VALUE_BITS 56 -#define CKB_SINCE_VALUE_MASK 0x00ffffffffffffff -#define CKB_SINCE_FLAG_METRIC_MASK 0b01100000 -#define CKB_SINCE_EPOCH_FRACTION_FLAG 0b00100000 - -/* - * Compare since, comparable is set to 1 when the - * a and b since values have the same flags, otherwise comparable is set to 0. - * - * Return value only has meaning when the comparable is set to 1: - * return 0 if a is equals to b, - * return -1 if a is less than b, - * return 1 if a is greater than b - */ -int ckb_since_cmp(uint64_t a, uint64_t b, int *comparable) { - uint8_t a_flag = a >> CKB_SINCE_VALUE_BITS; - uint8_t b_flag = b >> CKB_SINCE_VALUE_BITS; - if (a_flag != b_flag) { - *comparable = 0; - return 0; - } - *comparable = 1; - if ((a_flag & CKB_SINCE_FLAG_METRIC_MASK) == CKB_SINCE_EPOCH_FRACTION_FLAG) { - return ckb_epoch_number_with_fraction_cmp(a, b); - } else { - uint64_t a_value = a & CKB_SINCE_VALUE_MASK; - uint64_t b_value = b & CKB_SINCE_VALUE_MASK; - if (a_value < b_value) { - return -1; - } else if (a_value > b_value) { - return 1; - } else { - return 0; - } - } -} - -/* - * A temporal patch to solve https://github.com/nervosnetwork/ckb-vm/issues/97. - * If you use a ckb-vm >= 0.20.x, you can safely ignore it. A common practice - * is that use CKB_SP_ALIGN in the first line of the main(), and then use - * CKB_SP_ALIGN_END before exiting. - * - * Example: - * int main() { - * CKB_SP_ALIGN; - * ... - * if cond { - * CKB_SP_ALIGN_END; - * return 1; - * } - * ... - * CKB_SP_ALIGN_END; - * return 0; - * } - */ -#define CKB_SP_ALIGN \ - __asm__( \ - "addi t0, sp, 0\n" \ - "andi sp, sp, 0xfffffffffffffff8\n" \ - "sd t0, -8(sp)\n" \ - "sd t0, -16(sp)\n" \ - "addi sp, sp, -8\n" \ - "andi sp, sp, 0xfffffffffffffff0" \ - : \ - : \ - : "t0") -#define CKB_SP_ALIGN_END __asm__("ld sp, 0(sp)") - -#endif /* CKB_C_STDLIB_CKB_UTILS_H_ */ diff --git a/include/ckb-c-stdlib/libc/ctype.h b/include/ckb-c-stdlib/libc/ctype.h deleted file mode 100644 index 7a68770..0000000 --- a/include/ckb-c-stdlib/libc/ctype.h +++ /dev/null @@ -1,5 +0,0 @@ -int islower(int); -int isupper(int); - -int tolower(int); -int toupper(int); diff --git a/include/ckb-c-stdlib/libc/entry.h b/include/ckb-c-stdlib/libc/entry.h deleted file mode 100644 index 1b13464..0000000 --- a/include/ckb-c-stdlib/libc/entry.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CKB_C_STDLIB_ENTRY_H_ -#define CKB_C_STDLIB_ENTRY_H_ - -#ifndef CKB_DECLARATION_ONLY -#include "src/impl.c" - -#ifndef __SHARED_LIBRARY__ -__attribute__((visibility("default"))) __attribute__((naked)) void _start() { - asm volatile( - ".option push\n" - ".option norelax\n" -#ifndef CKB_NO_ENTRY_GP - "1:auipc gp, %pcrel_hi(__global_pointer$)\n" - "addi gp, gp, %pcrel_lo(1b)\n" - ".option pop\n" -#endif - /* - * By default CKB VM initializes all memory to 0, there's no need - * to clear BSS segment again. - */ - "lw a0, 0(sp)\n" - "addi a1, sp, 8\n" - "li a2, 0\n" - "call main\n" - "li a7, 93\n" - "ecall"); -} -#endif /* __SHARED_LIBRARY__ */ -#endif /* CKB_DECLARATION_ONLY*/ - -#endif /* CKB_C_STDLIB_ENTRY_H_ */ diff --git a/include/ckb-c-stdlib/libc/features.h b/include/ckb-c-stdlib/libc/features.h deleted file mode 100644 index 85cfb72..0000000 --- a/include/ckb-c-stdlib/libc/features.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _FEATURES_H -#define _FEATURES_H - -#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) -#define _BSD_SOURCE 1 -#endif - -#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ - && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ - && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) -#define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 700 -#endif - -#if __STDC_VERSION__ >= 199901L -#define __restrict restrict -#elif !defined(__GNUC__) -#define __restrict -#endif - -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -#define __inline inline -#elif !defined(__GNUC__) -#define __inline -#endif - -#if __STDC_VERSION__ >= 201112L -#elif defined(__GNUC__) -#define _Noreturn __attribute__((__noreturn__)) -#else -#define _Noreturn -#endif - -#define __REDIR(x,y) __typeof__(x) x __asm__(#y) - -#endif diff --git a/include/ckb-c-stdlib/libc/internal/atomic.h b/include/ckb-c-stdlib/libc/internal/atomic.h deleted file mode 100644 index 6228043..0000000 --- a/include/ckb-c-stdlib/libc/internal/atomic.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef CKB_C_STDLIB_INTERNAL_ATOMIC_H_ -#define CKB_C_STDLIB_INTERNAL_ATOMIC_H_ -#include - -/* - * Modified from - * https://git.musl-libc.org/cgit/musl/tree/src/internal/atomic.h?id=33338ebc853d37c80f0f236cc7a92cb0acc6aace - */ -static inline int a_ctz_32(uint32_t x) { - static const char debruijn32[32] = { - 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, - 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14}; - return debruijn32[(x & -x) * 0x076be629 >> 27]; -} - -static inline int a_ctz_64(uint64_t x) { - static const char debruijn64[64] = { - 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, - 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, - 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, - 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12}; - if (sizeof(long) < 8) { - uint32_t y = x; - if (!y) { - y = x >> 32; - return 32 + a_ctz_32(y); - } - return a_ctz_32(y); - } - return debruijn64[(x & -x) * 0x022fdd63cc95386dull >> 58]; -} - -static inline int a_ctz_l(unsigned long x) { - return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x); -} - -#endif /* CKB_C_STDLIB_INTERNAL_ATOMIC_H_ */ diff --git a/include/ckb-c-stdlib/libc/internal/types.h b/include/ckb-c-stdlib/libc/internal/types.h deleted file mode 100644 index 953003c..0000000 --- a/include/ckb-c-stdlib/libc/internal/types.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CKB_C_STDLIB_INTERNAL_TYPES_H_ -#define CKB_C_STDLIB_INTERNAL_TYPES_H_ - -typedef unsigned long size_t; -typedef signed long ssize_t; - -typedef unsigned long uintptr_t; -typedef signed long intptr_t; - -typedef unsigned char uint8_t; -typedef signed char int8_t; - -typedef unsigned short uint16_t; -typedef signed short int16_t; - -typedef unsigned int uint32_t; -typedef signed int int32_t; - -typedef unsigned long uint64_t; -typedef signed long int64_t; - -typedef signed long ptrdiff_t; - -#endif /* CKB_C_STDLIB_INTERNAL_TYPES_H_ */ diff --git a/include/ckb-c-stdlib/libc/limits.h b/include/ckb-c-stdlib/libc/limits.h deleted file mode 100644 index 258f6aa..0000000 --- a/include/ckb-c-stdlib/libc/limits.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef HEADER__LIBC_LIMITS_H_ -#define HEADER__LIBC_LIMITS_H_ 1 - -#ifdef _MB_LEN_MAX -#define MB_LEN_MAX _MB_LEN_MAX -#else -#define MB_LEN_MAX 1 -#endif - -/* Maximum number of positional arguments, if _WANT_IO_POS_ARGS. */ -#ifndef NL_ARGMAX -#define NL_ARGMAX 32 -#endif - -/* Number of bits in a `char'. */ -#undef CHAR_BIT -#define CHAR_BIT 8 - -/* Minimum and maximum values a `signed char' can hold. */ -#undef SCHAR_MIN -#define SCHAR_MIN (-128) -#undef SCHAR_MAX -#define SCHAR_MAX 127 - -/* Maximum value an `unsigned char' can hold. (Minimum is 0). */ -#undef UCHAR_MAX -#define UCHAR_MAX 255 - -/* Minimum and maximum values a `char' can hold. */ -#ifdef __CHAR_UNSIGNED__ -#undef CHAR_MIN -#define CHAR_MIN 0 -#undef CHAR_MAX -#define CHAR_MAX 255 -#else -#undef CHAR_MIN -#define CHAR_MIN (-128) -#undef CHAR_MAX -#define CHAR_MAX 127 -#endif - -/* Minimum and maximum values a `signed short int' can hold. */ -#undef SHRT_MIN -/* For the sake of 16 bit hosts, we may not use -32768 */ -#define SHRT_MIN (-32767 - 1) -#undef SHRT_MAX -#define SHRT_MAX 32767 - -/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */ -#undef USHRT_MAX -#define USHRT_MAX 65535 - -/* Minimum and maximum values a `signed int' can hold. */ -#ifndef __INT_MAX__ -#define __INT_MAX__ 2147483647 -#endif -#undef INT_MIN -#define INT_MIN (-INT_MAX - 1) -#undef INT_MAX -#define INT_MAX __INT_MAX__ - -/* Maximum value an `unsigned int' can hold. (Minimum is 0). */ -#undef UINT_MAX -#define UINT_MAX (INT_MAX * 2U + 1) - -/* Minimum and maximum values a `signed long int' can hold. - (Same as `int'). */ -#ifndef __LONG_MAX__ -#if defined(__alpha__) || (defined(__sparc__) && defined(__arch64__)) || \ - defined(__sparcv9) -#define __LONG_MAX__ 9223372036854775807L -#else -#define __LONG_MAX__ 2147483647L -#endif /* __alpha__ || sparc64 */ -#endif -#undef LONG_MIN -#define LONG_MIN (-LONG_MAX - 1) -#undef LONG_MAX -#define LONG_MAX __LONG_MAX__ - -/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ -#undef ULONG_MAX -#define ULONG_MAX (LONG_MAX * 2UL + 1) - -#ifndef __LONG_LONG_MAX__ -#define __LONG_LONG_MAX__ 9223372036854775807LL -#endif - -#if __ISO_C_VISIBLE >= 1999 -/* Minimum and maximum values a `signed long long int' can hold. */ -#undef LLONG_MIN -#define LLONG_MIN (-LLONG_MAX - 1) -#undef LLONG_MAX -#define LLONG_MAX __LONG_LONG_MAX__ - -/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ -#undef ULLONG_MAX -#define ULLONG_MAX (LLONG_MAX * 2ULL + 1) -#endif - -#if __GNU_VISIBLE -/* Minimum and maximum values a `signed long long int' can hold. */ -#undef LONG_LONG_MIN -#define LONG_LONG_MIN (-LONG_LONG_MAX - 1) -#undef LONG_LONG_MAX -#define LONG_LONG_MAX __LONG_LONG_MAX__ - -/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ -#undef ULONG_LONG_MAX -#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1) -#endif - -#endif /* _LIBC_LIMITS_H_ */ - -#ifndef _POSIX2_RE_DUP_MAX -/* The maximum number of repeated occurrences of a regular expression - * permitted when using the interval notation `\{M,N\}'. */ -#define _POSIX2_RE_DUP_MAX 255 -#endif /* _POSIX2_RE_DUP_MAX */ - -#ifndef ARG_MAX -#define ARG_MAX 4096 -#endif - -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif diff --git a/include/ckb-c-stdlib/libc/locale.h b/include/ckb-c-stdlib/libc/locale.h deleted file mode 100644 index 6cf5e32..0000000 --- a/include/ckb-c-stdlib/libc/locale.h +++ /dev/null @@ -1,29 +0,0 @@ -struct lconv { - char *decimal_point; - char *thousands_sep; - char *grouping; - - char *int_curr_symbol; - char *currency_symbol; - char *mon_decimal_point; - char *mon_thousands_sep; - char *mon_grouping; - char *positive_sign; - char *negative_sign; - char int_frac_digits; - char frac_digits; - char p_cs_precedes; - char p_sep_by_space; - char n_cs_precedes; - char n_sep_by_space; - char p_sign_posn; - char n_sign_posn; - char int_p_cs_precedes; - char int_p_sep_by_space; - char int_n_cs_precedes; - char int_n_sep_by_space; - char int_p_sign_posn; - char int_n_sign_posn; -}; - -struct lconv *localeconv(void); diff --git a/include/ckb-c-stdlib/libc/math.h b/include/ckb-c-stdlib/libc/math.h deleted file mode 100644 index 738961f..0000000 --- a/include/ckb-c-stdlib/libc/math.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _MATH_H -#define _MATH_H - -#define DBL_MAX 1.79769313486231570815e+308 - -#ifdef __cplusplus -extern "C" { -#endif - -/* fp_force_eval ensures that the input value is computed when that's - otherwise unused. To prevent the constant folding of the input - expression, an additional fp_barrier may be needed or a compilation - mode that does so (e.g. -frounding-math in gcc). Then it can be - used to evaluate an expression for its fenv side-effects only. */ - -#ifndef fp_force_evalf -#define fp_force_evalf fp_force_evalf -static inline void fp_force_evalf(float x) -{ - volatile float y; - y = x; - (void)y; -} -#endif - -#ifndef fp_force_eval -#define fp_force_eval fp_force_eval -static inline void fp_force_eval(double x) -{ - volatile double y; - y = x; - (void)y; -} -#endif - -#ifndef fp_force_evall -#define fp_force_evall fp_force_evall -static inline void fp_force_evall(long double x) -{ - volatile long double y; - y = x; - (void)y; -} -#endif - -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - fp_force_evalf(x); \ - } else if (sizeof(x) == sizeof(double)) { \ - fp_force_eval(x); \ - } else { \ - fp_force_evall(x); \ - } \ -} while(0) - -double fmod(double, double); -double frexp(double, int *); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/ckb-c-stdlib/libc/memory.h b/include/ckb-c-stdlib/libc/memory.h deleted file mode 100644 index 13b49b6..0000000 --- a/include/ckb-c-stdlib/libc/memory.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include diff --git a/include/ckb-c-stdlib/libc/setjmp.h b/include/ckb-c-stdlib/libc/setjmp.h deleted file mode 100644 index 3a80991..0000000 --- a/include/ckb-c-stdlib/libc/setjmp.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _SETJMP_H -#define _SETJMP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef unsigned long __jmp_buf[26]; - -typedef struct __jmp_buf_tag { - __jmp_buf __jb; - unsigned long __fl; - unsigned long __ss[128 / sizeof(long)]; -} jmp_buf[1]; - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) -#define __setjmp_attr __attribute__((__returns_twice__)) -#else -#define __setjmp_attr -#endif - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \ - defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -typedef jmp_buf sigjmp_buf; -int sigsetjmp(sigjmp_buf, int) __setjmp_attr; -_Noreturn void siglongjmp(sigjmp_buf, int); -#endif - -int _setjmp(jmp_buf) __setjmp_attr; - -_Noreturn void _longjmp(jmp_buf, int); - -int setjmp(jmp_buf) __setjmp_attr; -_Noreturn void longjmp(jmp_buf, int); - -#define setjmp setjmp - -#undef __setjmp_attr - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/ckb-c-stdlib/libc/src/errno.h b/include/ckb-c-stdlib/libc/src/errno.h deleted file mode 100644 index 6306e15..0000000 --- a/include/ckb-c-stdlib/libc/src/errno.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _ERRNO_H -#define _ERRNO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -__attribute__((const)) -#endif -int *__errno_location(void); -#define errno (*__errno_location()) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/ckb-c-stdlib/libc/src/impl.c b/include/ckb-c-stdlib/libc/src/impl.c deleted file mode 100644 index deeb2c7..0000000 --- a/include/ckb-c-stdlib/libc/src/impl.c +++ /dev/null @@ -1,2454 +0,0 @@ -// -// If you have only one single C file, you can include std header files in it, -// and then done. It automatically includes impl.c(this file). It is compatible -// to a lot of old CKB code. -// -// If you have more than one C file, and it's a big project. You need to define -// macro CKB_DECLARATION_ONLY for every C files. Compile very C file, together -// with this impl.c (compiled *without* macro CKB_DECLARATION_ONLY) and then -// link them together. -// - -#ifndef __CKB_IMPL_INCLUDED__ -#define __CKB_IMPL_INCLUDED__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The implementation here is based on musl-libc with modifications for our - * use case. The original musl-libc follows MIT license, thanks to the authors - * for the creation. - */ - -void *memset(void *dest, int c, size_t n) { - unsigned char *s = dest; -#ifndef __OPTIMIZE_SIZE__ - size_t k; - - /* Fill head and tail with minimal branching. Each - * conditional ensures that all the subsequently used - * offsets are well-defined and in the dest region. */ - - if (!n) - return dest; - s[0] = c; - s[n - 1] = c; - if (n <= 2) - return dest; - s[1] = c; - s[2] = c; - s[n - 2] = c; - s[n - 3] = c; - if (n <= 6) - return dest; - s[3] = c; - s[n - 4] = c; - if (n <= 8) - return dest; - - /* Advance pointer to align it at a 4-byte boundary, - * and truncate n to a multiple of 4. The previous code - * already took care of any head/tail that get cut off - * by the alignment. */ - - k = -(uintptr_t)s & 3; - s += k; - n -= k; - n &= -4; - -#ifdef __GNUC__ - typedef uint32_t __attribute__((__may_alias__)) u32; - typedef uint64_t __attribute__((__may_alias__)) u64; - - u32 c32 = ((u32)-1) / 255 * (unsigned char)c; - - /* In preparation to copy 32 bytes at a time, aligned on - * an 8-byte bounary, fill head/tail up to 28 bytes each. - * As in the initial byte-based head/tail fill, each - * conditional below ensures that the subsequent offsets - * are valid (e.g. !(n<=24) implies n>=28). */ - - *(u32 *)(s + 0) = c32; - *(u32 *)(s + n - 4) = c32; - if (n <= 8) - return dest; - *(u32 *)(s + 4) = c32; - *(u32 *)(s + 8) = c32; - *(u32 *)(s + n - 12) = c32; - *(u32 *)(s + n - 8) = c32; - if (n <= 24) - return dest; - *(u32 *)(s + 12) = c32; - *(u32 *)(s + 16) = c32; - *(u32 *)(s + 20) = c32; - *(u32 *)(s + 24) = c32; - *(u32 *)(s + n - 28) = c32; - *(u32 *)(s + n - 24) = c32; - *(u32 *)(s + n - 20) = c32; - *(u32 *)(s + n - 16) = c32; - - /* Align to a multiple of 8 so we can fill 64 bits at a time, - * and avoid writing the same bytes twice as much as is - * practical without introducing additional branching. */ - - k = 24 + ((uintptr_t)s & 4); - s += k; - n -= k; - - /* If this loop is reached, 28 tail bytes have already been - * filled, so any remainder when n drops below 32 can be - * safely ignored. */ - - u64 c64 = c32 | ((u64)c32 << 32); - for (; n >= 32; n -= 32, s += 32) { - *(u64 *)(s + 0) = c64; - *(u64 *)(s + 8) = c64; - *(u64 *)(s + 16) = c64; - *(u64 *)(s + 24) = c64; - } -#else - /* Pure C fallback with no aliasing violations. */ - for (; n; n--, s++) - *s = c; -#endif - -#else - for (; n; n--, s++) - *s = c; -#endif /* __OPTIMIZE_SIZE__ */ - - return dest; -} - -void *memcpy(void *restrict dest, const void *restrict src, size_t n) { - unsigned char *d = dest; - const unsigned char *s = src; - -#if defined(__GNUC__) && (!defined(__OPTIMIZE_SIZE__)) - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define LS >> -#define RS << -#else -#define LS << -#define RS >> -#endif - - typedef uint32_t __attribute__((__may_alias__)) u32; - uint32_t w, x; - - for (; (uintptr_t)s % 4 && n; n--) - *d++ = *s++; - - if ((uintptr_t)d % 4 == 0) { - for (; n >= 16; s += 16, d += 16, n -= 16) { - *(u32 *)(d + 0) = *(u32 *)(s + 0); - *(u32 *)(d + 4) = *(u32 *)(s + 4); - *(u32 *)(d + 8) = *(u32 *)(s + 8); - *(u32 *)(d + 12) = *(u32 *)(s + 12); - } - if (n & 8) { - *(u32 *)(d + 0) = *(u32 *)(s + 0); - - *(u32 *)(d + 4) = *(u32 *)(s + 4); - d += 8; - s += 8; - } - if (n & 4) { - *(u32 *)(d + 0) = *(u32 *)(s + 0); - d += 4; - s += 4; - } - if (n & 2) { - *d++ = *s++; - *d++ = *s++; - } - if (n & 1) { - *d = *s; - } - return dest; - } - - if (n >= 32) - switch ((uintptr_t)d % 4) { - case 1: - w = *(u32 *)s; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - n -= 3; - for (; n >= 17; s += 16, d += 16, n -= 16) { - x = *(u32 *)(s + 1); - *(u32 *)(d + 0) = (w LS 24) | (x RS 8); - w = *(u32 *)(s + 5); - *(u32 *)(d + 4) = (x LS 24) | (w RS 8); - x = *(u32 *)(s + 9); - *(u32 *)(d + 8) = (w LS 24) | (x RS 8); - w = *(u32 *)(s + 13); - *(u32 *)(d + 12) = (x LS 24) | (w RS 8); - } - break; - case 2: - w = *(u32 *)s; - *d++ = *s++; - *d++ = *s++; - n -= 2; - for (; n >= 18; s += 16, d += 16, n -= 16) { - x = *(u32 *)(s + 2); - *(u32 *)(d + 0) = (w LS 16) | (x RS 16); - w = *(u32 *)(s + 6); - *(u32 *)(d + 4) = (x LS 16) | (w RS 16); - x = *(u32 *)(s + 10); - *(u32 *)(d + 8) = (w LS 16) | (x RS 16); - w = *(u32 *)(s + 14); - *(u32 *)(d + 12) = (x LS 16) | (w RS 16); - } - break; - case 3: - w = *(u32 *)s; - *d++ = *s++; - n -= 1; - for (; n >= 19; s += 16, d += 16, n -= 16) { - x = *(u32 *)(s + 3); - *(u32 *)(d + 0) = (w LS 8) | (x RS 24); - w = *(u32 *)(s + 7); - *(u32 *)(d + 4) = (x LS 8) | (w RS 24); - x = *(u32 *)(s + 11); - *(u32 *)(d + 8) = (w LS 8) | (x RS 24); - w = *(u32 *)(s + 15); - *(u32 *)(d + 12) = (x LS 8) | (w RS 24); - } - break; - } - if (n & 16) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - if (n & 8) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - if (n & 4) { - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - if (n & 2) { - *d++ = *s++; - *d++ = *s++; - } - if (n & 1) { - *d = *s; - } - return dest; -#endif - - for (; n; n--) - *d++ = *s++; - return dest; -} - -int memcmp(const void *vl, const void *vr, size_t n) { - const unsigned char *l = vl, *r = vr; - for (; n && *l == *r; n--, l++, r++) - ; - return n ? *l - *r : 0; -} - -#ifdef __GNUC__ -typedef __attribute__((__may_alias__)) size_t WT; -#define WS (sizeof(WT)) -#endif - -void *memmove(void *dest, const void *src, size_t n) { - char *d = dest; - const char *s = src; - - if (d == s) - return d; - if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n) - return memcpy(d, s, n); - - if (d < s) { -#ifdef __GNUC__ - if ((uintptr_t)s % WS == (uintptr_t)d % WS) { - while ((uintptr_t)d % WS) { - if (!n--) - return dest; - *d++ = *s++; - } - for (; n >= WS; n -= WS, d += WS, s += WS) - *(WT *)d = *(WT *)s; - } -#endif - for (; n; n--) - *d++ = *s++; - } else { -#ifdef __GNUC__ - if ((uintptr_t)s % WS == (uintptr_t)d % WS) { - while ((uintptr_t)(d + n) % WS) { - if (!n--) - return dest; - d[n] = s[n]; - } - while (n >= WS) - n -= WS, *(WT *)(d + n) = *(WT *)(s + n); - } -#endif - while (n) - n--, d[n] = s[n]; - } - - return dest; -} - -#define CKB_SS (sizeof(size_t)) -#define CKB_ALIGN (sizeof(size_t) - 1) -#define CKB_ONES ((size_t)-1 / UCHAR_MAX) -#define CKB_HIGHS (CKB_ONES * (UCHAR_MAX / 2 + 1)) -#define CKB_HASZERO(x) (((x)-CKB_ONES) & ~(x)&CKB_HIGHS) - -void *memchr(const void *src, int c, size_t n) { - const unsigned char *s = src; - c = (unsigned char)c; -#ifdef __GNUC__ - for (; ((uintptr_t)s & CKB_ALIGN) && n && *s != c; s++, n--) - ; - if (n && *s != c) { - typedef size_t __attribute__((__may_alias__)) word; - const word *w; - size_t k = CKB_ONES * c; - for (w = (const void *)s; n >= CKB_SS && !CKB_HASZERO(*w ^ k); - w++, n -= CKB_SS) - ; - s = (const void *)w; - } -#endif - for (; n && *s != c; s++, n--) - ; - return n ? (void *)s : 0; -} - -#define BITOP(a, b, op) \ - ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ - << ((size_t)(b) % (8 * sizeof *(a)))) - -char *strcpy(char *restrict d, const char *restrict s) { - char *dest = d; - for (; (*d = *s); s++, d++) - ; - return dest; -} - -size_t strlen(const char *s) { - const char *a = s; - for (; *s; s++) - ; - return s - a; -} - -int strcmp(const char *l, const char *r) { - for (; *l == *r && *l; l++, r++) - ; - return *(unsigned char *)l - *(unsigned char *)r; -} - -char *__strchrnul(const char *s, int c) { - c = (unsigned char)c; - if (!c) - return (char *)s + strlen(s); - - for (; *s && *(unsigned char *)s != c; s++) - ; - return (char *)s; -} - -char *strchr(const char *s, int c) { - char *r = __strchrnul(s, c); - return *(unsigned char *)r == (unsigned char)c ? r : 0; -} - -int strncmp(const char *_l, const char *_r, size_t n) { - const unsigned char *l = (void *)_l, *r = (void *)_r; - if (!n--) - return 0; - for (; *l && *r && n && *l == *r; l++, r++, n--) - ; - return *l - *r; -} - -size_t strspn(const char *s, const char *c) { - const char *a = s; - size_t byteset[32 / sizeof(size_t)] = {0}; - - if (!c[0]) - return 0; - if (!c[1]) { - for (; *s == *c; s++) - ; - return s - a; - } - - for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) - ; - for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++) - ; - return s - a; -} - -size_t strcspn(const char *s, const char *c) { - const char *a = s; - size_t byteset[32 / sizeof(size_t)]; - - if (!c[0] || !c[1]) - return __strchrnul(s, *c) - a; - - memset(byteset, 0, sizeof byteset); - for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) - ; - for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++) - ; - return s - a; -} - -char *strpbrk(const char *s, const char *b) { - s += strcspn(s, b); - return *s ? (char *)s : 0; -} - -static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) { - uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1]; - for (h++; *h && hw != nw; hw = hw << 8 | *++h) - ; - return *h ? (char *)h - 1 : 0; -} - -static char *threebyte_strstr(const unsigned char *h, const unsigned char *n) { - uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8; - uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8; - for (h += 2; *h && hw != nw; hw = (hw | *++h) << 8) - ; - return *h ? (char *)h - 2 : 0; -} - -static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n) { - uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; - uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3]; - for (h += 3; *h && hw != nw; hw = hw << 8 | *++h) - ; - return *h ? (char *)h - 3 : 0; -} - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#define BITOP(a, b, op) \ - ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ - << ((size_t)(b) % (8 * sizeof *(a)))) - -static char *twoway_strstr(const unsigned char *h, const unsigned char *n) { - const unsigned char *z; - size_t l, ip, jp, k, p, ms, p0, mem, mem0; - size_t byteset[32 / sizeof(size_t)] = {0}; - size_t shift[256]; - - /* Computing length of needle and fill shift table */ - for (l = 0; n[l] && h[l]; l++) - BITOP(byteset, n[l], |=), shift[n[l]] = l + 1; - if (n[l]) - return 0; /* hit the end of h */ - - /* Compute maximal suffix */ - ip = -1; - jp = 0; - k = p = 1; - while (jp + k < l) { - if (n[ip + k] == n[jp + k]) { - if (k == p) { - jp += p; - k = 1; - } else - k++; - } else if (n[ip + k] > n[jp + k]) { - jp += k; - k = 1; - p = jp - ip; - } else { - ip = jp++; - k = p = 1; - } - } - ms = ip; - p0 = p; - - /* And with the opposite comparison */ - ip = -1; - jp = 0; - k = p = 1; - while (jp + k < l) { - if (n[ip + k] == n[jp + k]) { - if (k == p) { - jp += p; - k = 1; - } else - k++; - } else if (n[ip + k] < n[jp + k]) { - jp += k; - k = 1; - p = jp - ip; - } else { - ip = jp++; - k = p = 1; - } - } - if (ip + 1 > ms + 1) - ms = ip; - else - p = p0; - - /* Periodic needle? */ - if (memcmp(n, n + p, ms + 1)) { - mem0 = 0; - p = MAX(ms, l - ms - 1) + 1; - } else - mem0 = l - p; - mem = 0; - - /* Initialize incremental end-of-haystack pointer */ - z = h; - - /* Search loop */ - for (;;) { - /* Update incremental end-of-haystack pointer */ - if (z - h < l) { - /* Fast estimate for MAX(l,63) */ - size_t grow = l | 63; - const unsigned char *z2 = memchr(z, 0, grow); - if (z2) { - z = z2; - if (z - h < l) - return 0; - } else - z += grow; - } - - /* Check last byte first; advance by shift on mismatch */ - if (BITOP(byteset, h[l - 1], &)) { - k = l - shift[h[l - 1]]; - if (k) { - if (k < mem) - k = mem; - h += k; - mem = 0; - continue; - } - } else { - h += l; - mem = 0; - continue; - } - - /* Compare right half */ - for (k = MAX(ms + 1, mem); n[k] && n[k] == h[k]; k++) - ; - if (n[k]) { - h += k - ms; - mem = 0; - continue; - } - /* Compare left half */ - for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--) - ; - if (k <= mem) - return (char *)h; - h += p; - mem = mem0; - } -} - -char *strstr(const char *h, const char *n) { - /* Return immediately on empty needle */ - if (!n[0]) - return (char *)h; - - /* Use faster algorithms for short needles */ - h = strchr(h, *n); - if (!h || !n[1]) - return (char *)h; - if (!h[1]) - return 0; - if (!n[2]) - return twobyte_strstr((void *)h, (void *)n); - if (!h[2]) - return 0; - if (!n[3]) - return threebyte_strstr((void *)h, (void *)n); - if (!h[3]) - return 0; - if (!n[4]) - return fourbyte_strstr((void *)h, (void *)n); - - return twoway_strstr((void *)h, (void *)n); -} - -static const struct lconv posix_lconv = { - .decimal_point = ".", - .thousands_sep = "", - .grouping = "", - .int_curr_symbol = "", - .currency_symbol = "", - .mon_decimal_point = "", - .mon_thousands_sep = "", - .mon_grouping = "", - .positive_sign = "", - .negative_sign = "", - .int_frac_digits = CHAR_MAX, - .frac_digits = CHAR_MAX, - .p_cs_precedes = CHAR_MAX, - .p_sep_by_space = CHAR_MAX, - .n_cs_precedes = CHAR_MAX, - .n_sep_by_space = CHAR_MAX, - .p_sign_posn = CHAR_MAX, - .n_sign_posn = CHAR_MAX, - .int_p_cs_precedes = CHAR_MAX, - .int_p_sep_by_space = CHAR_MAX, - .int_n_cs_precedes = CHAR_MAX, - .int_n_sep_by_space = CHAR_MAX, - .int_p_sign_posn = CHAR_MAX, - .int_n_sign_posn = CHAR_MAX, -}; - -struct lconv *localeconv(void) { - return (void *)&posix_lconv; -} - -#ifdef CKB_C_STDLIB_MALLOC -#include "malloc_impl.h" -#else -void *malloc(size_t size) { return NULL; } -void free(void *ptr) {} -void *calloc(size_t nmemb, size_t size) { return NULL; } -void *realloc(void *ptr, size_t size) { return NULL; } -#endif - -/* - * qsort implementation below is modified from - * https://git.musl-libc.org/cgit/musl/tree/src/stdlib/qsort.c?id=33338ebc853d37c80f0f236cc7a92cb0acc6aace - */ -/* Copyright (C) 2011 by Valentin Ochs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */ - -/* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1). - Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */ - -#define ntz(x) a_ctz_l((x)) - -typedef int (*cmpfun)(const void *, const void *); - -static inline int pntz(size_t p[2]) { - int r = ntz(p[0] - 1); - if (r != 0 || (r = 8 * sizeof(size_t) + ntz(p[1])) != 8 * sizeof(size_t)) { - return r; - } - return 0; -} - -static void cycle(size_t width, unsigned char *ar[], int n) { - unsigned char tmp[256]; - size_t l; - int i; - - if (n < 2) { - return; - } - - ar[n] = tmp; - while (width) { - l = sizeof(tmp) < width ? sizeof(tmp) : width; - memcpy(ar[n], ar[0], l); - for (i = 0; i < n; i++) { - memcpy(ar[i], ar[i + 1], l); - ar[i] += l; - } - width -= l; - } -} - -/* shl() and shr() need n > 0 */ -static inline void shl(size_t p[2], int n) { - if (n >= (int)(8 * sizeof(size_t))) { - n -= 8 * sizeof(size_t); - p[1] = p[0]; - p[0] = 0; - } - p[1] <<= n; - p[1] |= p[0] >> (sizeof(size_t) * 8 - n); - p[0] <<= n; -} - -static inline void shr(size_t p[2], int n) { - if (n >= (int)(8 * sizeof(size_t))) { - n -= 8 * sizeof(size_t); - p[0] = p[1]; - p[1] = 0; - } - p[0] >>= n; - p[0] |= p[1] << (sizeof(size_t) * 8 - n); - p[1] >>= n; -} - -static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, - size_t lp[]) { - unsigned char *rt, *lf; - unsigned char *ar[14 * sizeof(size_t) + 1]; - int i = 1; - - ar[0] = head; - while (pshift > 1) { - rt = head - width; - lf = head - width - lp[pshift - 2]; - - if ((*cmp)(ar[0], lf) >= 0 && (*cmp)(ar[0], rt) >= 0) { - break; - } - if ((*cmp)(lf, rt) >= 0) { - ar[i++] = lf; - head = lf; - pshift -= 1; - } else { - ar[i++] = rt; - head = rt; - pshift -= 2; - } - } - cycle(width, ar, i); -} - -static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], - int pshift, int trusty, size_t lp[]) { - unsigned char *stepson, *rt, *lf; - size_t p[2]; - unsigned char *ar[14 * sizeof(size_t) + 1]; - int i = 1; - int trail; - - p[0] = pp[0]; - p[1] = pp[1]; - - ar[0] = head; - while (p[0] != 1 || p[1] != 0) { - stepson = head - lp[pshift]; - if ((*cmp)(stepson, ar[0]) <= 0) { - break; - } - if (!trusty && pshift > 1) { - rt = head - width; - lf = head - width - lp[pshift - 2]; - if ((*cmp)(rt, stepson) >= 0 || (*cmp)(lf, stepson) >= 0) { - break; - } - } - - ar[i++] = stepson; - head = stepson; - trail = pntz(p); - shr(p, trail); - pshift += trail; - trusty = 0; - } - if (!trusty) { - cycle(width, ar, i); - sift(head, width, cmp, pshift, lp); - } -} - -void qsort(void *base, size_t nel, size_t width, cmpfun cmp) { - size_t lp[12 * sizeof(size_t)]; - size_t i, size = width * nel; - unsigned char *head, *high; - size_t p[2] = {1, 0}; - int pshift = 1; - int trail; - - if (!size) - return; - - head = base; - high = head + size - width; - - /* Precompute Leonardo numbers, scaled by element width */ - for (lp[0] = lp[1] = width, i = 2; - (lp[i] = lp[i - 2] + lp[i - 1] + width) < size; i++) - ; - - while (head < high) { - if ((p[0] & 3) == 3) { - sift(head, width, cmp, pshift, lp); - shr(p, 2); - pshift += 2; - } else { - if (lp[pshift - 1] >= (size_t)(high - head)) { - trinkle(head, width, cmp, p, pshift, 0, lp); - } else { - sift(head, width, cmp, pshift, lp); - } - - if (pshift == 1) { - shl(p, 1); - pshift = 0; - } else { - shl(p, pshift - 1); - pshift = 1; - } - } - - p[0] |= 1; - head += width; - } - - trinkle(head, width, cmp, p, pshift, 0, lp); - - while (pshift != 1 || p[0] != 1 || p[1] != 0) { - if (pshift <= 1) { - trail = pntz(p); - shr(p, trail); - pshift += trail; - } else { - shl(p, 2); - pshift -= 2; - p[0] ^= 7; - shr(p, 1); - trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp); - shl(p, 1); - p[0] |= 1; - trinkle(head - width, width, cmp, p, pshift, 1, lp); - } - head -= width; - } -} - -// bsearch implementation below is modified from -// http://git.musl-libc.org/cgit/musl/tree/src/stdlib/bsearch.c -void *bsearch(const void *key, const void *base, size_t nel, size_t width, - int (*cmp)(const void *, const void *)) { - void *try_v; - int sign; - while (nel > 0) { - try_v = (char *)base + width * (nel / 2); - sign = cmp(key, try_v); - if (sign < 0) { - nel /= 2; - } else if (sign > 0) { - base = (char *)try_v + width; - nel -= nel / 2 + 1; - } else { - return try_v; - } - } - return NULL; -} - -// printf, pass -D CKB_C_STDLIB_PRINTF to enable printf -// default: disabled -#ifdef CKB_C_STDLIB_PRINTF - -// Default PRINTF_BUFFER_SIZE -#ifndef CKB_C_STDLIB_PRINTF_BUFFER_SIZE -#define CKB_C_STDLIB_PRINTF_BUFFER_SIZE 256 -#endif - -// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the -// printf_config.h header file -// default: undefined -#ifdef PRINTF_INCLUDE_CONFIG_H -#include "printf_config.h" -#endif - -// 'ntoa' conversion buffer size, this must be big enough to hold one converted -// numeric number including padded zeros (dynamically created on stack) -// default: 32 byte -#ifndef PRINTF_NTOA_BUFFER_SIZE -#define PRINTF_NTOA_BUFFER_SIZE 32U -#endif - -// 'ftoa' conversion buffer size, this must be big enough to hold one converted -// float number including padded zeros (dynamically created on stack) -// default: 32 byte -#ifndef PRINTF_FTOA_BUFFER_SIZE -#define PRINTF_FTOA_BUFFER_SIZE 32U -#endif - -// support for the floating point type (%f) -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_FLOAT -#define PRINTF_SUPPORT_FLOAT -#endif - -// support for exponential floating point notation (%e/%g) -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL -#define PRINTF_SUPPORT_EXPONENTIAL -#endif - -// define the default floating point precision -// default: 6 digits -#ifndef PRINTF_DEFAULT_FLOAT_PRECISION -#define PRINTF_DEFAULT_FLOAT_PRECISION 6U -#endif - -// define the largest float suitable to print with %f -// default: 1e9 -#ifndef PRINTF_MAX_FLOAT -#define PRINTF_MAX_FLOAT 1e9 -#endif - -// support for the long long types (%llu or %p) -// default: activated -#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG -#define PRINTF_SUPPORT_LONG_LONG -#endif - -// support for the ptrdiff_t type (%t) -// ptrdiff_t is normally defined in as long or long long type -// default: disabled -#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T -#endif - -/////////////////////////////////////////////////////////////////////////////// - -// internal flag definitions -#define FLAGS_ZEROPAD (1U << 0U) -#define FLAGS_LEFT (1U << 1U) -#define FLAGS_PLUS (1U << 2U) -#define FLAGS_SPACE (1U << 3U) -#define FLAGS_HASH (1U << 4U) -#define FLAGS_UPPERCASE (1U << 5U) -#define FLAGS_CHAR (1U << 6U) -#define FLAGS_SHORT (1U << 7U) -#define FLAGS_LONG (1U << 8U) -#define FLAGS_LONG_LONG (1U << 9U) -#define FLAGS_PRECISION (1U << 10U) -#define FLAGS_ADAPT_EXP (1U << 11U) - -// output function type -typedef void (*out_fct_type)(char character, void *buffer, size_t idx, - size_t maxlen); - -// wrapper (used as buffer) for output function type -typedef struct { - void (*fct)(char character, void *arg); - void *arg; -} out_fct_wrap_type; - -// internal buffer output -static inline void _out_buffer(char character, void *buffer, size_t idx, - size_t maxlen) { - if (idx < maxlen) { - ((char *)buffer)[idx] = character; - } -} - -// internal null output -static inline void _out_null(char character, void *buffer, size_t idx, - size_t maxlen) { - (void)character; - (void)buffer; - (void)idx; - (void)maxlen; -} - -// internal output function wrapper -static inline void _out_fct(char character, void *buffer, size_t idx, - size_t maxlen) { - (void)idx; - (void)maxlen; - if (character) { - // buffer is the output fct pointer - ((out_fct_wrap_type *)buffer) - ->fct(character, ((out_fct_wrap_type *)buffer)->arg); - } -} - -// internal secure strlen -// \return The length of the string (excluding the terminating 0) limited by -// 'maxsize' -static inline unsigned int _strnlen_s(const char *str, size_t maxsize) { - const char *s; - for (s = str; *s && maxsize--; ++s) - ; - return (unsigned int)(s - str); -} - -// internal test if char is a digit (0-9) -// \return true if char is a digit -static inline bool _is_digit(char ch) { return (ch >= '0') && (ch <= '9'); } - -// internal ASCII string to unsigned int conversion -static unsigned int _atoi(const char **str) { - unsigned int i = 0U; - while (_is_digit(**str)) { - i = i * 10U + (unsigned int)(*((*str)++) - '0'); - } - return i; -} - -// output the specified string in reverse, taking care of any zero-padding -static size_t _out_rev(out_fct_type out, char *buffer, size_t idx, - size_t maxlen, const char *buf, size_t len, - unsigned int width, unsigned int flags) { - const size_t start_idx = idx; - - // pad spaces up to given width - if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { - for (size_t i = len; i < width; i++) { - out(' ', buffer, idx++, maxlen); - } - } - - // reverse string - while (len) { - out(buf[--len], buffer, idx++, maxlen); - } - - // append pad spaces up to given width - if (flags & FLAGS_LEFT) { - while (idx - start_idx < width) { - out(' ', buffer, idx++, maxlen); - } - } - - return idx; -} - -// internal itoa format -static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx, - size_t maxlen, char *buf, size_t len, bool negative, - unsigned int base, unsigned int prec, - unsigned int width, unsigned int flags) { - // pad leading zeros - if (!(flags & FLAGS_LEFT)) { - if (width && (flags & FLAGS_ZEROPAD) && - (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { - width--; - } - while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - while ((flags & FLAGS_ZEROPAD) && (len < width) && - (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - } - - // handle hash - if (flags & FLAGS_HASH) { - if (!(flags & FLAGS_PRECISION) && len && - ((len == prec) || (len == width))) { - len--; - if (len && (base == 16U)) { - len--; - } - } - if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && - (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'x'; - } else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && - (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'X'; - } else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { - buf[len++] = 'b'; - } - if (len < PRINTF_NTOA_BUFFER_SIZE) { - buf[len++] = '0'; - } - } - - if (len < PRINTF_NTOA_BUFFER_SIZE) { - if (negative) { - buf[len++] = '-'; - } else if (flags & FLAGS_PLUS) { - buf[len++] = '+'; // ignore the space if the '+' exists - } else if (flags & FLAGS_SPACE) { - buf[len++] = ' '; - } - } - - return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); -} - -// internal itoa for 'long' type -static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, - size_t maxlen, unsigned long value, bool negative, - unsigned long base, unsigned int prec, - unsigned int width, unsigned int flags) { - char buf[PRINTF_NTOA_BUFFER_SIZE]; - size_t len = 0U; - - // no hash for 0 values - if (!value) { - flags &= ~FLAGS_HASH; - } - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { - do { - const char digit = (char)(value % base); - buf[len++] = digit < 10 - ? '0' + digit - : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= base; - } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); - } - - return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, - (unsigned int)base, prec, width, flags); -} - -// internal itoa for 'long long' type -#if defined(PRINTF_SUPPORT_LONG_LONG) -static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, - size_t maxlen, unsigned long long value, - bool negative, unsigned long long base, - unsigned int prec, unsigned int width, - unsigned int flags) { - char buf[PRINTF_NTOA_BUFFER_SIZE]; - size_t len = 0U; - - // no hash for 0 values - if (!value) { - flags &= ~FLAGS_HASH; - } - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { - do { - const char digit = (char)(value % base); - buf[len++] = digit < 10 - ? '0' + digit - : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; - value /= base; - } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); - } - - return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, - (unsigned int)base, prec, width, flags); -} -#endif // PRINTF_SUPPORT_LONG_LONG - -#if defined(PRINTF_SUPPORT_FLOAT) - -#if defined(PRINTF_SUPPORT_EXPONENTIAL) -// forward declaration so that _ftoa can switch to exp notation for values > -// PRINTF_MAX_FLOAT -static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, - double value, unsigned int prec, unsigned int width, - unsigned int flags); -#endif - -// internal ftoa for fixed decimal floating point -static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, - double value, unsigned int prec, unsigned int width, - unsigned int flags) { - char buf[PRINTF_FTOA_BUFFER_SIZE]; - size_t len = 0U; - double diff = 0.0; - - // powers of 10 - static const double pow10[] = {1, 10, 100, 1000, - 10000, 100000, 1000000, 10000000, - 100000000, 1000000000}; - - // test for special values - if (value != value) - return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); - if (value < -DBL_MAX) - return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); - if (value > DBL_MAX) - return _out_rev(out, buffer, idx, maxlen, - (flags & FLAGS_PLUS) ? "fni+" : "fni", - (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); - - // test for very large values - // standard printf behavior is to print EVERY whole number digit -- which - // could be 100s of characters overflowing your buffers == bad - if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { -#if defined(PRINTF_SUPPORT_EXPONENTIAL) - return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); -#else - return 0U; -#endif - } - - // test for negative - bool negative = false; - if (value < 0) { - negative = true; - value = 0 - value; - } - - // set default precision, if not set explicitly - if (!(flags & FLAGS_PRECISION)) { - prec = PRINTF_DEFAULT_FLOAT_PRECISION; - } - // limit precision to 9, cause a prec >= 10 can lead to overflow errors - while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { - buf[len++] = '0'; - prec--; - } - - int whole = (int)value; - double tmp = (value - whole) * pow10[prec]; - unsigned long frac = (unsigned long)tmp; - diff = tmp - frac; - - if (diff > 0.5) { - ++frac; - // handle rollover, e.g. case 0.99 with prec 1 is 1.0 - if (frac >= pow10[prec]) { - frac = 0; - ++whole; - } - } else if (diff < 0.5) { - } else if ((frac == 0U) || (frac & 1U)) { - // if halfway, round up if odd OR if last digit is 0 - ++frac; - } - - if (prec == 0U) { - diff = value - (double)whole; - if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { - // exactly 0.5 and ODD, then round up - // 1.5 -> 2, but 2.5 -> 2 - ++whole; - } - } else { - unsigned int count = prec; - // now do fractional part, as an unsigned number - while (len < PRINTF_FTOA_BUFFER_SIZE) { - --count; - buf[len++] = (char)(48U + (frac % 10U)); - if (!(frac /= 10U)) { - break; - } - } - // add extra 0s - while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { - buf[len++] = '0'; - } - if (len < PRINTF_FTOA_BUFFER_SIZE) { - // add decimal - buf[len++] = '.'; - } - } - - // do whole part, number is reversed - while (len < PRINTF_FTOA_BUFFER_SIZE) { - buf[len++] = (char)(48 + (whole % 10)); - if (!(whole /= 10)) { - break; - } - } - - // pad leading zeros - if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { - if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { - width--; - } - while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { - buf[len++] = '0'; - } - } - - if (len < PRINTF_FTOA_BUFFER_SIZE) { - if (negative) { - buf[len++] = '-'; - } else if (flags & FLAGS_PLUS) { - buf[len++] = '+'; // ignore the space if the '+' exists - } else if (flags & FLAGS_SPACE) { - buf[len++] = ' '; - } - } - - return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); -} - -#if defined(PRINTF_SUPPORT_EXPONENTIAL) -// internal ftoa variant for exponential floating-point type, contributed by -// Martijn Jasperse -static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, - double value, unsigned int prec, unsigned int width, - unsigned int flags) { - // check for NaN and special values - if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { - return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); - } - - // determine the sign - const bool negative = value < 0; - if (negative) { - value = -value; - } - - // default precision - if (!(flags & FLAGS_PRECISION)) { - prec = PRINTF_DEFAULT_FLOAT_PRECISION; - } - - // determine the decimal exponent - // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) - union { - uint64_t U; - double F; - } conv; - - conv.F = value; - int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 - conv.U = (conv.U & ((1ULL << 52U) - 1U)) | - (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) - // now approximate log10 from the log2 integer part and an expansion of ln - // around 1.5 - int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + - (conv.F - 1.5) * 0.289529654602168); - // now we want to compute 10^expval but we want to be sure it won't overflow - exp2 = (int)(expval * 3.321928094887362 + 0.5); - const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; - const double z2 = z * z; - conv.U = (uint64_t)(exp2 + 1023) << 52U; - // compute exp(z) using continued fractions, see - // https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex - conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); - // correct for rounding errors - if (value < conv.F) { - expval--; - conv.F /= 10; - } - - // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 - // characters - unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; - - // in "%g" mode, "prec" is the number of *significant figures* not decimals - if (flags & FLAGS_ADAPT_EXP) { - // do we want to fall-back to "%f" mode? - if ((value >= 1e-4) && (value < 1e6)) { - if ((int)prec > expval) { - prec = (unsigned)((int)prec - expval - 1); - } else { - prec = 0; - } - flags |= FLAGS_PRECISION; // make sure _ftoa respects precision - // no characters in exponent - minwidth = 0U; - expval = 0; - } else { - // we use one sigfig for the whole part - if ((prec > 0) && (flags & FLAGS_PRECISION)) { - --prec; - } - } - } - - // will everything fit? - unsigned int fwidth = width; - if (width > minwidth) { - // we didn't fall-back so subtract the characters required for the exponent - fwidth -= minwidth; - } else { - // not enough characters, so go back to default sizing - fwidth = 0U; - } - if ((flags & FLAGS_LEFT) && minwidth) { - // if we're padding on the right, DON'T pad the floating part - fwidth = 0U; - } - - // rescale the float value - if (expval) { - value /= conv.F; - } - - // output the floating part - const size_t start_idx = idx; - idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, - flags & ~FLAGS_ADAPT_EXP); - - // output the exponent part - if (minwidth) { - // output the exponential symbol - out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); - // output the exponent value - idx = - _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, - expval < 0, 10, 0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS); - // might need to right-pad spaces - if (flags & FLAGS_LEFT) { - while (idx - start_idx < width) - out(' ', buffer, idx++, maxlen); - } - } - return idx; -} -#endif // PRINTF_SUPPORT_EXPONENTIAL -#endif // PRINTF_SUPPORT_FLOAT - -// internal vsnprintf -static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, - const char *format, va_list va) { - unsigned int flags, width, precision, n; - size_t idx = 0U; - - if (!buffer) { - // use null output function - out = _out_null; - } - - while (*format) { - // format specifier? %[flags][width][.precision][length] - if (*format != '%') { - // no - out(*format, buffer, idx++, maxlen); - format++; - continue; - } else { - // yes, evaluate it - format++; - } - - // evaluate flags - flags = 0U; - do { - switch (*format) { - case '0': - flags |= FLAGS_ZEROPAD; - format++; - n = 1U; - break; - case '-': - flags |= FLAGS_LEFT; - format++; - n = 1U; - break; - case '+': - flags |= FLAGS_PLUS; - format++; - n = 1U; - break; - case ' ': - flags |= FLAGS_SPACE; - format++; - n = 1U; - break; - case '#': - flags |= FLAGS_HASH; - format++; - n = 1U; - break; - default: - n = 0U; - break; - } - } while (n); - - // evaluate width field - width = 0U; - if (_is_digit(*format)) { - width = _atoi(&format); - } else if (*format == '*') { - const int w = va_arg(va, int); - if (w < 0) { - flags |= FLAGS_LEFT; // reverse padding - width = (unsigned int)-w; - } else { - width = (unsigned int)w; - } - format++; - } - - // evaluate precision field - precision = 0U; - if (*format == '.') { - flags |= FLAGS_PRECISION; - format++; - if (_is_digit(*format)) { - precision = _atoi(&format); - } else if (*format == '*') { - const int prec = (int)va_arg(va, int); - precision = prec > 0 ? (unsigned int)prec : 0U; - format++; - } - } - - // evaluate length field - switch (*format) { - case 'l': - flags |= FLAGS_LONG; - format++; - if (*format == 'l') { - flags |= FLAGS_LONG_LONG; - format++; - } - break; - case 'h': - flags |= FLAGS_SHORT; - format++; - if (*format == 'h') { - flags |= FLAGS_CHAR; - format++; - } - break; -#if defined(PRINTF_SUPPORT_PTRDIFF_T) - case 't': - flags |= - (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; -#endif - case 'j': - flags |= - (sizeof(uint64_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; - case 'z': - flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); - format++; - break; - default: - break; - } - - // evaluate specifier - switch (*format) { - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': - case 'o': - case 'b': { - // set the base - unsigned int base; - if (*format == 'x' || *format == 'X') { - base = 16U; - } else if (*format == 'o') { - base = 8U; - } else if (*format == 'b') { - base = 2U; - } else { - base = 10U; - flags &= ~FLAGS_HASH; // no hash for dec format - } - // uppercase - if (*format == 'X') { - flags |= FLAGS_UPPERCASE; - } - - // no plus or space flag for u, x, X, o, b - if ((*format != 'i') && (*format != 'd')) { - flags &= ~(FLAGS_PLUS | FLAGS_SPACE); - } - - // ignore '0' flag when precision is given - if (flags & FLAGS_PRECISION) { - flags &= ~FLAGS_ZEROPAD; - } - - // convert the integer - if ((*format == 'i') || (*format == 'd')) { - // signed - if (flags & FLAGS_LONG_LONG) { -#if defined(PRINTF_SUPPORT_LONG_LONG) - const long long value = va_arg(va, long long); - idx = _ntoa_long_long( - out, buffer, idx, maxlen, - (unsigned long long)(value > 0 ? value : 0 - value), value < 0, - base, precision, width, flags); -#endif - } else if (flags & FLAGS_LONG) { - const long value = va_arg(va, long); - idx = _ntoa_long(out, buffer, idx, maxlen, - (unsigned long)(value > 0 ? value : 0 - value), - value < 0, base, precision, width, flags); - } else { - const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) - : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) - : va_arg(va, int); - idx = _ntoa_long(out, buffer, idx, maxlen, - (unsigned int)(value > 0 ? value : 0 - value), - value < 0, base, precision, width, flags); - } - } else { - // unsigned - if (flags & FLAGS_LONG_LONG) { -#if defined(PRINTF_SUPPORT_LONG_LONG) - idx = _ntoa_long_long(out, buffer, idx, maxlen, - va_arg(va, unsigned long long), false, base, - precision, width, flags); -#endif - } else if (flags & FLAGS_LONG) { - idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), - false, base, precision, width, flags); - } else { - const unsigned int value = - (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) - : (flags & FLAGS_SHORT) - ? (unsigned short int)va_arg(va, unsigned int) - : va_arg(va, unsigned int); - idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, - precision, width, flags); - } - } - format++; - break; - } -#if defined(PRINTF_SUPPORT_FLOAT) - case 'f': - case 'F': - if (*format == 'F') - flags |= FLAGS_UPPERCASE; - idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, - width, flags); - format++; - break; -#if defined(PRINTF_SUPPORT_EXPONENTIAL) - case 'e': - case 'E': - case 'g': - case 'G': - if ((*format == 'g') || (*format == 'G')) - flags |= FLAGS_ADAPT_EXP; - if ((*format == 'E') || (*format == 'G')) - flags |= FLAGS_UPPERCASE; - idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, - width, flags); - format++; - break; -#endif // PRINTF_SUPPORT_EXPONENTIAL -#endif // PRINTF_SUPPORT_FLOAT - case 'c': { - unsigned int l = 1U; - // pre padding - if (!(flags & FLAGS_LEFT)) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - // char output - out((char)va_arg(va, int), buffer, idx++, maxlen); - // post padding - if (flags & FLAGS_LEFT) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - format++; - break; - } - - case 's': { - const char *p = va_arg(va, char *); - unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); - // pre padding - if (flags & FLAGS_PRECISION) { - l = (l < precision ? l : precision); - } - if (!(flags & FLAGS_LEFT)) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - // string output - while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { - out(*(p++), buffer, idx++, maxlen); - } - // post padding - if (flags & FLAGS_LEFT) { - while (l++ < width) { - out(' ', buffer, idx++, maxlen); - } - } - format++; - break; - } - - case 'p': { - width = sizeof(void *) * 2U; - flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; -#if defined(PRINTF_SUPPORT_LONG_LONG) - const bool is_ll = sizeof(uintptr_t) == sizeof(long long); - if (is_ll) { - idx = _ntoa_long_long(out, buffer, idx, maxlen, - (uintptr_t)va_arg(va, void *), false, 16U, - precision, width, flags); - } else { -#endif - idx = _ntoa_long(out, buffer, idx, maxlen, - (unsigned long)((uintptr_t)va_arg(va, void *)), false, - 16U, precision, width, flags); -#if defined(PRINTF_SUPPORT_LONG_LONG) - } -#endif - format++; - break; - } - - case '%': - out('%', buffer, idx++, maxlen); - format++; - break; - - default: - out(*format, buffer, idx++, maxlen); - format++; - break; - } - } - - // termination - out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); - - // return written chars without terminating \0 - return (int)idx; -} - -/////////////////////////////////////////////////////////////////////////////// - -int sprintf_(char *buffer, const char *format, ...) { - va_list va; - va_start(va, format); - const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); - va_end(va); - return ret; -} - -int snprintf_(char *buffer, size_t count, const char *format, ...) { - va_list va; - va_start(va, format); - const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); - va_end(va); - return ret; -} - -int vsnprintf_(char *buffer, size_t count, const char *format, va_list va) { - return _vsnprintf(_out_buffer, buffer, count, format, va); -} - -int fctprintf(void (*out)(char character, void *arg), void *arg, - const char *format, ...) { - va_list va; - va_start(va, format); - const out_fct_wrap_type out_fct_wrap = {out, arg}; - const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, - (size_t)-1, format, va); - va_end(va); - return ret; -} - -// syscall -int ckb_debug(const char *s); -int printf(const char *format, ...) { - static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; - va_list va; - va_start(va, format); - int ret = vsnprintf_(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); - va_end(va); - ckb_debug(buf); - return ret; -} -int ckb_printf(const char *format, ...) { - static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; - va_list va; - va_start(va, format); - int ret = vsnprintf_(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); - va_end(va); - ckb_debug(buf); - return ret; -} - -#else - -int printf(const char *format, ...) { return 0; } -int ckb_printf(const char *format, ...) { return 0; } - -#endif /* CKB_C_STDLIB_PRINTF */ - -/* Copied from - * https://github.com/bminor/musl/blob/46d1c7801bb509e1097e8fadbaf359367fa4ef0b/src/setjmp/riscv64/setjmp.S - */ -/* We need to use inline asm for easier compilation, - * https://stackoverflow.com/a/42358235. */ -/* We need __attribute__((naked)) to remove prologue and epilogue, - * https://stackoverflow.com/a/42637729 */ -__attribute__((naked)) int setjmp(jmp_buf b) { - asm volatile("sd s0, 0(a0)\n" - "sd s1, 8(a0)\n" - "sd s2, 16(a0)\n" - "sd s3, 24(a0)\n" - "sd s4, 32(a0)\n" - "sd s5, 40(a0)\n" - "sd s6, 48(a0)\n" - "sd s7, 56(a0)\n" - "sd s8, 64(a0)\n" - "sd s9, 72(a0)\n" - "sd s10, 80(a0)\n" - "sd s11, 88(a0)\n" - "sd sp, 96(a0)\n" - "sd ra, 104(a0)\n" - "li a0, 0\n" - "ret\n"); -} - -__attribute__((naked)) int _setjmp(jmp_buf b) { - asm volatile("sd s0, 0(a0)\n" - "sd s1, 8(a0)\n" - "sd s2, 16(a0)\n" - "sd s3, 24(a0)\n" - "sd s4, 32(a0)\n" - "sd s5, 40(a0)\n" - "sd s6, 48(a0)\n" - "sd s7, 56(a0)\n" - "sd s8, 64(a0)\n" - "sd s9, 72(a0)\n" - "sd s10, 80(a0)\n" - "sd s11, 88(a0)\n" - "sd sp, 96(a0)\n" - "sd ra, 104(a0)\n" - "li a0, 0\n" - "ret\n"); -} - -__attribute__((naked)) void longjmp(jmp_buf b, int n) { - asm volatile("ld s0, 0(a0)\n" - "ld s1, 8(a0)\n" - "ld s2, 16(a0)\n" - "ld s3, 24(a0)\n" - "ld s4, 32(a0)\n" - "ld s5, 40(a0)\n" - "ld s6, 48(a0)\n" - "ld s7, 56(a0)\n" - "ld s8, 64(a0)\n" - "ld s9, 72(a0)\n" - "ld s10, 80(a0)\n" - "ld s11, 88(a0)\n" - "ld sp, 96(a0)\n" - "ld ra, 104(a0)\n" - "seqz a0, a1\n" - "add a0, a0, a1\n" - "ret\n"); -} - -__attribute__((naked)) void _longjmp(jmp_buf b, int n) { - asm volatile("ld s0, 0(a0)\n" - "ld s1, 8(a0)\n" - "ld s2, 16(a0)\n" - "ld s3, 24(a0)\n" - "ld s4, 32(a0)\n" - "ld s5, 40(a0)\n" - "ld s6, 48(a0)\n" - "ld s7, 56(a0)\n" - "ld s8, 64(a0)\n" - "ld s9, 72(a0)\n" - "ld s10, 80(a0)\n" - "ld s11, 88(a0)\n" - "ld sp, 96(a0)\n" - "ld ra, 104(a0)\n" - "seqz a0, a1\n" - "add a0, a0, a1\n" - "ret\n"); -} - -int abs(int a) { return a > 0 ? a : -a; } - -double frexp(double x, int *e) { - union { - double d; - uint64_t i; - } y = {x}; - int ee = y.i >> 52 & 0x7ff; - - if (!ee) { - if (x) { - x = frexp(x * 0x1p64, e); - *e -= 64; - } else - *e = 0; - return x; - } else if (ee == 0x7ff) { - return x; - } - - *e = ee - 0x3fe; - y.i &= 0x800fffffffffffffull; - y.i |= 0x3fe0000000000000ull; - return y.d; -} - -double fmod(double x, double y) { - union { - double f; - uint64_t i; - } ux = {x}, uy = {y}; - int ex = ux.i >> 52 & 0x7ff; - int ey = uy.i >> 52 & 0x7ff; - int sx = ux.i >> 63; - uint64_t i; - - /* in the followings uxi should be ux.i, but then gcc wrongly adds */ - /* float load/store to inner loops ruining performance and code size */ - uint64_t uxi = ux.i; - - if (uy.i << 1 == 0 || __builtin_isnan(y) || ex == 0x7ff) - return (x * y) / (x * y); - if (uxi << 1 <= uy.i << 1) { - if (uxi << 1 == uy.i << 1) - return 0 * x; - return x; - } - - /* normalize x and y */ - if (!ex) { - for (i = uxi << 12; i >> 63 == 0; ex--, i <<= 1) - ; - uxi <<= -ex + 1; - } else { - uxi &= -1ULL >> 12; - uxi |= 1ULL << 52; - } - if (!ey) { - for (i = uy.i << 12; i >> 63 == 0; ey--, i <<= 1) - ; - uy.i <<= -ey + 1; - } else { - uy.i &= -1ULL >> 12; - uy.i |= 1ULL << 52; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) - return 0 * x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) - return 0 * x; - uxi = i; - } - for (; uxi >> 52 == 0; uxi <<= 1, ex--) - ; - - /* scale result */ - if (ex > 0) { - uxi -= 1ULL << 52; - uxi |= (uint64_t)ex << 52; - } else { - uxi >>= -ex + 1; - } - uxi |= (uint64_t)sx << 63; - ux.i = uxi; - return ux.f; -} - -int strcoll(const char *l, const char *r) { return strcmp(l, r); } - -int *__errno_location(void) { - static int error = -1; - return &error; -} - -char *strerror(int e) { - static char *errorstr = "There is an error"; - return errorstr; -} - -int islower(int c) { return (unsigned)c - 'a' < 26; } - -int isupper(int c) { return (unsigned)c - 'A' < 26; } - -int tolower(int c) { - if (isupper(c)) - return c | 32; - return c; -} - -int toupper(int c) { - if (islower(c)) - return c & 0x5f; - return c; -} - -#define X(x) (((x) / 256 | (x)*256) % 65536) - -const unsigned short **__ctype_b_loc(void) { - static const unsigned short table[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), - X(0x200), X(0x200), X(0x200), X(0x200), X(0x320), X(0x220), X(0x220), - X(0x220), X(0x220), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), - X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), - X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x160), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), - X(0x4c0), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), - X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x4c0), X(0x4c0), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x8d5), X(0x8d5), X(0x8d5), - X(0x8d5), X(0x8d5), X(0x8d5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), - X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), - X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), - X(0x8c5), X(0x8c5), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), - X(0x4c0), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), - X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), - X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), - X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x4c0), - X(0x4c0), X(0x4c0), X(0x4c0), X(0x200), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - }; - - static const unsigned short *const ptable = table + 128; - return (void *)&ptable; -} - -const int32_t **__ctype_toupper_loc(void) { - static const int32_t table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 96, - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 123, 124, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - - static const int32_t *const ptable = table + 128; - - return (void *)&ptable; -} - -const int32_t **__ctype_tolower_loc(void) { - static const int32_t table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 91, 92, 93, 94, 95, 96, - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 123, 124, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - - static const int32_t *const ptable = table + 128; - - return (void *)&ptable; -} - -char *getenv(const char *name) { return 0; } - -int isspace(int c) { return c == ' ' || (unsigned)c - '\t' < 5; } - -// Copied from dietlibc -float strtof(const char *s, char **endptr) { - register const char *p = s; - register float value = 0.; - int sign = +1; - float factor; - unsigned int expo; - - while (isspace(*p)) - p++; - - switch (*p) { - case '-': - sign = -1; /* fall through */ - case '+': - p++; - default: - break; - } - - while ((unsigned int)(*p - '0') < 10u) - value = value * 10 + (*p++ - '0'); - - if (*p == '.') { - factor = 1.; - - p++; - while ((unsigned int)(*p - '0') < 10u) { - factor *= 0.1; - value += (*p++ - '0') * factor; - } - } - - if ((*p | 32) == 'e') { - expo = 0; - factor = 10.L; - - switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' - // folgenden MUSS. - case '-': - factor = 0.1; /* fall through */ - case '+': - p++; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - default: - value = 0.L; - p = s; - goto done; - } - - while ((unsigned int)(*p - '0') < 10u) - expo = 10 * expo + (*p++ - '0'); - - while (1) { - if (expo & 1) - value *= factor; - if ((expo >>= 1) == 0) - break; - factor *= factor; - } - } - -done: - if (endptr != NULL) - *endptr = (char *)p; - - return value * sign; -} - -// Convert char to an int in base `base`, -// `base` must be 10 or 16, return -1 on error. -int char2int(char ch, unsigned int base) -{ - if (ch >= '0' && ch <= '9') - return ch - '0'; - if (base == 16) { - if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - } - return -1; -} - -#define ldbltype long double -double strtod(const char *s, char **endptr) { - register const char *p = s; - register ldbltype value = 0.; - int sign = +1; - unsigned int base = 10; - ldbltype base_inverse = (ldbltype)1/(ldbltype)base; - ldbltype factor; - unsigned int expo; - unsigned int has_digits = 0; - - while (isspace(*p)) - p++; - - switch (*p) { - case '-': - sign = -1; /* fall through */ - case '+': - p++; - case '0': - p++; - if ((*p | 32) == 'x') { - base = 16; - base_inverse = (ldbltype)1/(ldbltype)base; - p++; - } else { - p--; - } - default: - break; - } - - unsigned int current_value; - while ((current_value = char2int(*p, base)) != -1) { - p++; - value = value * base + current_value; - has_digits = 1; - } - - if (*p == '.') { - factor = 1.; - - p++; - while ((current_value = char2int(*p, base)) != -1) { - p++; - factor *= base_inverse; - value += current_value * factor; - has_digits = 1; - } - } - - if ((*p | 32) == 'e' && base == 10) { - expo = 0; - factor = 10.; - - switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' - // folgenden MUSS. - case '-': - factor = 0.1; /* fall through */ - case '+': - p++; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - default: - value = 0.; - p = s; - goto done; - } - - while ((unsigned int)(*p - '0') < 10u) - expo = 10 * expo + (*p++ - '0'); - - while (1) { - if (expo & 1) - value *= factor; - if ((expo >>= 1) == 0) - break; - factor *= factor; - } - } - - if ((*p | 32) == 'p' && base == 16) { - // TODO: add specifier p support - // https://cplusplus.com/reference/cstdlib/strtod/ - // - A 0x or 0X prefix, then a sequence of hexadecimal digits (as in isxdigit) optionally containing a period which separates the whole and fractional number parts. Optionally followed by a power of 2 exponent (a p or P character followed by an optional sign and a sequence of hexadecimal digits). - } -done: - if (endptr != NULL) { - if (has_digits) { - *endptr = (char *)p; - } else { - *endptr = (char *)s; - } - } - - return value * sign; -} - -long double strtold(const char *s, char **endptr) { - register const char *p = s; - register long double value = 0.L; - int sign = +1; - long double factor; - unsigned int expo; - - while (isspace(*p)) - p++; - - switch (*p) { - case '-': - sign = -1; /* fall through */ - case '+': - p++; - default: - break; - } - - while ((unsigned int)(*p - '0') < 10u) - value = value * 10 + (*p++ - '0'); - - if (*p == '.') { - factor = 1.; - - p++; - while ((unsigned int)(*p - '0') < 10u) { - factor *= 0.1; - value += (*p++ - '0') * factor; - } - } - - if ((*p | 32) == 'e') { - expo = 0; - factor = 10.L; - - switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' - // folgenden MUSS. - case '-': - factor = 0.1; /* fall through */ - case '+': - p++; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; - default: - value = 0.L; - p = s; - goto done; - } - - while ((unsigned int)(*p - '0') < 10u) - expo = 10 * expo + (*p++ - '0'); - - while (1) { - if (expo & 1) - value *= factor; - if ((expo >>= 1) == 0) - break; - factor *= factor; - } - } - -done: - if (endptr != NULL) - *endptr = (char *)p; - - return value * sign; -} -#endif // __CKB_IMPL_INCLUDED__ diff --git a/include/ckb-c-stdlib/libc/src/malloc_impl.h b/include/ckb-c-stdlib/libc/src/malloc_impl.h deleted file mode 100644 index a05fda9..0000000 --- a/include/ckb-c-stdlib/libc/src/malloc_impl.h +++ /dev/null @@ -1,408 +0,0 @@ -#ifndef CKB_C_STDLIB_MALLOC_H_ -#define CKB_C_STDLIB_MALLOC_H_ - -#include "ckb_syscalls.h" - -#ifndef CKB_BRK_MIN -extern char _end[]; /* _end is set in the linker */ -#define CKB_BRK_MIN ((uintptr_t)&_end) -#endif -#ifndef CKB_BRK_MAX -#define CKB_BRK_MAX 0x00300000 -#endif - -struct chunk { - size_t psize, csize; - struct chunk *next, *prev; -}; - -struct bin { - volatile int lock[2]; - struct chunk *head; - struct chunk *tail; -}; - -#define CKB_SIZE_ALIGN (4 * sizeof(size_t)) -#define CKB_SIZE_MASK (-CKB_SIZE_ALIGN) -#define CKB_OVERHEAD (2 * sizeof(size_t)) -#define CKB_DONTCARE 16 -#define CKB_RECLAIM 163840 -#define CKB_MMAP_THRESHOLD (0x1c00*CKB_SIZE_ALIGN) - -#define CKB_CHUNK_SIZE(c) ((c)->csize & -2) -#define CKB_CHUNK_PSIZE(c) ((c)->psize & -2) -#define CKB_PREV_CHUNK(c) ((struct chunk *)((char *)(c)-CKB_CHUNK_PSIZE(c))) -#define CKB_NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CKB_CHUNK_SIZE(c))) -#define CKB_MEM_TO_CHUNK(p) (struct chunk *)((char *)(p)-CKB_OVERHEAD) -#define CKB_CHUNK_TO_MEM(c) (void *)((char *)(c) + CKB_OVERHEAD) -#define CKB_BIN_TO_CHUNK(i) (CKB_MEM_TO_CHUNK(&mal.bins[i].head)) -#define CKB_C_INUSE ((size_t)1) -#define CKB_IS_MMAPPED(c) !((c)->csize & (CKB_C_INUSE)) -#define CKB_PAGE_SIZE 4096 -void __bin_chunk(struct chunk *); -int ckb_exit(int8_t code); -static inline void a_crash() { ckb_exit(-1); } -void free(void *p); - -static inline void a_and_64(volatile uint64_t *p, uint64_t v) { *p &= v; } - -static inline void a_or_64(volatile uint64_t *p, uint64_t v) { *p |= v; } - -static uintptr_t s_program_break = 0; -static uintptr_t s_brk_min = CKB_BRK_MIN; -static uintptr_t s_brk_max = CKB_BRK_MAX; - -void malloc_config(uintptr_t min, uintptr_t max) { - s_brk_min = min; - s_brk_max = max; - s_program_break = 0; -} - -void *_sbrk(uintptr_t incr) { - if (!s_program_break) { - s_program_break = s_brk_min; - s_program_break += -s_program_break & (CKB_PAGE_SIZE - 1); - } - if ((s_program_break + incr) > s_brk_max) { - return (void *)-1; - } - - uintptr_t start = s_program_break; - s_program_break += incr; - return (void *)start; -} - -static struct { - volatile uint64_t binmap; - struct bin bins[64]; - volatile int split_merge_lock[2]; -} mal; - -static inline void lock_bin(int i) { - if (!mal.bins[i].head) - mal.bins[i].head = mal.bins[i].tail = CKB_BIN_TO_CHUNK(i); -} - -static inline void unlock_bin(int i) {} - -#if 0 -static int first_set(uint64_t x) { - // TODO: use RISC-V asm - static const char debruijn64[64] = { - 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, - 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, - 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, - 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12}; - static const char debruijn32[32] = { - 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, - 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14}; - if (sizeof(long) < 8) { - uint32_t y = x; - if (!y) { - y = x >> 32; - return 32 + debruijn32[(y & -y) * 0x076be629 >> 27]; - } - return debruijn32[(y & -y) * 0x076be629 >> 27]; - } - return debruijn64[(x & -x) * 0x022fdd63cc95386dull >> 58]; -} - -#else - -static int __attribute__((naked)) first_set(uint64_t x) { - __asm__(".byte 0x13, 0x15, 0x15, 0x60"); - __asm__("ret"); -} - -#endif - -static const unsigned char bin_tab[60] = { - 32, 33, 34, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, - 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, - 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 46, - 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, -}; - -static int bin_index(size_t x) { - x = x / CKB_SIZE_ALIGN - 1; - if (x <= 32) - return x; - if (x < 512) - return bin_tab[x / 8 - 4]; - if (x > 0x1c00) - return 63; - return bin_tab[x / 128 - 4] + 16; -} - -static int bin_index_up(size_t x) { - x = x / CKB_SIZE_ALIGN - 1; - if (x <= 32) - return x; - x--; - if (x < 512) - return bin_tab[x / 8 - 4] + 1; - return bin_tab[x / 128 - 4] + 17; -} - -static void *__expand_heap(size_t *pn) { - size_t n = *pn; - n += -n & (CKB_PAGE_SIZE - 1); - - void *p = _sbrk(n); - if (p == (void *)-1) { - return 0; - } - *pn = n; - return p; -} - -static struct chunk *expand_heap(size_t n) { - static void *end; - void *p; - struct chunk *w; - - /* The argument n already accounts for the caller's chunk - * CKB_OVERHEAD needs, but if the heap can't be extended in-place, - * we need room for an extra zero-sized sentinel chunk. */ - n += CKB_SIZE_ALIGN; - - p = __expand_heap(&n); - if (!p) - return 0; - /* If not just expanding existing space, we need to make a - * new sentinel chunk below the allocated space. */ - if (p != end) { - /* Valid/safe because of the prologue increment. */ - n -= CKB_SIZE_ALIGN; - p = (char *)p + CKB_SIZE_ALIGN; - w = CKB_MEM_TO_CHUNK(p); - w->psize = 0 | CKB_C_INUSE; - } - - /* Record new heap end and fill in footer. */ - end = (char *)p + n; - w = CKB_MEM_TO_CHUNK(end); - w->psize = n | CKB_C_INUSE; - w->csize = 0 | CKB_C_INUSE; - - /* Fill in header, which may be new or may be replacing a - * zero-size sentinel header at the old end-of-heap. */ - w = CKB_MEM_TO_CHUNK(p); - w->csize = n | CKB_C_INUSE; - - return w; -} - -static int adjust_size(size_t *n) { - /* Result of pointer difference must fit in ptrdiff_t. */ - if (*n - 1 > INT64_MAX - CKB_SIZE_ALIGN - CKB_PAGE_SIZE) { - if (*n) { - return -1; - } else { - *n = CKB_SIZE_ALIGN; - return 0; - } - } - *n = (*n + CKB_OVERHEAD + CKB_SIZE_ALIGN - 1) & CKB_SIZE_MASK; - return 0; -} - -static void unbin(struct chunk *c, int i) { - if (c->prev == c->next) - a_and_64(&mal.binmap, ~(1ULL << i)); - c->prev->next = c->next; - c->next->prev = c->prev; - c->csize |= CKB_C_INUSE; - CKB_NEXT_CHUNK(c)->psize |= CKB_C_INUSE; -} - -static void bin_chunk(struct chunk *self, int i) { - self->next = CKB_BIN_TO_CHUNK(i); - self->prev = mal.bins[i].tail; - self->next->prev = self; - self->prev->next = self; - if (self->prev == CKB_BIN_TO_CHUNK(i)) - a_or_64(&mal.binmap, 1ULL << i); -} - -static void trim(struct chunk *self, size_t n) { - size_t n1 = CKB_CHUNK_SIZE(self); - struct chunk *next, *split; - - if (n >= n1 - CKB_DONTCARE) - return; - - next = CKB_NEXT_CHUNK(self); - split = (void *)((char *)self + n); - - split->psize = n | CKB_C_INUSE; - split->csize = n1 - n; - next->psize = n1 - n; - self->csize = n | CKB_C_INUSE; - - int i = bin_index(n1 - n); - lock_bin(i); - - bin_chunk(split, i); - - unlock_bin(i); -} - -void *malloc(size_t n) { - struct chunk *c; - int i, j; - uint64_t mask; - - if (adjust_size(&n) < 0) - return 0; - - if (n >= CKB_MMAP_THRESHOLD) { - // TODO: don't support too large memory - return 0; - } - - i = bin_index_up(n); - if (i < 63 && (mal.binmap & (1ULL << i))) { - lock_bin(i); - c = mal.bins[i].head; - if (c != CKB_BIN_TO_CHUNK(i) && CKB_CHUNK_SIZE(c) - n <= CKB_DONTCARE) { - unbin(c, i); - unlock_bin(i); - return CKB_CHUNK_TO_MEM(c); - } - unlock_bin(i); - } - for (mask = mal.binmap & -(1ULL << i); mask; mask -= (mask & -mask)) { - j = first_set(mask); - lock_bin(j); - c = mal.bins[j].head; - if (c != CKB_BIN_TO_CHUNK(j)) { - unbin(c, j); - unlock_bin(j); - break; - } - unlock_bin(j); - } - if (!mask) { - c = expand_heap(n); - if (!c) { - return 0; - } - } - trim(c, n); - return CKB_CHUNK_TO_MEM(c); -} - -void *realloc(void *p, size_t n) { - struct chunk *self, *next; - size_t n0; - void *new; - - if (!p) - return malloc(n); - - if (adjust_size(&n) < 0) - return 0; - - self = CKB_MEM_TO_CHUNK(p); - n0 = CKB_CHUNK_SIZE(self); - - if (n <= n0 && n0 - n <= CKB_DONTCARE) - return p; - - next = CKB_NEXT_CHUNK(self); - - /* Crash on corrupted footer (likely from buffer overflow) */ - if (next->psize != self->csize) - a_crash(); - - if (n < n0) { - int i = bin_index_up(n); - int j = bin_index(n0); - if (i < j && (mal.binmap & (1ULL << i))) - goto copy_realloc; - struct chunk *split = (void *)((char *)self + n); - self->csize = split->psize = n | CKB_C_INUSE; - split->csize = next->psize = (n0 - n) | CKB_C_INUSE; - __bin_chunk(split); - return CKB_CHUNK_TO_MEM(self); - } - - size_t nsize = next->csize & CKB_C_INUSE ? 0 : CKB_CHUNK_SIZE(next); - if (n0 + nsize >= n) { - int i = bin_index(nsize); - lock_bin(i); - if (!(next->csize & CKB_C_INUSE)) { - unbin(next, i); - unlock_bin(i); - next = CKB_NEXT_CHUNK(next); - self->csize = next->psize = (n0 + nsize) | CKB_C_INUSE; - trim(self, n); - return CKB_CHUNK_TO_MEM(self); - } - unlock_bin(i); - } -copy_realloc: - /* As a last resort, allocate a new chunk and copy to it. */ - new = malloc(n - CKB_OVERHEAD); - if (!new) - return 0; - memcpy(new, p, (n < n0 ? n : n0) - CKB_OVERHEAD); - free(CKB_CHUNK_TO_MEM(self)); - return new; -} - -void __bin_chunk(struct chunk *self) { - struct chunk *next = CKB_NEXT_CHUNK(self); - - /* Crash on corrupted footer (likely from buffer overflow) */ - if (next->psize != self->csize) - a_crash(); - - size_t osize = CKB_CHUNK_SIZE(self), size = osize; - - /* Since we hold split_merge_lock, only transition from free to - * in-use can race; in-use to free is impossible */ - size_t psize = self->psize & CKB_C_INUSE ? 0 : CKB_CHUNK_PSIZE(self); - size_t nsize = next->csize & CKB_C_INUSE ? 0 : CKB_CHUNK_SIZE(next); - - if (psize) { - int i = bin_index(psize); - lock_bin(i); - if (!(self->psize & CKB_C_INUSE)) { - struct chunk *prev = CKB_PREV_CHUNK(self); - unbin(prev, i); - self = prev; - size += psize; - } - unlock_bin(i); - } - if (nsize) { - int i = bin_index(nsize); - lock_bin(i); - if (!(next->csize & CKB_C_INUSE)) { - unbin(next, i); - next = CKB_NEXT_CHUNK(next); - size += nsize; - } - unlock_bin(i); - } - - int i = bin_index(size); - lock_bin(i); - - self->csize = size; - next->psize = size; - bin_chunk(self, i); - - unlock_bin(i); -} - -void free(void *p) { - if (!p) - return; - struct chunk *self = CKB_MEM_TO_CHUNK(p); - __bin_chunk(self); -} - -#endif diff --git a/include/ckb-c-stdlib/libc/stdarg.h b/include/ckb-c-stdlib/libc/stdarg.h deleted file mode 100644 index eb5e9d3..0000000 --- a/include/ckb-c-stdlib/libc/stdarg.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CKB_C_STDLIB_STDARG_H_ -#define CKB_C_STDLIB_STDARG_H_ - -#define va_start(v, l) __builtin_va_start(v, l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v, l) __builtin_va_arg(v, l) -#define __va_copy(d, s) __builtin_va_copy(d, s) -#define va_list __builtin_va_list - -#endif /* CKB_C_STDLIB_STDARG_H_ */ diff --git a/include/ckb-c-stdlib/libc/stdbool.h b/include/ckb-c-stdlib/libc/stdbool.h deleted file mode 100644 index 327068b..0000000 --- a/include/ckb-c-stdlib/libc/stdbool.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CKB_C_STDLIB_STDBOOL_H_ -#define CKB_C_STDLIB_STDBOOL_H_ -#include - -#define true 1 -#define false 0 -#define bool _Bool - -#endif /* CKB_C_STDLIB_STDBOOL_H_ */ diff --git a/include/ckb-c-stdlib/libc/stddef.h b/include/ckb-c-stdlib/libc/stddef.h deleted file mode 100644 index ad71d9d..0000000 --- a/include/ckb-c-stdlib/libc/stddef.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CKB_C_STDLIB_STDDEF_H_ -#define CKB_C_STDLIB_STDDEF_H_ - -#include "internal/types.h" -#define NULL ((void*)0) -#include - -#endif /* CKB_C_STDLIB_STDDEF_H_ */ diff --git a/include/ckb-c-stdlib/libc/stdint.h b/include/ckb-c-stdlib/libc/stdint.h deleted file mode 100644 index 54a62cb..0000000 --- a/include/ckb-c-stdlib/libc/stdint.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef CKB_C_STDLIB_STDINT_H_ -#define CKB_C_STDLIB_STDINT_H_ - -#include - -#include "internal/types.h" - -#define INT8_MIN (-1 - 0x7f) -#define INT16_MIN (-1 - 0x7fff) -#define INT32_MIN (-1 - 0x7fffffff) -#define INT64_MIN (-1 - 0x7fffffffffffffff) - -#define INT8_MAX (0x7f) -#define INT16_MAX (0x7fff) -#define INT32_MAX (0x7fffffff) -#define INT64_MAX (0x7fffffffffffffff) - -#define UINT8_MAX (0xff) -#define UINT16_MAX (0xffff) -#define UINT32_MAX (0xffffffffu) -#define UINT64_MAX (0xffffffffffffffffu) - -#define SIZE_MAX UINT64_MAX - -#endif /* CKB_C_STDLIB_STDINT_H_ */ diff --git a/include/ckb-c-stdlib/libc/stdio.h b/include/ckb-c-stdlib/libc/stdio.h deleted file mode 100644 index c626b88..0000000 --- a/include/ckb-c-stdlib/libc/stdio.h +++ /dev/null @@ -1,59 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// \author (c) Marco Paland (info@paland.com) -// 2014-2019, PALANDesign Hannover, Germany -// -// \license The MIT License (MIT) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for -// speed on -// embedded systems with a very limited resources. These routines are -// thread safe and reentrant! Use this instead of the bloated -// standard/newlib printf cause these use malloc for printf (and may not -// be thread safe). -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef CKB_C_STDLIB_STDIO_H_ -#define CKB_C_STDLIB_STDIO_H_ -#include - -/* - * This function uses `ckb_debug` syscall to output formatted messages. - * - * Pass `-D CKB_C_STDLIB_PRINTF` flag to GCC to enable printf; - * If the flag is undefined the printf will be compiled as an empty function. - * - * Some versions of GCC raise errors on compiling since those versions have a - * built-in printf function; pass `-fno-builtin-printf` flag to GCC to fix the - * compiling. - */ -int printf(const char* format, ...); -/* - * This function uses `ckb_debug` syscall to output formatted messages. - * - * Pass `-D CKB_C_STDLIB_PRINTF` flag to GCC to enable ckb_printf; - * If the flag is undefined the ckb_printf will be compiled as an empty - * function. - */ -int ckb_printf(const char* format, ...); -int ckb_debug(const char* s); - -#endif /* CKB_C_STDLIB_STDIO_H_ */ diff --git a/include/ckb-c-stdlib/libc/stdlib.h b/include/ckb-c-stdlib/libc/stdlib.h deleted file mode 100644 index bb7b2d1..0000000 --- a/include/ckb-c-stdlib/libc/stdlib.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CKB_C_STDLIB_STDLIB_H_ -#define CKB_C_STDLIB_STDLIB_H_ -#include -#include - -void *malloc(size_t size); -void free(void *ptr); -void *calloc(size_t nmemb, size_t size); -void *realloc(void *ptr, size_t size); -typedef int (*cmpfun)(const void *, const void *); -void qsort(void *base, size_t nel, size_t width, cmpfun cmp); -int rand(void); -void *bsearch(const void *key, const void *base, size_t nel, size_t width, - int (*cmp)(const void *, const void *)); - -float strtof(const char *__restrict, char **__restrict); -double strtod(const char *__restrict, char **__restrict); -long double strtold(const char *__restrict, char **__restrict); - -int abs (int); - -#endif /* CKB_C_STDLIB_STDLIB_H_ */ diff --git a/include/ckb-c-stdlib/libc/string.h b/include/ckb-c-stdlib/libc/string.h deleted file mode 100644 index 096a351..0000000 --- a/include/ckb-c-stdlib/libc/string.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CKB_C_STDLIB_STRING_H_ -#define CKB_C_STDLIB_STRING_H_ - -#include -#include - -void *memset(void *dest, int c, size_t n); -void *memcpy(void *restrict dest, const void *restrict src, size_t n); -void *memmove(void *dest, const void *src, size_t n); -int memcmp(const void *vl, const void *vr, size_t n); -char *strcpy(char *restrict d, const char *restrict s); -size_t strlen(const char *s); -int strcmp(const char *l, const char *r); -char *strstr(const char *, const char *); -char *strchr (const char *, int); -int strncmp(const char *_l, const char *_r, size_t n); -char *strpbrk (const char *, const char *); -size_t strcspn (const char *, const char *); -size_t strspn (const char *, const char *); -void *memchr (const void *, int, size_t); - -int strcoll (const char *, const char *); - -char *strerror (int); - -#endif /* CKB_C_STDLIB_STRING_H_ */ diff --git a/include/ckb-c-stdlib/molecule/VERSION b/include/ckb-c-stdlib/molecule/VERSION deleted file mode 100644 index 267577d..0000000 --- a/include/ckb-c-stdlib/molecule/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.4.1 diff --git a/include/ckb-c-stdlib/molecule/blockchain-api2.h b/include/ckb-c-stdlib/molecule/blockchain-api2.h deleted file mode 100644 index 5afaf9c..0000000 --- a/include/ckb-c-stdlib/molecule/blockchain-api2.h +++ /dev/null @@ -1,1496 +0,0 @@ - -#ifndef _BLOCKCHAIN_API2_H_ -#define _BLOCKCHAIN_API2_H_ - -#define MOLECULEC2_VERSION 6001 -#define MOLECULE2_API_VERSION_MIN 5000 - -#include "molecule2_reader.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -// ----forward declaration-------- -struct Uint32Type; -struct Uint32VTable; -struct Uint32VTable *GetUint32VTable(void); -struct Uint32Type make_Uint32(mol2_cursor_t *cur); -uint32_t Uint32_len_impl(struct Uint32Type *); -uint8_t Uint32_get_impl(struct Uint32Type *, uint32_t, bool *); -struct Uint64Type; -struct Uint64VTable; -struct Uint64VTable *GetUint64VTable(void); -struct Uint64Type make_Uint64(mol2_cursor_t *cur); -uint32_t Uint64_len_impl(struct Uint64Type *); -uint8_t Uint64_get_impl(struct Uint64Type *, uint32_t, bool *); -struct Uint128Type; -struct Uint128VTable; -struct Uint128VTable *GetUint128VTable(void); -struct Uint128Type make_Uint128(mol2_cursor_t *cur); -uint32_t Uint128_len_impl(struct Uint128Type *); -uint8_t Uint128_get_impl(struct Uint128Type *, uint32_t, bool *); -struct Byte32Type; -struct Byte32VTable; -struct Byte32VTable *GetByte32VTable(void); -struct Byte32Type make_Byte32(mol2_cursor_t *cur); -uint32_t Byte32_len_impl(struct Byte32Type *); -uint8_t Byte32_get_impl(struct Byte32Type *, uint32_t, bool *); -struct Uint256Type; -struct Uint256VTable; -struct Uint256VTable *GetUint256VTable(void); -struct Uint256Type make_Uint256(mol2_cursor_t *cur); -uint32_t Uint256_len_impl(struct Uint256Type *); -uint8_t Uint256_get_impl(struct Uint256Type *, uint32_t, bool *); -struct BytesType; -struct BytesVTable; -struct BytesVTable *GetBytesVTable(void); -struct BytesType make_Bytes(mol2_cursor_t *cur); -uint32_t Bytes_len_impl(struct BytesType *); -uint8_t Bytes_get_impl(struct BytesType *, uint32_t, bool *); -struct BytesOptType; -struct BytesOptVTable; -struct BytesOptVTable *GetBytesOptVTable(void); -struct BytesOptType make_BytesOpt(mol2_cursor_t *cur); -bool BytesOpt_is_none_impl(struct BytesOptType *); -bool BytesOpt_is_some_impl(struct BytesOptType *); -mol2_cursor_t BytesOpt_unwrap_impl(struct BytesOptType *); -struct BytesVecType; -struct BytesVecVTable; -struct BytesVecVTable *GetBytesVecVTable(void); -struct BytesVecType make_BytesVec(mol2_cursor_t *cur); -uint32_t BytesVec_len_impl(struct BytesVecType *); -mol2_cursor_t BytesVec_get_impl(struct BytesVecType *, uint32_t, bool *); -struct Byte32VecType; -struct Byte32VecVTable; -struct Byte32VecVTable *GetByte32VecVTable(void); -struct Byte32VecType make_Byte32Vec(mol2_cursor_t *cur); -uint32_t Byte32Vec_len_impl(struct Byte32VecType *); -mol2_cursor_t Byte32Vec_get_impl(struct Byte32VecType *, uint32_t, bool *); -struct ScriptOptType; -struct ScriptOptVTable; -struct ScriptOptVTable *GetScriptOptVTable(void); -struct ScriptOptType make_ScriptOpt(mol2_cursor_t *cur); -bool ScriptOpt_is_none_impl(struct ScriptOptType *); -bool ScriptOpt_is_some_impl(struct ScriptOptType *); -struct ScriptType ScriptOpt_unwrap_impl(struct ScriptOptType *); -struct ProposalShortIdType; -struct ProposalShortIdVTable; -struct ProposalShortIdVTable *GetProposalShortIdVTable(void); -struct ProposalShortIdType make_ProposalShortId(mol2_cursor_t *cur); -uint32_t ProposalShortId_len_impl(struct ProposalShortIdType *); -uint8_t ProposalShortId_get_impl(struct ProposalShortIdType *, uint32_t, - bool *); -struct UncleBlockVecType; -struct UncleBlockVecVTable; -struct UncleBlockVecVTable *GetUncleBlockVecVTable(void); -struct UncleBlockVecType make_UncleBlockVec(mol2_cursor_t *cur); -uint32_t UncleBlockVec_len_impl(struct UncleBlockVecType *); -struct UncleBlockType UncleBlockVec_get_impl(struct UncleBlockVecType *, - uint32_t, bool *); -struct TransactionVecType; -struct TransactionVecVTable; -struct TransactionVecVTable *GetTransactionVecVTable(void); -struct TransactionVecType make_TransactionVec(mol2_cursor_t *cur); -uint32_t TransactionVec_len_impl(struct TransactionVecType *); -struct TransactionType TransactionVec_get_impl(struct TransactionVecType *, - uint32_t, bool *); -struct ProposalShortIdVecType; -struct ProposalShortIdVecVTable; -struct ProposalShortIdVecVTable *GetProposalShortIdVecVTable(void); -struct ProposalShortIdVecType make_ProposalShortIdVec(mol2_cursor_t *cur); -uint32_t ProposalShortIdVec_len_impl(struct ProposalShortIdVecType *); -mol2_cursor_t ProposalShortIdVec_get_impl(struct ProposalShortIdVecType *, - uint32_t, bool *); -struct CellDepVecType; -struct CellDepVecVTable; -struct CellDepVecVTable *GetCellDepVecVTable(void); -struct CellDepVecType make_CellDepVec(mol2_cursor_t *cur); -uint32_t CellDepVec_len_impl(struct CellDepVecType *); -struct CellDepType CellDepVec_get_impl(struct CellDepVecType *, uint32_t, - bool *); -struct CellInputVecType; -struct CellInputVecVTable; -struct CellInputVecVTable *GetCellInputVecVTable(void); -struct CellInputVecType make_CellInputVec(mol2_cursor_t *cur); -uint32_t CellInputVec_len_impl(struct CellInputVecType *); -struct CellInputType CellInputVec_get_impl(struct CellInputVecType *, uint32_t, - bool *); -struct CellOutputVecType; -struct CellOutputVecVTable; -struct CellOutputVecVTable *GetCellOutputVecVTable(void); -struct CellOutputVecType make_CellOutputVec(mol2_cursor_t *cur); -uint32_t CellOutputVec_len_impl(struct CellOutputVecType *); -struct CellOutputType CellOutputVec_get_impl(struct CellOutputVecType *, - uint32_t, bool *); -struct ScriptType; -struct ScriptVTable; -struct ScriptVTable *GetScriptVTable(void); -struct ScriptType make_Script(mol2_cursor_t *cur); -mol2_cursor_t Script_get_code_hash_impl(struct ScriptType *); -uint8_t Script_get_hash_type_impl(struct ScriptType *); -mol2_cursor_t Script_get_args_impl(struct ScriptType *); -struct OutPointType; -struct OutPointVTable; -struct OutPointVTable *GetOutPointVTable(void); -struct OutPointType make_OutPoint(mol2_cursor_t *cur); -mol2_cursor_t OutPoint_get_tx_hash_impl(struct OutPointType *); -uint32_t OutPoint_get_index_impl(struct OutPointType *); -struct CellInputType; -struct CellInputVTable; -struct CellInputVTable *GetCellInputVTable(void); -struct CellInputType make_CellInput(mol2_cursor_t *cur); -uint64_t CellInput_get_since_impl(struct CellInputType *); -struct OutPointType CellInput_get_previous_output_impl(struct CellInputType *); -struct CellOutputType; -struct CellOutputVTable; -struct CellOutputVTable *GetCellOutputVTable(void); -struct CellOutputType make_CellOutput(mol2_cursor_t *cur); -uint64_t CellOutput_get_capacity_impl(struct CellOutputType *); -struct ScriptType CellOutput_get_lock_impl(struct CellOutputType *); -struct ScriptOptType CellOutput_get_type__impl(struct CellOutputType *); -struct CellDepType; -struct CellDepVTable; -struct CellDepVTable *GetCellDepVTable(void); -struct CellDepType make_CellDep(mol2_cursor_t *cur); -struct OutPointType CellDep_get_out_point_impl(struct CellDepType *); -uint8_t CellDep_get_dep_type_impl(struct CellDepType *); -struct RawTransactionType; -struct RawTransactionVTable; -struct RawTransactionVTable *GetRawTransactionVTable(void); -struct RawTransactionType make_RawTransaction(mol2_cursor_t *cur); -uint32_t RawTransaction_get_version_impl(struct RawTransactionType *); -struct CellDepVecType RawTransaction_get_cell_deps_impl( - struct RawTransactionType *); -struct Byte32VecType RawTransaction_get_header_deps_impl( - struct RawTransactionType *); -struct CellInputVecType RawTransaction_get_inputs_impl( - struct RawTransactionType *); -struct CellOutputVecType RawTransaction_get_outputs_impl( - struct RawTransactionType *); -struct BytesVecType RawTransaction_get_outputs_data_impl( - struct RawTransactionType *); -struct TransactionType; -struct TransactionVTable; -struct TransactionVTable *GetTransactionVTable(void); -struct TransactionType make_Transaction(mol2_cursor_t *cur); -struct RawTransactionType Transaction_get_raw_impl(struct TransactionType *); -struct BytesVecType Transaction_get_witnesses_impl(struct TransactionType *); -struct RawHeaderType; -struct RawHeaderVTable; -struct RawHeaderVTable *GetRawHeaderVTable(void); -struct RawHeaderType make_RawHeader(mol2_cursor_t *cur); -uint32_t RawHeader_get_version_impl(struct RawHeaderType *); -uint32_t RawHeader_get_compact_target_impl(struct RawHeaderType *); -uint64_t RawHeader_get_timestamp_impl(struct RawHeaderType *); -uint64_t RawHeader_get_number_impl(struct RawHeaderType *); -uint64_t RawHeader_get_epoch_impl(struct RawHeaderType *); -mol2_cursor_t RawHeader_get_parent_hash_impl(struct RawHeaderType *); -mol2_cursor_t RawHeader_get_transactions_root_impl(struct RawHeaderType *); -mol2_cursor_t RawHeader_get_proposals_hash_impl(struct RawHeaderType *); -mol2_cursor_t RawHeader_get_uncles_hash_impl(struct RawHeaderType *); -mol2_cursor_t RawHeader_get_dao_impl(struct RawHeaderType *); -struct HeaderType; -struct HeaderVTable; -struct HeaderVTable *GetHeaderVTable(void); -struct HeaderType make_Header(mol2_cursor_t *cur); -struct RawHeaderType Header_get_raw_impl(struct HeaderType *); -mol2_cursor_t Header_get_nonce_impl(struct HeaderType *); -struct UncleBlockType; -struct UncleBlockVTable; -struct UncleBlockVTable *GetUncleBlockVTable(void); -struct UncleBlockType make_UncleBlock(mol2_cursor_t *cur); -struct HeaderType UncleBlock_get_header_impl(struct UncleBlockType *); -struct ProposalShortIdVecType UncleBlock_get_proposals_impl( - struct UncleBlockType *); -struct BlockType; -struct BlockVTable; -struct BlockVTable *GetBlockVTable(void); -struct BlockType make_Block(mol2_cursor_t *cur); -struct HeaderType Block_get_header_impl(struct BlockType *); -struct UncleBlockVecType Block_get_uncles_impl(struct BlockType *); -struct TransactionVecType Block_get_transactions_impl(struct BlockType *); -struct ProposalShortIdVecType Block_get_proposals_impl(struct BlockType *); -struct CellbaseWitnessType; -struct CellbaseWitnessVTable; -struct CellbaseWitnessVTable *GetCellbaseWitnessVTable(void); -struct CellbaseWitnessType make_CellbaseWitness(mol2_cursor_t *cur); -struct ScriptType CellbaseWitness_get_lock_impl(struct CellbaseWitnessType *); -mol2_cursor_t CellbaseWitness_get_message_impl(struct CellbaseWitnessType *); -struct WitnessArgsType; -struct WitnessArgsVTable; -struct WitnessArgsVTable *GetWitnessArgsVTable(void); -struct WitnessArgsType make_WitnessArgs(mol2_cursor_t *cur); -struct BytesOptType WitnessArgs_get_lock_impl(struct WitnessArgsType *); -struct BytesOptType WitnessArgs_get_input_type_impl(struct WitnessArgsType *); -struct BytesOptType WitnessArgs_get_output_type_impl(struct WitnessArgsType *); - -// ----definition----------------- -typedef struct Uint32VTable { - uint32_t (*len)(struct Uint32Type *); - uint8_t (*get)(struct Uint32Type *, uint32_t, bool *); -} Uint32VTable; -typedef struct Uint32Type { - mol2_cursor_t cur; - Uint32VTable *t; -} Uint32Type; - -typedef struct Uint64VTable { - uint32_t (*len)(struct Uint64Type *); - uint8_t (*get)(struct Uint64Type *, uint32_t, bool *); -} Uint64VTable; -typedef struct Uint64Type { - mol2_cursor_t cur; - Uint64VTable *t; -} Uint64Type; - -typedef struct Uint128VTable { - uint32_t (*len)(struct Uint128Type *); - uint8_t (*get)(struct Uint128Type *, uint32_t, bool *); -} Uint128VTable; -typedef struct Uint128Type { - mol2_cursor_t cur; - Uint128VTable *t; -} Uint128Type; - -typedef struct Byte32VTable { - uint32_t (*len)(struct Byte32Type *); - uint8_t (*get)(struct Byte32Type *, uint32_t, bool *); -} Byte32VTable; -typedef struct Byte32Type { - mol2_cursor_t cur; - Byte32VTable *t; -} Byte32Type; - -typedef struct Uint256VTable { - uint32_t (*len)(struct Uint256Type *); - uint8_t (*get)(struct Uint256Type *, uint32_t, bool *); -} Uint256VTable; -typedef struct Uint256Type { - mol2_cursor_t cur; - Uint256VTable *t; -} Uint256Type; - -typedef struct BytesVTable { - uint32_t (*len)(struct BytesType *); - uint8_t (*get)(struct BytesType *, uint32_t, bool *); -} BytesVTable; -typedef struct BytesType { - mol2_cursor_t cur; - BytesVTable *t; -} BytesType; - -typedef struct BytesOptVTable { - bool (*is_none)(struct BytesOptType *); - bool (*is_some)(struct BytesOptType *); - mol2_cursor_t (*unwrap)(struct BytesOptType *); -} BytesOptVTable; -typedef struct BytesOptType { - mol2_cursor_t cur; - BytesOptVTable *t; -} BytesOptType; - -typedef struct BytesVecVTable { - uint32_t (*len)(struct BytesVecType *); - mol2_cursor_t (*get)(struct BytesVecType *, uint32_t, bool *); -} BytesVecVTable; -typedef struct BytesVecType { - mol2_cursor_t cur; - BytesVecVTable *t; -} BytesVecType; - -typedef struct Byte32VecVTable { - uint32_t (*len)(struct Byte32VecType *); - mol2_cursor_t (*get)(struct Byte32VecType *, uint32_t, bool *); -} Byte32VecVTable; -typedef struct Byte32VecType { - mol2_cursor_t cur; - Byte32VecVTable *t; -} Byte32VecType; - -typedef struct ScriptOptVTable { - bool (*is_none)(struct ScriptOptType *); - bool (*is_some)(struct ScriptOptType *); - struct ScriptType (*unwrap)(struct ScriptOptType *); -} ScriptOptVTable; -typedef struct ScriptOptType { - mol2_cursor_t cur; - ScriptOptVTable *t; -} ScriptOptType; - -typedef struct ProposalShortIdVTable { - uint32_t (*len)(struct ProposalShortIdType *); - uint8_t (*get)(struct ProposalShortIdType *, uint32_t, bool *); -} ProposalShortIdVTable; -typedef struct ProposalShortIdType { - mol2_cursor_t cur; - ProposalShortIdVTable *t; -} ProposalShortIdType; - -typedef struct UncleBlockVecVTable { - uint32_t (*len)(struct UncleBlockVecType *); - struct UncleBlockType (*get)(struct UncleBlockVecType *, uint32_t, bool *); -} UncleBlockVecVTable; -typedef struct UncleBlockVecType { - mol2_cursor_t cur; - UncleBlockVecVTable *t; -} UncleBlockVecType; - -typedef struct TransactionVecVTable { - uint32_t (*len)(struct TransactionVecType *); - struct TransactionType (*get)(struct TransactionVecType *, uint32_t, bool *); -} TransactionVecVTable; -typedef struct TransactionVecType { - mol2_cursor_t cur; - TransactionVecVTable *t; -} TransactionVecType; - -typedef struct ProposalShortIdVecVTable { - uint32_t (*len)(struct ProposalShortIdVecType *); - mol2_cursor_t (*get)(struct ProposalShortIdVecType *, uint32_t, bool *); -} ProposalShortIdVecVTable; -typedef struct ProposalShortIdVecType { - mol2_cursor_t cur; - ProposalShortIdVecVTable *t; -} ProposalShortIdVecType; - -typedef struct CellDepVecVTable { - uint32_t (*len)(struct CellDepVecType *); - struct CellDepType (*get)(struct CellDepVecType *, uint32_t, bool *); -} CellDepVecVTable; -typedef struct CellDepVecType { - mol2_cursor_t cur; - CellDepVecVTable *t; -} CellDepVecType; - -typedef struct CellInputVecVTable { - uint32_t (*len)(struct CellInputVecType *); - struct CellInputType (*get)(struct CellInputVecType *, uint32_t, bool *); -} CellInputVecVTable; -typedef struct CellInputVecType { - mol2_cursor_t cur; - CellInputVecVTable *t; -} CellInputVecType; - -typedef struct CellOutputVecVTable { - uint32_t (*len)(struct CellOutputVecType *); - struct CellOutputType (*get)(struct CellOutputVecType *, uint32_t, bool *); -} CellOutputVecVTable; -typedef struct CellOutputVecType { - mol2_cursor_t cur; - CellOutputVecVTable *t; -} CellOutputVecType; - -typedef struct ScriptVTable { - mol2_cursor_t (*code_hash)(struct ScriptType *); - uint8_t (*hash_type)(struct ScriptType *); - mol2_cursor_t (*args)(struct ScriptType *); -} ScriptVTable; -typedef struct ScriptType { - mol2_cursor_t cur; - ScriptVTable *t; -} ScriptType; - -typedef struct OutPointVTable { - mol2_cursor_t (*tx_hash)(struct OutPointType *); - uint32_t (*index)(struct OutPointType *); -} OutPointVTable; -typedef struct OutPointType { - mol2_cursor_t cur; - OutPointVTable *t; -} OutPointType; - -typedef struct CellInputVTable { - uint64_t (*since)(struct CellInputType *); - struct OutPointType (*previous_output)(struct CellInputType *); -} CellInputVTable; -typedef struct CellInputType { - mol2_cursor_t cur; - CellInputVTable *t; -} CellInputType; - -typedef struct CellOutputVTable { - uint64_t (*capacity)(struct CellOutputType *); - struct ScriptType (*lock)(struct CellOutputType *); - struct ScriptOptType (*type_)(struct CellOutputType *); -} CellOutputVTable; -typedef struct CellOutputType { - mol2_cursor_t cur; - CellOutputVTable *t; -} CellOutputType; - -typedef struct CellDepVTable { - struct OutPointType (*out_point)(struct CellDepType *); - uint8_t (*dep_type)(struct CellDepType *); -} CellDepVTable; -typedef struct CellDepType { - mol2_cursor_t cur; - CellDepVTable *t; -} CellDepType; - -typedef struct RawTransactionVTable { - uint32_t (*version)(struct RawTransactionType *); - struct CellDepVecType (*cell_deps)(struct RawTransactionType *); - struct Byte32VecType (*header_deps)(struct RawTransactionType *); - struct CellInputVecType (*inputs)(struct RawTransactionType *); - struct CellOutputVecType (*outputs)(struct RawTransactionType *); - struct BytesVecType (*outputs_data)(struct RawTransactionType *); -} RawTransactionVTable; -typedef struct RawTransactionType { - mol2_cursor_t cur; - RawTransactionVTable *t; -} RawTransactionType; - -typedef struct TransactionVTable { - struct RawTransactionType (*raw)(struct TransactionType *); - struct BytesVecType (*witnesses)(struct TransactionType *); -} TransactionVTable; -typedef struct TransactionType { - mol2_cursor_t cur; - TransactionVTable *t; -} TransactionType; - -typedef struct RawHeaderVTable { - uint32_t (*version)(struct RawHeaderType *); - uint32_t (*compact_target)(struct RawHeaderType *); - uint64_t (*timestamp)(struct RawHeaderType *); - uint64_t (*number)(struct RawHeaderType *); - uint64_t (*epoch)(struct RawHeaderType *); - mol2_cursor_t (*parent_hash)(struct RawHeaderType *); - mol2_cursor_t (*transactions_root)(struct RawHeaderType *); - mol2_cursor_t (*proposals_hash)(struct RawHeaderType *); - mol2_cursor_t (*uncles_hash)(struct RawHeaderType *); - mol2_cursor_t (*dao)(struct RawHeaderType *); -} RawHeaderVTable; -typedef struct RawHeaderType { - mol2_cursor_t cur; - RawHeaderVTable *t; -} RawHeaderType; - -typedef struct HeaderVTable { - struct RawHeaderType (*raw)(struct HeaderType *); - mol2_cursor_t (*nonce)(struct HeaderType *); -} HeaderVTable; -typedef struct HeaderType { - mol2_cursor_t cur; - HeaderVTable *t; -} HeaderType; - -typedef struct UncleBlockVTable { - struct HeaderType (*header)(struct UncleBlockType *); - struct ProposalShortIdVecType (*proposals)(struct UncleBlockType *); -} UncleBlockVTable; -typedef struct UncleBlockType { - mol2_cursor_t cur; - UncleBlockVTable *t; -} UncleBlockType; - -typedef struct BlockVTable { - struct HeaderType (*header)(struct BlockType *); - struct UncleBlockVecType (*uncles)(struct BlockType *); - struct TransactionVecType (*transactions)(struct BlockType *); - struct ProposalShortIdVecType (*proposals)(struct BlockType *); -} BlockVTable; -typedef struct BlockType { - mol2_cursor_t cur; - BlockVTable *t; -} BlockType; - -typedef struct CellbaseWitnessVTable { - struct ScriptType (*lock)(struct CellbaseWitnessType *); - mol2_cursor_t (*message)(struct CellbaseWitnessType *); -} CellbaseWitnessVTable; -typedef struct CellbaseWitnessType { - mol2_cursor_t cur; - CellbaseWitnessVTable *t; -} CellbaseWitnessType; - -typedef struct WitnessArgsVTable { - struct BytesOptType (*lock)(struct WitnessArgsType *); - struct BytesOptType (*input_type)(struct WitnessArgsType *); - struct BytesOptType (*output_type)(struct WitnessArgsType *); -} WitnessArgsVTable; -typedef struct WitnessArgsType { - mol2_cursor_t cur; - WitnessArgsVTable *t; -} WitnessArgsType; - -#ifndef MOLECULEC_C2_DECLARATION_ONLY - -// ----implementation------------- -struct Uint32Type make_Uint32(mol2_cursor_t *cur) { - Uint32Type ret; - ret.cur = *cur; - ret.t = GetUint32VTable(); - return ret; -} -struct Uint32VTable *GetUint32VTable(void) { - static Uint32VTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Uint32_len_impl; - s_vtable.get = Uint32_get_impl; - return &s_vtable; -} -uint32_t Uint32_len_impl(Uint32Type *this) { return 4; } -uint8_t Uint32_get_impl(Uint32Type *this, uint32_t index, bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_slice_by_offset2(&this->cur, 1 * index, 1); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct Uint64Type make_Uint64(mol2_cursor_t *cur) { - Uint64Type ret; - ret.cur = *cur; - ret.t = GetUint64VTable(); - return ret; -} -struct Uint64VTable *GetUint64VTable(void) { - static Uint64VTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Uint64_len_impl; - s_vtable.get = Uint64_get_impl; - return &s_vtable; -} -uint32_t Uint64_len_impl(Uint64Type *this) { return 8; } -uint8_t Uint64_get_impl(Uint64Type *this, uint32_t index, bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_slice_by_offset2(&this->cur, 1 * index, 1); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct Uint128Type make_Uint128(mol2_cursor_t *cur) { - Uint128Type ret; - ret.cur = *cur; - ret.t = GetUint128VTable(); - return ret; -} -struct Uint128VTable *GetUint128VTable(void) { - static Uint128VTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Uint128_len_impl; - s_vtable.get = Uint128_get_impl; - return &s_vtable; -} -uint32_t Uint128_len_impl(Uint128Type *this) { return 16; } -uint8_t Uint128_get_impl(Uint128Type *this, uint32_t index, bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_slice_by_offset2(&this->cur, 1 * index, 1); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct Byte32Type make_Byte32(mol2_cursor_t *cur) { - Byte32Type ret; - ret.cur = *cur; - ret.t = GetByte32VTable(); - return ret; -} -struct Byte32VTable *GetByte32VTable(void) { - static Byte32VTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Byte32_len_impl; - s_vtable.get = Byte32_get_impl; - return &s_vtable; -} -uint32_t Byte32_len_impl(Byte32Type *this) { return 32; } -uint8_t Byte32_get_impl(Byte32Type *this, uint32_t index, bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_slice_by_offset2(&this->cur, 1 * index, 1); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct Uint256Type make_Uint256(mol2_cursor_t *cur) { - Uint256Type ret; - ret.cur = *cur; - ret.t = GetUint256VTable(); - return ret; -} -struct Uint256VTable *GetUint256VTable(void) { - static Uint256VTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Uint256_len_impl; - s_vtable.get = Uint256_get_impl; - return &s_vtable; -} -uint32_t Uint256_len_impl(Uint256Type *this) { return 32; } -uint8_t Uint256_get_impl(Uint256Type *this, uint32_t index, bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_slice_by_offset2(&this->cur, 1 * index, 1); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct BytesType make_Bytes(mol2_cursor_t *cur) { - BytesType ret; - ret.cur = *cur; - ret.t = GetBytesVTable(); - return ret; -} -struct BytesVTable *GetBytesVTable(void) { - static BytesVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Bytes_len_impl; - s_vtable.get = Bytes_get_impl; - return &s_vtable; -} -uint32_t Bytes_len_impl(BytesType *this) { - return mol2_fixvec_length(&this->cur); -} -uint8_t Bytes_get_impl(BytesType *this, uint32_t index, bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_fixvec_slice_by_index(&this->cur, 1, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct BytesOptType make_BytesOpt(mol2_cursor_t *cur) { - BytesOptType ret; - ret.cur = *cur; - ret.t = GetBytesOptVTable(); - return ret; -} -struct BytesOptVTable *GetBytesOptVTable(void) { - static BytesOptVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.is_none = BytesOpt_is_none_impl; - s_vtable.is_some = BytesOpt_is_some_impl; - s_vtable.unwrap = BytesOpt_unwrap_impl; - return &s_vtable; -} -bool BytesOpt_is_none_impl(BytesOptType *this) { - return mol2_option_is_none(&this->cur); -} -bool BytesOpt_is_some_impl(BytesOptType *this) { - return !mol2_option_is_none(&this->cur); -} -mol2_cursor_t BytesOpt_unwrap_impl(BytesOptType *this) { - mol2_cursor_t ret; - ret = convert_to_rawbytes(&this->cur); - return ret; -} -struct BytesVecType make_BytesVec(mol2_cursor_t *cur) { - BytesVecType ret; - ret.cur = *cur; - ret.t = GetBytesVecVTable(); - return ret; -} -struct BytesVecVTable *GetBytesVecVTable(void) { - static BytesVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = BytesVec_len_impl; - s_vtable.get = BytesVec_get_impl; - return &s_vtable; -} -uint32_t BytesVec_len_impl(BytesVecType *this) { - return mol2_dynvec_length(&this->cur); -} -mol2_cursor_t BytesVec_get_impl(BytesVecType *this, uint32_t index, - bool *existing) { - mol2_cursor_t ret = {0}; - mol2_cursor_res_t res = mol2_dynvec_slice_by_index(&this->cur, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - return convert_to_rawbytes(&res.cur); -} -struct Byte32VecType make_Byte32Vec(mol2_cursor_t *cur) { - Byte32VecType ret; - ret.cur = *cur; - ret.t = GetByte32VecVTable(); - return ret; -} -struct Byte32VecVTable *GetByte32VecVTable(void) { - static Byte32VecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = Byte32Vec_len_impl; - s_vtable.get = Byte32Vec_get_impl; - return &s_vtable; -} -uint32_t Byte32Vec_len_impl(Byte32VecType *this) { - return mol2_fixvec_length(&this->cur); -} -mol2_cursor_t Byte32Vec_get_impl(Byte32VecType *this, uint32_t index, - bool *existing) { - mol2_cursor_t ret = {0}; - mol2_cursor_res_t res = mol2_fixvec_slice_by_index(&this->cur, 32, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_array(&res.cur); - return ret; -} -struct ScriptOptType make_ScriptOpt(mol2_cursor_t *cur) { - ScriptOptType ret; - ret.cur = *cur; - ret.t = GetScriptOptVTable(); - return ret; -} -struct ScriptOptVTable *GetScriptOptVTable(void) { - static ScriptOptVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.is_none = ScriptOpt_is_none_impl; - s_vtable.is_some = ScriptOpt_is_some_impl; - s_vtable.unwrap = ScriptOpt_unwrap_impl; - return &s_vtable; -} -bool ScriptOpt_is_none_impl(ScriptOptType *this) { - return mol2_option_is_none(&this->cur); -} -bool ScriptOpt_is_some_impl(ScriptOptType *this) { - return !mol2_option_is_none(&this->cur); -} -ScriptType ScriptOpt_unwrap_impl(ScriptOptType *this) { - ScriptType ret; - mol2_cursor_t cur = this->cur; - ret.cur = cur; - ret.t = GetScriptVTable(); - return ret; -} -struct ProposalShortIdType make_ProposalShortId(mol2_cursor_t *cur) { - ProposalShortIdType ret; - ret.cur = *cur; - ret.t = GetProposalShortIdVTable(); - return ret; -} -struct ProposalShortIdVTable *GetProposalShortIdVTable(void) { - static ProposalShortIdVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = ProposalShortId_len_impl; - s_vtable.get = ProposalShortId_get_impl; - return &s_vtable; -} -uint32_t ProposalShortId_len_impl(ProposalShortIdType *this) { return 10; } -uint8_t ProposalShortId_get_impl(ProposalShortIdType *this, uint32_t index, - bool *existing) { - uint8_t ret = {0}; - mol2_cursor_res_t res = mol2_slice_by_offset2(&this->cur, 1 * index, 1); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_Uint8(&res.cur); - return ret; -} -struct UncleBlockVecType make_UncleBlockVec(mol2_cursor_t *cur) { - UncleBlockVecType ret; - ret.cur = *cur; - ret.t = GetUncleBlockVecVTable(); - return ret; -} -struct UncleBlockVecVTable *GetUncleBlockVecVTable(void) { - static UncleBlockVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = UncleBlockVec_len_impl; - s_vtable.get = UncleBlockVec_get_impl; - return &s_vtable; -} -uint32_t UncleBlockVec_len_impl(UncleBlockVecType *this) { - return mol2_dynvec_length(&this->cur); -} -UncleBlockType UncleBlockVec_get_impl(UncleBlockVecType *this, uint32_t index, - bool *existing) { - UncleBlockType ret = {0}; - mol2_cursor_res_t res = mol2_dynvec_slice_by_index(&this->cur, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret.cur = res.cur; - ret.t = GetUncleBlockVTable(); - return ret; -} -struct TransactionVecType make_TransactionVec(mol2_cursor_t *cur) { - TransactionVecType ret; - ret.cur = *cur; - ret.t = GetTransactionVecVTable(); - return ret; -} -struct TransactionVecVTable *GetTransactionVecVTable(void) { - static TransactionVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = TransactionVec_len_impl; - s_vtable.get = TransactionVec_get_impl; - return &s_vtable; -} -uint32_t TransactionVec_len_impl(TransactionVecType *this) { - return mol2_dynvec_length(&this->cur); -} -TransactionType TransactionVec_get_impl(TransactionVecType *this, - uint32_t index, bool *existing) { - TransactionType ret = {0}; - mol2_cursor_res_t res = mol2_dynvec_slice_by_index(&this->cur, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret.cur = res.cur; - ret.t = GetTransactionVTable(); - return ret; -} -struct ProposalShortIdVecType make_ProposalShortIdVec(mol2_cursor_t *cur) { - ProposalShortIdVecType ret; - ret.cur = *cur; - ret.t = GetProposalShortIdVecVTable(); - return ret; -} -struct ProposalShortIdVecVTable *GetProposalShortIdVecVTable(void) { - static ProposalShortIdVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = ProposalShortIdVec_len_impl; - s_vtable.get = ProposalShortIdVec_get_impl; - return &s_vtable; -} -uint32_t ProposalShortIdVec_len_impl(ProposalShortIdVecType *this) { - return mol2_fixvec_length(&this->cur); -} -mol2_cursor_t ProposalShortIdVec_get_impl(ProposalShortIdVecType *this, - uint32_t index, bool *existing) { - mol2_cursor_t ret = {0}; - mol2_cursor_res_t res = mol2_fixvec_slice_by_index(&this->cur, 10, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret = convert_to_array(&res.cur); - return ret; -} -struct CellDepVecType make_CellDepVec(mol2_cursor_t *cur) { - CellDepVecType ret; - ret.cur = *cur; - ret.t = GetCellDepVecVTable(); - return ret; -} -struct CellDepVecVTable *GetCellDepVecVTable(void) { - static CellDepVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = CellDepVec_len_impl; - s_vtable.get = CellDepVec_get_impl; - return &s_vtable; -} -uint32_t CellDepVec_len_impl(CellDepVecType *this) { - return mol2_fixvec_length(&this->cur); -} -CellDepType CellDepVec_get_impl(CellDepVecType *this, uint32_t index, - bool *existing) { - CellDepType ret = {0}; - mol2_cursor_res_t res = mol2_fixvec_slice_by_index(&this->cur, 37, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret.cur = res.cur; - ret.t = GetCellDepVTable(); - return ret; -} -struct CellInputVecType make_CellInputVec(mol2_cursor_t *cur) { - CellInputVecType ret; - ret.cur = *cur; - ret.t = GetCellInputVecVTable(); - return ret; -} -struct CellInputVecVTable *GetCellInputVecVTable(void) { - static CellInputVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = CellInputVec_len_impl; - s_vtable.get = CellInputVec_get_impl; - return &s_vtable; -} -uint32_t CellInputVec_len_impl(CellInputVecType *this) { - return mol2_fixvec_length(&this->cur); -} -CellInputType CellInputVec_get_impl(CellInputVecType *this, uint32_t index, - bool *existing) { - CellInputType ret = {0}; - mol2_cursor_res_t res = mol2_fixvec_slice_by_index(&this->cur, 44, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret.cur = res.cur; - ret.t = GetCellInputVTable(); - return ret; -} -struct CellOutputVecType make_CellOutputVec(mol2_cursor_t *cur) { - CellOutputVecType ret; - ret.cur = *cur; - ret.t = GetCellOutputVecVTable(); - return ret; -} -struct CellOutputVecVTable *GetCellOutputVecVTable(void) { - static CellOutputVecVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.len = CellOutputVec_len_impl; - s_vtable.get = CellOutputVec_get_impl; - return &s_vtable; -} -uint32_t CellOutputVec_len_impl(CellOutputVecType *this) { - return mol2_dynvec_length(&this->cur); -} -CellOutputType CellOutputVec_get_impl(CellOutputVecType *this, uint32_t index, - bool *existing) { - CellOutputType ret = {0}; - mol2_cursor_res_t res = mol2_dynvec_slice_by_index(&this->cur, index); - if (res.errno != MOL2_OK) { - *existing = false; - return ret; - } else { - *existing = true; - } - ret.cur = res.cur; - ret.t = GetCellOutputVTable(); - return ret; -} -struct ScriptType make_Script(mol2_cursor_t *cur) { - ScriptType ret; - ret.cur = *cur; - ret.t = GetScriptVTable(); - return ret; -} -struct ScriptVTable *GetScriptVTable(void) { - static ScriptVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.code_hash = Script_get_code_hash_impl; - s_vtable.hash_type = Script_get_hash_type_impl; - s_vtable.args = Script_get_args_impl; - return &s_vtable; -} -mol2_cursor_t Script_get_code_hash_impl(ScriptType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_table_slice_by_index(&this->cur, 0); - ret = convert_to_array(&ret2); - return ret; -} -uint8_t Script_get_hash_type_impl(ScriptType *this) { - uint8_t ret; - mol2_cursor_t ret2 = mol2_table_slice_by_index(&this->cur, 1); - ret = convert_to_Uint8(&ret2); - return ret; -} -mol2_cursor_t Script_get_args_impl(ScriptType *this) { - mol2_cursor_t ret; - mol2_cursor_t re2 = mol2_table_slice_by_index(&this->cur, 2); - ret = convert_to_rawbytes(&re2); - return ret; -} -struct OutPointType make_OutPoint(mol2_cursor_t *cur) { - OutPointType ret; - ret.cur = *cur; - ret.t = GetOutPointVTable(); - return ret; -} -struct OutPointVTable *GetOutPointVTable(void) { - static OutPointVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.tx_hash = OutPoint_get_tx_hash_impl; - s_vtable.index = OutPoint_get_index_impl; - return &s_vtable; -} -mol2_cursor_t OutPoint_get_tx_hash_impl(OutPointType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 0, 32); - ret = convert_to_array(&ret2); - return ret; -} -uint32_t OutPoint_get_index_impl(OutPointType *this) { - uint32_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 32, 4); - ret = convert_to_Uint32(&ret2); - return ret; -} -struct CellInputType make_CellInput(mol2_cursor_t *cur) { - CellInputType ret; - ret.cur = *cur; - ret.t = GetCellInputVTable(); - return ret; -} -struct CellInputVTable *GetCellInputVTable(void) { - static CellInputVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.since = CellInput_get_since_impl; - s_vtable.previous_output = CellInput_get_previous_output_impl; - return &s_vtable; -} -uint64_t CellInput_get_since_impl(CellInputType *this) { - uint64_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 0, 8); - ret = convert_to_Uint64(&ret2); - return ret; -} -OutPointType CellInput_get_previous_output_impl(CellInputType *this) { - OutPointType ret; - mol2_cursor_t cur = mol2_slice_by_offset(&this->cur, 8, 36); - ret.cur = cur; - ret.t = GetOutPointVTable(); - return ret; -} -struct CellOutputType make_CellOutput(mol2_cursor_t *cur) { - CellOutputType ret; - ret.cur = *cur; - ret.t = GetCellOutputVTable(); - return ret; -} -struct CellOutputVTable *GetCellOutputVTable(void) { - static CellOutputVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.capacity = CellOutput_get_capacity_impl; - s_vtable.lock = CellOutput_get_lock_impl; - s_vtable.type_ = CellOutput_get_type__impl; - return &s_vtable; -} -uint64_t CellOutput_get_capacity_impl(CellOutputType *this) { - uint64_t ret; - mol2_cursor_t ret2 = mol2_table_slice_by_index(&this->cur, 0); - ret = convert_to_Uint64(&ret2); - return ret; -} -ScriptType CellOutput_get_lock_impl(CellOutputType *this) { - ScriptType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 1); - ret.cur = cur; - ret.t = GetScriptVTable(); - return ret; -} -ScriptOptType CellOutput_get_type__impl(CellOutputType *this) { - ScriptOptType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 2); - ret.cur = cur; - ret.t = GetScriptOptVTable(); - return ret; -} -struct CellDepType make_CellDep(mol2_cursor_t *cur) { - CellDepType ret; - ret.cur = *cur; - ret.t = GetCellDepVTable(); - return ret; -} -struct CellDepVTable *GetCellDepVTable(void) { - static CellDepVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.out_point = CellDep_get_out_point_impl; - s_vtable.dep_type = CellDep_get_dep_type_impl; - return &s_vtable; -} -OutPointType CellDep_get_out_point_impl(CellDepType *this) { - OutPointType ret; - mol2_cursor_t cur = mol2_slice_by_offset(&this->cur, 0, 36); - ret.cur = cur; - ret.t = GetOutPointVTable(); - return ret; -} -uint8_t CellDep_get_dep_type_impl(CellDepType *this) { - uint8_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 36, 1); - ret = convert_to_Uint8(&ret2); - return ret; -} -struct RawTransactionType make_RawTransaction(mol2_cursor_t *cur) { - RawTransactionType ret; - ret.cur = *cur; - ret.t = GetRawTransactionVTable(); - return ret; -} -struct RawTransactionVTable *GetRawTransactionVTable(void) { - static RawTransactionVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.version = RawTransaction_get_version_impl; - s_vtable.cell_deps = RawTransaction_get_cell_deps_impl; - s_vtable.header_deps = RawTransaction_get_header_deps_impl; - s_vtable.inputs = RawTransaction_get_inputs_impl; - s_vtable.outputs = RawTransaction_get_outputs_impl; - s_vtable.outputs_data = RawTransaction_get_outputs_data_impl; - return &s_vtable; -} -uint32_t RawTransaction_get_version_impl(RawTransactionType *this) { - uint32_t ret; - mol2_cursor_t ret2 = mol2_table_slice_by_index(&this->cur, 0); - ret = convert_to_Uint32(&ret2); - return ret; -} -CellDepVecType RawTransaction_get_cell_deps_impl(RawTransactionType *this) { - CellDepVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 1); - ret.cur = cur; - ret.t = GetCellDepVecVTable(); - return ret; -} -Byte32VecType RawTransaction_get_header_deps_impl(RawTransactionType *this) { - Byte32VecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 2); - ret.cur = cur; - ret.t = GetByte32VecVTable(); - return ret; -} -CellInputVecType RawTransaction_get_inputs_impl(RawTransactionType *this) { - CellInputVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 3); - ret.cur = cur; - ret.t = GetCellInputVecVTable(); - return ret; -} -CellOutputVecType RawTransaction_get_outputs_impl(RawTransactionType *this) { - CellOutputVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 4); - ret.cur = cur; - ret.t = GetCellOutputVecVTable(); - return ret; -} -BytesVecType RawTransaction_get_outputs_data_impl(RawTransactionType *this) { - BytesVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 5); - ret.cur = cur; - ret.t = GetBytesVecVTable(); - return ret; -} -struct TransactionType make_Transaction(mol2_cursor_t *cur) { - TransactionType ret; - ret.cur = *cur; - ret.t = GetTransactionVTable(); - return ret; -} -struct TransactionVTable *GetTransactionVTable(void) { - static TransactionVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.raw = Transaction_get_raw_impl; - s_vtable.witnesses = Transaction_get_witnesses_impl; - return &s_vtable; -} -RawTransactionType Transaction_get_raw_impl(TransactionType *this) { - RawTransactionType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 0); - ret.cur = cur; - ret.t = GetRawTransactionVTable(); - return ret; -} -BytesVecType Transaction_get_witnesses_impl(TransactionType *this) { - BytesVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 1); - ret.cur = cur; - ret.t = GetBytesVecVTable(); - return ret; -} -struct RawHeaderType make_RawHeader(mol2_cursor_t *cur) { - RawHeaderType ret; - ret.cur = *cur; - ret.t = GetRawHeaderVTable(); - return ret; -} -struct RawHeaderVTable *GetRawHeaderVTable(void) { - static RawHeaderVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.version = RawHeader_get_version_impl; - s_vtable.compact_target = RawHeader_get_compact_target_impl; - s_vtable.timestamp = RawHeader_get_timestamp_impl; - s_vtable.number = RawHeader_get_number_impl; - s_vtable.epoch = RawHeader_get_epoch_impl; - s_vtable.parent_hash = RawHeader_get_parent_hash_impl; - s_vtable.transactions_root = RawHeader_get_transactions_root_impl; - s_vtable.proposals_hash = RawHeader_get_proposals_hash_impl; - s_vtable.uncles_hash = RawHeader_get_uncles_hash_impl; - s_vtable.dao = RawHeader_get_dao_impl; - return &s_vtable; -} -uint32_t RawHeader_get_version_impl(RawHeaderType *this) { - uint32_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 0, 4); - ret = convert_to_Uint32(&ret2); - return ret; -} -uint32_t RawHeader_get_compact_target_impl(RawHeaderType *this) { - uint32_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 4, 4); - ret = convert_to_Uint32(&ret2); - return ret; -} -uint64_t RawHeader_get_timestamp_impl(RawHeaderType *this) { - uint64_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 8, 8); - ret = convert_to_Uint64(&ret2); - return ret; -} -uint64_t RawHeader_get_number_impl(RawHeaderType *this) { - uint64_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 16, 8); - ret = convert_to_Uint64(&ret2); - return ret; -} -uint64_t RawHeader_get_epoch_impl(RawHeaderType *this) { - uint64_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 24, 8); - ret = convert_to_Uint64(&ret2); - return ret; -} -mol2_cursor_t RawHeader_get_parent_hash_impl(RawHeaderType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 32, 32); - ret = convert_to_array(&ret2); - return ret; -} -mol2_cursor_t RawHeader_get_transactions_root_impl(RawHeaderType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 64, 32); - ret = convert_to_array(&ret2); - return ret; -} -mol2_cursor_t RawHeader_get_proposals_hash_impl(RawHeaderType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 96, 32); - ret = convert_to_array(&ret2); - return ret; -} -mol2_cursor_t RawHeader_get_uncles_hash_impl(RawHeaderType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 128, 32); - ret = convert_to_array(&ret2); - return ret; -} -mol2_cursor_t RawHeader_get_dao_impl(RawHeaderType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 160, 32); - ret = convert_to_array(&ret2); - return ret; -} -struct HeaderType make_Header(mol2_cursor_t *cur) { - HeaderType ret; - ret.cur = *cur; - ret.t = GetHeaderVTable(); - return ret; -} -struct HeaderVTable *GetHeaderVTable(void) { - static HeaderVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.raw = Header_get_raw_impl; - s_vtable.nonce = Header_get_nonce_impl; - return &s_vtable; -} -RawHeaderType Header_get_raw_impl(HeaderType *this) { - RawHeaderType ret; - mol2_cursor_t cur = mol2_slice_by_offset(&this->cur, 0, 192); - ret.cur = cur; - ret.t = GetRawHeaderVTable(); - return ret; -} -mol2_cursor_t Header_get_nonce_impl(HeaderType *this) { - mol2_cursor_t ret; - mol2_cursor_t ret2 = mol2_slice_by_offset(&this->cur, 192, 16); - ret = convert_to_array(&ret2); - return ret; -} -struct UncleBlockType make_UncleBlock(mol2_cursor_t *cur) { - UncleBlockType ret; - ret.cur = *cur; - ret.t = GetUncleBlockVTable(); - return ret; -} -struct UncleBlockVTable *GetUncleBlockVTable(void) { - static UncleBlockVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.header = UncleBlock_get_header_impl; - s_vtable.proposals = UncleBlock_get_proposals_impl; - return &s_vtable; -} -HeaderType UncleBlock_get_header_impl(UncleBlockType *this) { - HeaderType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 0); - ret.cur = cur; - ret.t = GetHeaderVTable(); - return ret; -} -ProposalShortIdVecType UncleBlock_get_proposals_impl(UncleBlockType *this) { - ProposalShortIdVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 1); - ret.cur = cur; - ret.t = GetProposalShortIdVecVTable(); - return ret; -} -struct BlockType make_Block(mol2_cursor_t *cur) { - BlockType ret; - ret.cur = *cur; - ret.t = GetBlockVTable(); - return ret; -} -struct BlockVTable *GetBlockVTable(void) { - static BlockVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.header = Block_get_header_impl; - s_vtable.uncles = Block_get_uncles_impl; - s_vtable.transactions = Block_get_transactions_impl; - s_vtable.proposals = Block_get_proposals_impl; - return &s_vtable; -} -HeaderType Block_get_header_impl(BlockType *this) { - HeaderType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 0); - ret.cur = cur; - ret.t = GetHeaderVTable(); - return ret; -} -UncleBlockVecType Block_get_uncles_impl(BlockType *this) { - UncleBlockVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 1); - ret.cur = cur; - ret.t = GetUncleBlockVecVTable(); - return ret; -} -TransactionVecType Block_get_transactions_impl(BlockType *this) { - TransactionVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 2); - ret.cur = cur; - ret.t = GetTransactionVecVTable(); - return ret; -} -ProposalShortIdVecType Block_get_proposals_impl(BlockType *this) { - ProposalShortIdVecType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 3); - ret.cur = cur; - ret.t = GetProposalShortIdVecVTable(); - return ret; -} -struct CellbaseWitnessType make_CellbaseWitness(mol2_cursor_t *cur) { - CellbaseWitnessType ret; - ret.cur = *cur; - ret.t = GetCellbaseWitnessVTable(); - return ret; -} -struct CellbaseWitnessVTable *GetCellbaseWitnessVTable(void) { - static CellbaseWitnessVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.lock = CellbaseWitness_get_lock_impl; - s_vtable.message = CellbaseWitness_get_message_impl; - return &s_vtable; -} -ScriptType CellbaseWitness_get_lock_impl(CellbaseWitnessType *this) { - ScriptType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 0); - ret.cur = cur; - ret.t = GetScriptVTable(); - return ret; -} -mol2_cursor_t CellbaseWitness_get_message_impl(CellbaseWitnessType *this) { - mol2_cursor_t ret; - mol2_cursor_t re2 = mol2_table_slice_by_index(&this->cur, 1); - ret = convert_to_rawbytes(&re2); - return ret; -} -struct WitnessArgsType make_WitnessArgs(mol2_cursor_t *cur) { - WitnessArgsType ret; - ret.cur = *cur; - ret.t = GetWitnessArgsVTable(); - return ret; -} -struct WitnessArgsVTable *GetWitnessArgsVTable(void) { - static WitnessArgsVTable s_vtable; - static int inited = 0; - if (inited) return &s_vtable; - s_vtable.lock = WitnessArgs_get_lock_impl; - s_vtable.input_type = WitnessArgs_get_input_type_impl; - s_vtable.output_type = WitnessArgs_get_output_type_impl; - return &s_vtable; -} -BytesOptType WitnessArgs_get_lock_impl(WitnessArgsType *this) { - BytesOptType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 0); - ret.cur = cur; - ret.t = GetBytesOptVTable(); - return ret; -} -BytesOptType WitnessArgs_get_input_type_impl(WitnessArgsType *this) { - BytesOptType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 1); - ret.cur = cur; - ret.t = GetBytesOptVTable(); - return ret; -} -BytesOptType WitnessArgs_get_output_type_impl(WitnessArgsType *this) { - BytesOptType ret; - mol2_cursor_t cur = mol2_table_slice_by_index(&this->cur, 2); - ret.cur = cur; - ret.t = GetBytesOptVTable(); - return ret; -} -#endif // MOLECULEC_C2_DECLARATION_ONLY - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif // _BLOCKCHAIN_API2_H_ diff --git a/include/ckb-c-stdlib/molecule/blockchain.h b/include/ckb-c-stdlib/molecule/blockchain.h deleted file mode 100644 index 42c5e63..0000000 --- a/include/ckb-c-stdlib/molecule/blockchain.h +++ /dev/null @@ -1,2075 +0,0 @@ -// Generated by Molecule 0.7.1 - -#define MOLECULEC_VERSION 7001 -#define MOLECULE_API_VERSION_MIN 7000 - -#include "molecule_reader.h" -#include "molecule_builder.h" - -#ifndef BLOCKCHAIN_H -#define BLOCKCHAIN_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef MOLECULE_API_DECORATOR -#define __DEFINE_MOLECULE_API_DECORATOR_BLOCKCHAIN -#define MOLECULE_API_DECORATOR -#endif /* MOLECULE_API_DECORATOR */ - -/* - * Reader APIs - */ - -#define MolReader_Uint32_verify(s, c) mol_verify_fixed_size(s, 4) -#define MolReader_Uint32_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint32_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint32_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint32_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint64_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_Uint64_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint64_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint64_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint64_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint64_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Uint64_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Uint64_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Uint64_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Uint128_verify(s, c) mol_verify_fixed_size(s, 16) -#define MolReader_Uint128_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint128_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint128_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint128_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint128_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Uint128_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Uint128_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Uint128_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Uint128_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_Uint128_get_nth9(s) mol_slice_by_offset(s, 9, 1) -#define MolReader_Uint128_get_nth10(s) mol_slice_by_offset(s, 10, 1) -#define MolReader_Uint128_get_nth11(s) mol_slice_by_offset(s, 11, 1) -#define MolReader_Uint128_get_nth12(s) mol_slice_by_offset(s, 12, 1) -#define MolReader_Uint128_get_nth13(s) mol_slice_by_offset(s, 13, 1) -#define MolReader_Uint128_get_nth14(s) mol_slice_by_offset(s, 14, 1) -#define MolReader_Uint128_get_nth15(s) mol_slice_by_offset(s, 15, 1) -#define MolReader_Byte32_verify(s, c) mol_verify_fixed_size(s, 32) -#define MolReader_Byte32_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Byte32_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Byte32_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Byte32_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Byte32_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Byte32_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Byte32_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Byte32_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Byte32_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_Byte32_get_nth9(s) mol_slice_by_offset(s, 9, 1) -#define MolReader_Byte32_get_nth10(s) mol_slice_by_offset(s, 10, 1) -#define MolReader_Byte32_get_nth11(s) mol_slice_by_offset(s, 11, 1) -#define MolReader_Byte32_get_nth12(s) mol_slice_by_offset(s, 12, 1) -#define MolReader_Byte32_get_nth13(s) mol_slice_by_offset(s, 13, 1) -#define MolReader_Byte32_get_nth14(s) mol_slice_by_offset(s, 14, 1) -#define MolReader_Byte32_get_nth15(s) mol_slice_by_offset(s, 15, 1) -#define MolReader_Byte32_get_nth16(s) mol_slice_by_offset(s, 16, 1) -#define MolReader_Byte32_get_nth17(s) mol_slice_by_offset(s, 17, 1) -#define MolReader_Byte32_get_nth18(s) mol_slice_by_offset(s, 18, 1) -#define MolReader_Byte32_get_nth19(s) mol_slice_by_offset(s, 19, 1) -#define MolReader_Byte32_get_nth20(s) mol_slice_by_offset(s, 20, 1) -#define MolReader_Byte32_get_nth21(s) mol_slice_by_offset(s, 21, 1) -#define MolReader_Byte32_get_nth22(s) mol_slice_by_offset(s, 22, 1) -#define MolReader_Byte32_get_nth23(s) mol_slice_by_offset(s, 23, 1) -#define MolReader_Byte32_get_nth24(s) mol_slice_by_offset(s, 24, 1) -#define MolReader_Byte32_get_nth25(s) mol_slice_by_offset(s, 25, 1) -#define MolReader_Byte32_get_nth26(s) mol_slice_by_offset(s, 26, 1) -#define MolReader_Byte32_get_nth27(s) mol_slice_by_offset(s, 27, 1) -#define MolReader_Byte32_get_nth28(s) mol_slice_by_offset(s, 28, 1) -#define MolReader_Byte32_get_nth29(s) mol_slice_by_offset(s, 29, 1) -#define MolReader_Byte32_get_nth30(s) mol_slice_by_offset(s, 30, 1) -#define MolReader_Byte32_get_nth31(s) mol_slice_by_offset(s, 31, 1) -#define MolReader_Uint256_verify(s, c) mol_verify_fixed_size(s, 32) -#define MolReader_Uint256_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint256_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint256_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint256_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint256_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Uint256_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Uint256_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Uint256_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Uint256_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_Uint256_get_nth9(s) mol_slice_by_offset(s, 9, 1) -#define MolReader_Uint256_get_nth10(s) mol_slice_by_offset(s, 10, 1) -#define MolReader_Uint256_get_nth11(s) mol_slice_by_offset(s, 11, 1) -#define MolReader_Uint256_get_nth12(s) mol_slice_by_offset(s, 12, 1) -#define MolReader_Uint256_get_nth13(s) mol_slice_by_offset(s, 13, 1) -#define MolReader_Uint256_get_nth14(s) mol_slice_by_offset(s, 14, 1) -#define MolReader_Uint256_get_nth15(s) mol_slice_by_offset(s, 15, 1) -#define MolReader_Uint256_get_nth16(s) mol_slice_by_offset(s, 16, 1) -#define MolReader_Uint256_get_nth17(s) mol_slice_by_offset(s, 17, 1) -#define MolReader_Uint256_get_nth18(s) mol_slice_by_offset(s, 18, 1) -#define MolReader_Uint256_get_nth19(s) mol_slice_by_offset(s, 19, 1) -#define MolReader_Uint256_get_nth20(s) mol_slice_by_offset(s, 20, 1) -#define MolReader_Uint256_get_nth21(s) mol_slice_by_offset(s, 21, 1) -#define MolReader_Uint256_get_nth22(s) mol_slice_by_offset(s, 22, 1) -#define MolReader_Uint256_get_nth23(s) mol_slice_by_offset(s, 23, 1) -#define MolReader_Uint256_get_nth24(s) mol_slice_by_offset(s, 24, 1) -#define MolReader_Uint256_get_nth25(s) mol_slice_by_offset(s, 25, 1) -#define MolReader_Uint256_get_nth26(s) mol_slice_by_offset(s, 26, 1) -#define MolReader_Uint256_get_nth27(s) mol_slice_by_offset(s, 27, 1) -#define MolReader_Uint256_get_nth28(s) mol_slice_by_offset(s, 28, 1) -#define MolReader_Uint256_get_nth29(s) mol_slice_by_offset(s, 29, 1) -#define MolReader_Uint256_get_nth30(s) mol_slice_by_offset(s, 30, 1) -#define MolReader_Uint256_get_nth31(s) mol_slice_by_offset(s, 31, 1) -#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) -#define MolReader_Bytes_length(s) mol_fixvec_length(s) -#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) -#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) -MOLECULE_API_DECORATOR mol_errno MolReader_BytesOpt_verify (const mol_seg_t*, bool); -#define MolReader_BytesOpt_is_none(s) mol_option_is_none(s) -MOLECULE_API_DECORATOR mol_errno MolReader_BytesVec_verify (const mol_seg_t*, bool); -#define MolReader_BytesVec_length(s) mol_dynvec_length(s) -#define MolReader_BytesVec_get(s, i) mol_dynvec_slice_by_index(s, i) -#define MolReader_Byte32Vec_verify(s, c) mol_fixvec_verify(s, 32) -#define MolReader_Byte32Vec_length(s) mol_fixvec_length(s) -#define MolReader_Byte32Vec_get(s, i) mol_fixvec_slice_by_index(s, 32, i) -MOLECULE_API_DECORATOR mol_errno MolReader_ScriptOpt_verify (const mol_seg_t*, bool); -#define MolReader_ScriptOpt_is_none(s) mol_option_is_none(s) -#define MolReader_ProposalShortId_verify(s, c) mol_verify_fixed_size(s, 10) -#define MolReader_ProposalShortId_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_ProposalShortId_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_ProposalShortId_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_ProposalShortId_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_ProposalShortId_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_ProposalShortId_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_ProposalShortId_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_ProposalShortId_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_ProposalShortId_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_ProposalShortId_get_nth9(s) mol_slice_by_offset(s, 9, 1) -MOLECULE_API_DECORATOR mol_errno MolReader_UncleBlockVec_verify (const mol_seg_t*, bool); -#define MolReader_UncleBlockVec_length(s) mol_dynvec_length(s) -#define MolReader_UncleBlockVec_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_TransactionVec_verify (const mol_seg_t*, bool); -#define MolReader_TransactionVec_length(s) mol_dynvec_length(s) -#define MolReader_TransactionVec_get(s, i) mol_dynvec_slice_by_index(s, i) -#define MolReader_ProposalShortIdVec_verify(s, c) mol_fixvec_verify(s, 10) -#define MolReader_ProposalShortIdVec_length(s) mol_fixvec_length(s) -#define MolReader_ProposalShortIdVec_get(s, i) mol_fixvec_slice_by_index(s, 10, i) -#define MolReader_CellDepVec_verify(s, c) mol_fixvec_verify(s, 37) -#define MolReader_CellDepVec_length(s) mol_fixvec_length(s) -#define MolReader_CellDepVec_get(s, i) mol_fixvec_slice_by_index(s, 37, i) -#define MolReader_CellInputVec_verify(s, c) mol_fixvec_verify(s, 44) -#define MolReader_CellInputVec_length(s) mol_fixvec_length(s) -#define MolReader_CellInputVec_get(s, i) mol_fixvec_slice_by_index(s, 44, i) -MOLECULE_API_DECORATOR mol_errno MolReader_CellOutputVec_verify (const mol_seg_t*, bool); -#define MolReader_CellOutputVec_length(s) mol_dynvec_length(s) -#define MolReader_CellOutputVec_get(s, i) mol_dynvec_slice_by_index(s, i) -MOLECULE_API_DECORATOR mol_errno MolReader_Script_verify (const mol_seg_t*, bool); -#define MolReader_Script_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Script_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Script_get_code_hash(s) mol_table_slice_by_index(s, 0) -#define MolReader_Script_get_hash_type(s) mol_table_slice_by_index(s, 1) -#define MolReader_Script_get_args(s) mol_table_slice_by_index(s, 2) -#define MolReader_OutPoint_verify(s, c) mol_verify_fixed_size(s, 36) -#define MolReader_OutPoint_get_tx_hash(s) mol_slice_by_offset(s, 0, 32) -#define MolReader_OutPoint_get_index(s) mol_slice_by_offset(s, 32, 4) -#define MolReader_CellInput_verify(s, c) mol_verify_fixed_size(s, 44) -#define MolReader_CellInput_get_since(s) mol_slice_by_offset(s, 0, 8) -#define MolReader_CellInput_get_previous_output(s) mol_slice_by_offset(s, 8, 36) -MOLECULE_API_DECORATOR mol_errno MolReader_CellOutput_verify (const mol_seg_t*, bool); -#define MolReader_CellOutput_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_CellOutput_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_CellOutput_get_capacity(s) mol_table_slice_by_index(s, 0) -#define MolReader_CellOutput_get_lock(s) mol_table_slice_by_index(s, 1) -#define MolReader_CellOutput_get_type_(s) mol_table_slice_by_index(s, 2) -#define MolReader_CellDep_verify(s, c) mol_verify_fixed_size(s, 37) -#define MolReader_CellDep_get_out_point(s) mol_slice_by_offset(s, 0, 36) -#define MolReader_CellDep_get_dep_type(s) mol_slice_by_offset(s, 36, 1) -MOLECULE_API_DECORATOR mol_errno MolReader_RawTransaction_verify (const mol_seg_t*, bool); -#define MolReader_RawTransaction_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_RawTransaction_has_extra_fields(s) mol_table_has_extra_fields(s, 6) -#define MolReader_RawTransaction_get_version(s) mol_table_slice_by_index(s, 0) -#define MolReader_RawTransaction_get_cell_deps(s) mol_table_slice_by_index(s, 1) -#define MolReader_RawTransaction_get_header_deps(s) mol_table_slice_by_index(s, 2) -#define MolReader_RawTransaction_get_inputs(s) mol_table_slice_by_index(s, 3) -#define MolReader_RawTransaction_get_outputs(s) mol_table_slice_by_index(s, 4) -#define MolReader_RawTransaction_get_outputs_data(s) mol_table_slice_by_index(s, 5) -MOLECULE_API_DECORATOR mol_errno MolReader_Transaction_verify (const mol_seg_t*, bool); -#define MolReader_Transaction_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Transaction_has_extra_fields(s) mol_table_has_extra_fields(s, 2) -#define MolReader_Transaction_get_raw(s) mol_table_slice_by_index(s, 0) -#define MolReader_Transaction_get_witnesses(s) mol_table_slice_by_index(s, 1) -#define MolReader_RawHeader_verify(s, c) mol_verify_fixed_size(s, 192) -#define MolReader_RawHeader_get_version(s) mol_slice_by_offset(s, 0, 4) -#define MolReader_RawHeader_get_compact_target(s) mol_slice_by_offset(s, 4, 4) -#define MolReader_RawHeader_get_timestamp(s) mol_slice_by_offset(s, 8, 8) -#define MolReader_RawHeader_get_number(s) mol_slice_by_offset(s, 16, 8) -#define MolReader_RawHeader_get_epoch(s) mol_slice_by_offset(s, 24, 8) -#define MolReader_RawHeader_get_parent_hash(s) mol_slice_by_offset(s, 32, 32) -#define MolReader_RawHeader_get_transactions_root(s) mol_slice_by_offset(s, 64, 32) -#define MolReader_RawHeader_get_proposals_hash(s) mol_slice_by_offset(s, 96, 32) -#define MolReader_RawHeader_get_extra_hash(s) mol_slice_by_offset(s, 128, 32) -#define MolReader_RawHeader_get_dao(s) mol_slice_by_offset(s, 160, 32) -#define MolReader_Header_verify(s, c) mol_verify_fixed_size(s, 208) -#define MolReader_Header_get_raw(s) mol_slice_by_offset(s, 0, 192) -#define MolReader_Header_get_nonce(s) mol_slice_by_offset(s, 192, 16) -MOLECULE_API_DECORATOR mol_errno MolReader_UncleBlock_verify (const mol_seg_t*, bool); -#define MolReader_UncleBlock_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_UncleBlock_has_extra_fields(s) mol_table_has_extra_fields(s, 2) -#define MolReader_UncleBlock_get_header(s) mol_table_slice_by_index(s, 0) -#define MolReader_UncleBlock_get_proposals(s) mol_table_slice_by_index(s, 1) -MOLECULE_API_DECORATOR mol_errno MolReader_Block_verify (const mol_seg_t*, bool); -#define MolReader_Block_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Block_has_extra_fields(s) mol_table_has_extra_fields(s, 4) -#define MolReader_Block_get_header(s) mol_table_slice_by_index(s, 0) -#define MolReader_Block_get_uncles(s) mol_table_slice_by_index(s, 1) -#define MolReader_Block_get_transactions(s) mol_table_slice_by_index(s, 2) -#define MolReader_Block_get_proposals(s) mol_table_slice_by_index(s, 3) -MOLECULE_API_DECORATOR mol_errno MolReader_BlockV1_verify (const mol_seg_t*, bool); -#define MolReader_BlockV1_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_BlockV1_has_extra_fields(s) mol_table_has_extra_fields(s, 5) -#define MolReader_BlockV1_get_header(s) mol_table_slice_by_index(s, 0) -#define MolReader_BlockV1_get_uncles(s) mol_table_slice_by_index(s, 1) -#define MolReader_BlockV1_get_transactions(s) mol_table_slice_by_index(s, 2) -#define MolReader_BlockV1_get_proposals(s) mol_table_slice_by_index(s, 3) -#define MolReader_BlockV1_get_extension(s) mol_table_slice_by_index(s, 4) -MOLECULE_API_DECORATOR mol_errno MolReader_CellbaseWitness_verify (const mol_seg_t*, bool); -#define MolReader_CellbaseWitness_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_CellbaseWitness_has_extra_fields(s) mol_table_has_extra_fields(s, 2) -#define MolReader_CellbaseWitness_get_lock(s) mol_table_slice_by_index(s, 0) -#define MolReader_CellbaseWitness_get_message(s) mol_table_slice_by_index(s, 1) -MOLECULE_API_DECORATOR mol_errno MolReader_WitnessArgs_verify (const mol_seg_t*, bool); -#define MolReader_WitnessArgs_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_WitnessArgs_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_WitnessArgs_get_lock(s) mol_table_slice_by_index(s, 0) -#define MolReader_WitnessArgs_get_input_type(s) mol_table_slice_by_index(s, 1) -#define MolReader_WitnessArgs_get_output_type(s) mol_table_slice_by_index(s, 2) - -/* - * Builder APIs - */ - -#define MolBuilder_Uint32_init(b) mol_builder_initialize_fixed_size(b, 4) -#define MolBuilder_Uint32_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint32_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint32_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint32_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint32_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint32_clear(b) mol_builder_discard(b) -#define MolBuilder_Uint64_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_Uint64_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint64_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint64_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint64_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint64_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Uint64_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Uint64_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Uint64_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Uint64_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint64_clear(b) mol_builder_discard(b) -#define MolBuilder_Uint128_init(b) mol_builder_initialize_fixed_size(b, 16) -#define MolBuilder_Uint128_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint128_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint128_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint128_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint128_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Uint128_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Uint128_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Uint128_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Uint128_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_Uint128_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_Uint128_set_nth10(b, p) mol_builder_set_byte_by_offset(b, 10, p) -#define MolBuilder_Uint128_set_nth11(b, p) mol_builder_set_byte_by_offset(b, 11, p) -#define MolBuilder_Uint128_set_nth12(b, p) mol_builder_set_byte_by_offset(b, 12, p) -#define MolBuilder_Uint128_set_nth13(b, p) mol_builder_set_byte_by_offset(b, 13, p) -#define MolBuilder_Uint128_set_nth14(b, p) mol_builder_set_byte_by_offset(b, 14, p) -#define MolBuilder_Uint128_set_nth15(b, p) mol_builder_set_byte_by_offset(b, 15, p) -#define MolBuilder_Uint128_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint128_clear(b) mol_builder_discard(b) -#define MolBuilder_Byte32_init(b) mol_builder_initialize_fixed_size(b, 32) -#define MolBuilder_Byte32_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Byte32_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Byte32_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Byte32_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Byte32_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Byte32_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Byte32_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Byte32_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Byte32_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_Byte32_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_Byte32_set_nth10(b, p) mol_builder_set_byte_by_offset(b, 10, p) -#define MolBuilder_Byte32_set_nth11(b, p) mol_builder_set_byte_by_offset(b, 11, p) -#define MolBuilder_Byte32_set_nth12(b, p) mol_builder_set_byte_by_offset(b, 12, p) -#define MolBuilder_Byte32_set_nth13(b, p) mol_builder_set_byte_by_offset(b, 13, p) -#define MolBuilder_Byte32_set_nth14(b, p) mol_builder_set_byte_by_offset(b, 14, p) -#define MolBuilder_Byte32_set_nth15(b, p) mol_builder_set_byte_by_offset(b, 15, p) -#define MolBuilder_Byte32_set_nth16(b, p) mol_builder_set_byte_by_offset(b, 16, p) -#define MolBuilder_Byte32_set_nth17(b, p) mol_builder_set_byte_by_offset(b, 17, p) -#define MolBuilder_Byte32_set_nth18(b, p) mol_builder_set_byte_by_offset(b, 18, p) -#define MolBuilder_Byte32_set_nth19(b, p) mol_builder_set_byte_by_offset(b, 19, p) -#define MolBuilder_Byte32_set_nth20(b, p) mol_builder_set_byte_by_offset(b, 20, p) -#define MolBuilder_Byte32_set_nth21(b, p) mol_builder_set_byte_by_offset(b, 21, p) -#define MolBuilder_Byte32_set_nth22(b, p) mol_builder_set_byte_by_offset(b, 22, p) -#define MolBuilder_Byte32_set_nth23(b, p) mol_builder_set_byte_by_offset(b, 23, p) -#define MolBuilder_Byte32_set_nth24(b, p) mol_builder_set_byte_by_offset(b, 24, p) -#define MolBuilder_Byte32_set_nth25(b, p) mol_builder_set_byte_by_offset(b, 25, p) -#define MolBuilder_Byte32_set_nth26(b, p) mol_builder_set_byte_by_offset(b, 26, p) -#define MolBuilder_Byte32_set_nth27(b, p) mol_builder_set_byte_by_offset(b, 27, p) -#define MolBuilder_Byte32_set_nth28(b, p) mol_builder_set_byte_by_offset(b, 28, p) -#define MolBuilder_Byte32_set_nth29(b, p) mol_builder_set_byte_by_offset(b, 29, p) -#define MolBuilder_Byte32_set_nth30(b, p) mol_builder_set_byte_by_offset(b, 30, p) -#define MolBuilder_Byte32_set_nth31(b, p) mol_builder_set_byte_by_offset(b, 31, p) -#define MolBuilder_Byte32_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Byte32_clear(b) mol_builder_discard(b) -#define MolBuilder_Uint256_init(b) mol_builder_initialize_fixed_size(b, 32) -#define MolBuilder_Uint256_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint256_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint256_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint256_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint256_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Uint256_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Uint256_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Uint256_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Uint256_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_Uint256_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_Uint256_set_nth10(b, p) mol_builder_set_byte_by_offset(b, 10, p) -#define MolBuilder_Uint256_set_nth11(b, p) mol_builder_set_byte_by_offset(b, 11, p) -#define MolBuilder_Uint256_set_nth12(b, p) mol_builder_set_byte_by_offset(b, 12, p) -#define MolBuilder_Uint256_set_nth13(b, p) mol_builder_set_byte_by_offset(b, 13, p) -#define MolBuilder_Uint256_set_nth14(b, p) mol_builder_set_byte_by_offset(b, 14, p) -#define MolBuilder_Uint256_set_nth15(b, p) mol_builder_set_byte_by_offset(b, 15, p) -#define MolBuilder_Uint256_set_nth16(b, p) mol_builder_set_byte_by_offset(b, 16, p) -#define MolBuilder_Uint256_set_nth17(b, p) mol_builder_set_byte_by_offset(b, 17, p) -#define MolBuilder_Uint256_set_nth18(b, p) mol_builder_set_byte_by_offset(b, 18, p) -#define MolBuilder_Uint256_set_nth19(b, p) mol_builder_set_byte_by_offset(b, 19, p) -#define MolBuilder_Uint256_set_nth20(b, p) mol_builder_set_byte_by_offset(b, 20, p) -#define MolBuilder_Uint256_set_nth21(b, p) mol_builder_set_byte_by_offset(b, 21, p) -#define MolBuilder_Uint256_set_nth22(b, p) mol_builder_set_byte_by_offset(b, 22, p) -#define MolBuilder_Uint256_set_nth23(b, p) mol_builder_set_byte_by_offset(b, 23, p) -#define MolBuilder_Uint256_set_nth24(b, p) mol_builder_set_byte_by_offset(b, 24, p) -#define MolBuilder_Uint256_set_nth25(b, p) mol_builder_set_byte_by_offset(b, 25, p) -#define MolBuilder_Uint256_set_nth26(b, p) mol_builder_set_byte_by_offset(b, 26, p) -#define MolBuilder_Uint256_set_nth27(b, p) mol_builder_set_byte_by_offset(b, 27, p) -#define MolBuilder_Uint256_set_nth28(b, p) mol_builder_set_byte_by_offset(b, 28, p) -#define MolBuilder_Uint256_set_nth29(b, p) mol_builder_set_byte_by_offset(b, 29, p) -#define MolBuilder_Uint256_set_nth30(b, p) mol_builder_set_byte_by_offset(b, 30, p) -#define MolBuilder_Uint256_set_nth31(b, p) mol_builder_set_byte_by_offset(b, 31, p) -#define MolBuilder_Uint256_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint256_clear(b) mol_builder_discard(b) -#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) -#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) -#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) -#define MolBuilder_BytesOpt_init(b) mol_builder_initialize_fixed_size(b, 0) -#define MolBuilder_BytesOpt_set(b, p, l) mol_option_builder_set(b, p, l) -#define MolBuilder_BytesOpt_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_BytesOpt_clear(b) mol_builder_discard(b) -#define MolBuilder_BytesVec_init(b) mol_builder_initialize_with_capacity(b, 64, 64) -#define MolBuilder_BytesVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_BytesVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_BytesVec_clear(b) mol_builder_discard(b) -#define MolBuilder_Byte32Vec_init(b) mol_fixvec_builder_initialize(b, 512) -#define MolBuilder_Byte32Vec_push(b, p) mol_fixvec_builder_push(b, p, 32) -#define MolBuilder_Byte32Vec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Byte32Vec_clear(b) mol_builder_discard(b) -#define MolBuilder_ScriptOpt_init(b) mol_builder_initialize_fixed_size(b, 0) -#define MolBuilder_ScriptOpt_set(b, p, l) mol_option_builder_set(b, p, l) -#define MolBuilder_ScriptOpt_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_ScriptOpt_clear(b) mol_builder_discard(b) -#define MolBuilder_ProposalShortId_init(b) mol_builder_initialize_fixed_size(b, 10) -#define MolBuilder_ProposalShortId_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_ProposalShortId_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_ProposalShortId_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_ProposalShortId_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_ProposalShortId_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_ProposalShortId_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_ProposalShortId_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_ProposalShortId_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_ProposalShortId_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_ProposalShortId_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_ProposalShortId_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_ProposalShortId_clear(b) mol_builder_discard(b) -#define MolBuilder_UncleBlockVec_init(b) mol_builder_initialize_with_capacity(b, 4096, 64) -#define MolBuilder_UncleBlockVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_UncleBlockVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_UncleBlockVec_clear(b) mol_builder_discard(b) -#define MolBuilder_TransactionVec_init(b) mol_builder_initialize_with_capacity(b, 2048, 64) -#define MolBuilder_TransactionVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_TransactionVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_TransactionVec_clear(b) mol_builder_discard(b) -#define MolBuilder_ProposalShortIdVec_init(b) mol_fixvec_builder_initialize(b, 256) -#define MolBuilder_ProposalShortIdVec_push(b, p) mol_fixvec_builder_push(b, p, 10) -#define MolBuilder_ProposalShortIdVec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_ProposalShortIdVec_clear(b) mol_builder_discard(b) -#define MolBuilder_CellDepVec_init(b) mol_fixvec_builder_initialize(b, 1024) -#define MolBuilder_CellDepVec_push(b, p) mol_fixvec_builder_push(b, p, 37) -#define MolBuilder_CellDepVec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_CellDepVec_clear(b) mol_builder_discard(b) -#define MolBuilder_CellInputVec_init(b) mol_fixvec_builder_initialize(b, 1024) -#define MolBuilder_CellInputVec_push(b, p) mol_fixvec_builder_push(b, p, 44) -#define MolBuilder_CellInputVec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_CellInputVec_clear(b) mol_builder_discard(b) -#define MolBuilder_CellOutputVec_init(b) mol_builder_initialize_with_capacity(b, 2048, 64) -#define MolBuilder_CellOutputVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_CellOutputVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_CellOutputVec_clear(b) mol_builder_discard(b) -#define MolBuilder_Script_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Script_set_code_hash(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Script_set_hash_type(b, p) mol_table_builder_add_byte(b, 1, p) -#define MolBuilder_Script_set_args(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Script_build (mol_builder_t); -#define MolBuilder_Script_clear(b) mol_builder_discard(b) -#define MolBuilder_OutPoint_init(b) mol_builder_initialize_fixed_size(b, 36) -#define MolBuilder_OutPoint_set_tx_hash(b, p) mol_builder_set_by_offset(b, 0, p, 32) -#define MolBuilder_OutPoint_set_index(b, p) mol_builder_set_by_offset(b, 32, p, 4) -#define MolBuilder_OutPoint_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_OutPoint_clear(b) mol_builder_discard(b) -#define MolBuilder_CellInput_init(b) mol_builder_initialize_fixed_size(b, 44) -#define MolBuilder_CellInput_set_since(b, p) mol_builder_set_by_offset(b, 0, p, 8) -#define MolBuilder_CellInput_set_previous_output(b, p) mol_builder_set_by_offset(b, 8, p, 36) -#define MolBuilder_CellInput_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_CellInput_clear(b) mol_builder_discard(b) -#define MolBuilder_CellOutput_init(b) mol_table_builder_initialize(b, 512, 3) -#define MolBuilder_CellOutput_set_capacity(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_CellOutput_set_lock(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_CellOutput_set_type_(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_CellOutput_build (mol_builder_t); -#define MolBuilder_CellOutput_clear(b) mol_builder_discard(b) -#define MolBuilder_CellDep_init(b) mol_builder_initialize_fixed_size(b, 37) -#define MolBuilder_CellDep_set_out_point(b, p) mol_builder_set_by_offset(b, 0, p, 36) -#define MolBuilder_CellDep_set_dep_type(b, p) mol_builder_set_byte_by_offset(b, 36, p) -#define MolBuilder_CellDep_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_CellDep_clear(b) mol_builder_discard(b) -#define MolBuilder_RawTransaction_init(b) mol_table_builder_initialize(b, 256, 6) -#define MolBuilder_RawTransaction_set_version(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_RawTransaction_set_cell_deps(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_RawTransaction_set_header_deps(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_RawTransaction_set_inputs(b, p, l) mol_table_builder_add(b, 3, p, l) -#define MolBuilder_RawTransaction_set_outputs(b, p, l) mol_table_builder_add(b, 4, p, l) -#define MolBuilder_RawTransaction_set_outputs_data(b, p, l) mol_table_builder_add(b, 5, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_RawTransaction_build (mol_builder_t); -#define MolBuilder_RawTransaction_clear(b) mol_builder_discard(b) -#define MolBuilder_Transaction_init(b) mol_table_builder_initialize(b, 512, 2) -#define MolBuilder_Transaction_set_raw(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Transaction_set_witnesses(b, p, l) mol_table_builder_add(b, 1, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Transaction_build (mol_builder_t); -#define MolBuilder_Transaction_clear(b) mol_builder_discard(b) -#define MolBuilder_RawHeader_init(b) mol_builder_initialize_fixed_size(b, 192) -#define MolBuilder_RawHeader_set_version(b, p) mol_builder_set_by_offset(b, 0, p, 4) -#define MolBuilder_RawHeader_set_compact_target(b, p) mol_builder_set_by_offset(b, 4, p, 4) -#define MolBuilder_RawHeader_set_timestamp(b, p) mol_builder_set_by_offset(b, 8, p, 8) -#define MolBuilder_RawHeader_set_number(b, p) mol_builder_set_by_offset(b, 16, p, 8) -#define MolBuilder_RawHeader_set_epoch(b, p) mol_builder_set_by_offset(b, 24, p, 8) -#define MolBuilder_RawHeader_set_parent_hash(b, p) mol_builder_set_by_offset(b, 32, p, 32) -#define MolBuilder_RawHeader_set_transactions_root(b, p) mol_builder_set_by_offset(b, 64, p, 32) -#define MolBuilder_RawHeader_set_proposals_hash(b, p) mol_builder_set_by_offset(b, 96, p, 32) -#define MolBuilder_RawHeader_set_extra_hash(b, p) mol_builder_set_by_offset(b, 128, p, 32) -#define MolBuilder_RawHeader_set_dao(b, p) mol_builder_set_by_offset(b, 160, p, 32) -#define MolBuilder_RawHeader_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_RawHeader_clear(b) mol_builder_discard(b) -#define MolBuilder_Header_init(b) mol_builder_initialize_fixed_size(b, 208) -#define MolBuilder_Header_set_raw(b, p) mol_builder_set_by_offset(b, 0, p, 192) -#define MolBuilder_Header_set_nonce(b, p) mol_builder_set_by_offset(b, 192, p, 16) -#define MolBuilder_Header_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Header_clear(b) mol_builder_discard(b) -#define MolBuilder_UncleBlock_init(b) mol_table_builder_initialize(b, 1024, 2) -#define MolBuilder_UncleBlock_set_header(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_UncleBlock_set_proposals(b, p, l) mol_table_builder_add(b, 1, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_UncleBlock_build (mol_builder_t); -#define MolBuilder_UncleBlock_clear(b) mol_builder_discard(b) -#define MolBuilder_Block_init(b) mol_table_builder_initialize(b, 1024, 4) -#define MolBuilder_Block_set_header(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Block_set_uncles(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Block_set_transactions(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_Block_set_proposals(b, p, l) mol_table_builder_add(b, 3, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Block_build (mol_builder_t); -#define MolBuilder_Block_clear(b) mol_builder_discard(b) -#define MolBuilder_BlockV1_init(b) mol_table_builder_initialize(b, 1024, 5) -#define MolBuilder_BlockV1_set_header(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_BlockV1_set_uncles(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_BlockV1_set_transactions(b, p, l) mol_table_builder_add(b, 2, p, l) -#define MolBuilder_BlockV1_set_proposals(b, p, l) mol_table_builder_add(b, 3, p, l) -#define MolBuilder_BlockV1_set_extension(b, p, l) mol_table_builder_add(b, 4, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_BlockV1_build (mol_builder_t); -#define MolBuilder_BlockV1_clear(b) mol_builder_discard(b) -#define MolBuilder_CellbaseWitness_init(b) mol_table_builder_initialize(b, 512, 2) -#define MolBuilder_CellbaseWitness_set_lock(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_CellbaseWitness_set_message(b, p, l) mol_table_builder_add(b, 1, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_CellbaseWitness_build (mol_builder_t); -#define MolBuilder_CellbaseWitness_clear(b) mol_builder_discard(b) -#define MolBuilder_WitnessArgs_init(b) mol_table_builder_initialize(b, 64, 3) -#define MolBuilder_WitnessArgs_set_lock(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_WitnessArgs_set_input_type(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_WitnessArgs_set_output_type(b, p, l) mol_table_builder_add(b, 2, p, l) -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_WitnessArgs_build (mol_builder_t); -#define MolBuilder_WitnessArgs_clear(b) mol_builder_discard(b) - -/* - * Default Value - */ - -#define ____ 0x00 - -MOLECULE_API_DECORATOR const uint8_t MolDefault_Uint32[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Uint64[8] = { - ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Uint128[16] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Byte32[32] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Uint256[32] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_BytesOpt[0] = {}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_BytesVec[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Byte32Vec[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_ScriptOpt[0] = {}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_ProposalShortId[10] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_UncleBlockVec[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_TransactionVec[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_ProposalShortIdVec[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellDepVec[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellInputVec[4] = {____, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellOutputVec[4] = {0x04, ____, ____, ____}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Script[53] = { - 0x35, ____, ____, ____, 0x10, ____, ____, ____, 0x30, ____, ____, ____, - 0x31, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_OutPoint[36] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellInput[44] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellOutput[77] = { - 0x4d, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, - 0x4d, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - 0x35, ____, ____, ____, 0x10, ____, ____, ____, 0x30, ____, ____, ____, - 0x31, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellDep[37] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_RawTransaction[52] = { - 0x34, ____, ____, ____, 0x1c, ____, ____, ____, 0x20, ____, ____, ____, - 0x24, ____, ____, ____, 0x28, ____, ____, ____, 0x2c, ____, ____, ____, - 0x30, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, 0x04, ____, ____, ____, - 0x04, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Transaction[68] = { - 0x44, ____, ____, ____, 0x0c, ____, ____, ____, 0x40, ____, ____, ____, - 0x34, ____, ____, ____, 0x1c, ____, ____, ____, 0x20, ____, ____, ____, - 0x24, ____, ____, ____, 0x28, ____, ____, ____, 0x2c, ____, ____, ____, - 0x30, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, 0x04, ____, ____, ____, - 0x04, ____, ____, ____, 0x04, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_RawHeader[192] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Header[208] = { - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_UncleBlock[224] = { - 0xe0, ____, ____, ____, 0x0c, ____, ____, ____, 0xdc, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_Block[240] = { - 0xf0, ____, ____, ____, 0x14, ____, ____, ____, 0xe4, ____, ____, ____, - 0xe8, ____, ____, ____, 0xec, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - 0x04, ____, ____, ____, 0x04, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_BlockV1[248] = { - 0xf8, ____, ____, ____, 0x18, ____, ____, ____, 0xe8, ____, ____, ____, - 0xec, ____, ____, ____, 0xf0, ____, ____, ____, 0xf4, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, 0x04, ____, ____, ____, 0x04, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_CellbaseWitness[69] = { - 0x45, ____, ____, ____, 0x0c, ____, ____, ____, 0x41, ____, ____, ____, - 0x35, ____, ____, ____, 0x10, ____, ____, ____, 0x30, ____, ____, ____, - 0x31, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, - ____, ____, ____, ____, ____, ____, ____, ____, ____, -}; -MOLECULE_API_DECORATOR const uint8_t MolDefault_WitnessArgs[16] = { - 0x10, ____, ____, ____, 0x10, ____, ____, ____, 0x10, ____, ____, ____, - 0x10, ____, ____, ____, -}; - -#undef ____ - -/* - * Reader Functions - */ - -MOLECULE_API_DECORATOR mol_errno MolReader_BytesOpt_verify (const mol_seg_t *input, bool compatible) { - if (input->size != 0) { - return MolReader_Bytes_verify(input, compatible); - } else { - return MOL_OK; - } -} -MOLECULE_API_DECORATOR mol_errno MolReader_BytesVec_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size == MOL_NUM_T_SIZE) { - return MOL_OK; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { - return MOL_ERR_HEADER; - } - mol_num_t end; - for (mol_num_t i=1; i end) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = end - offset; - mol_errno errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - offset = end; - } - if (offset > total_size) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = total_size - offset; - return MolReader_Bytes_verify(&inner, compatible); -} -MOLECULE_API_DECORATOR mol_errno MolReader_ScriptOpt_verify (const mol_seg_t *input, bool compatible) { - if (input->size != 0) { - return MolReader_Script_verify(input, compatible); - } else { - return MOL_OK; - } -} -MOLECULE_API_DECORATOR mol_errno MolReader_UncleBlockVec_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size == MOL_NUM_T_SIZE) { - return MOL_OK; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { - return MOL_ERR_HEADER; - } - mol_num_t end; - for (mol_num_t i=1; i end) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = end - offset; - mol_errno errno = MolReader_UncleBlock_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - offset = end; - } - if (offset > total_size) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = total_size - offset; - return MolReader_UncleBlock_verify(&inner, compatible); -} -MOLECULE_API_DECORATOR mol_errno MolReader_TransactionVec_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size == MOL_NUM_T_SIZE) { - return MOL_OK; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { - return MOL_ERR_HEADER; - } - mol_num_t end; - for (mol_num_t i=1; i end) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = end - offset; - mol_errno errno = MolReader_Transaction_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - offset = end; - } - if (offset > total_size) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = total_size - offset; - return MolReader_Transaction_verify(&inner, compatible); -} -MOLECULE_API_DECORATOR mol_errno MolReader_CellOutputVec_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size == MOL_NUM_T_SIZE) { - return MOL_OK; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t item_count = offset / 4 - 1; - if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { - return MOL_ERR_HEADER; - } - mol_num_t end; - for (mol_num_t i=1; i end) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = end - offset; - mol_errno errno = MolReader_CellOutput_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - offset = end; - } - if (offset > total_size) { - return MOL_ERR_OFFSET; - } - mol_seg_t inner; - inner.ptr = input->ptr + offset; - inner.size = total_size - offset; - return MolReader_CellOutput_verify(&inner, compatible); -} -MOLECULE_API_DECORATOR mol_errno MolReader_Script_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 3) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 3) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Byte32_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - if (offsets[2] - offsets[1] != 1) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_CellOutput_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 3) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 3) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Uint64_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_Script_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_ScriptOpt_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_RawTransaction_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 6) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 6) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Uint32_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_CellDepVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_Byte32Vec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_CellInputVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[4]; - inner.size = offsets[5] - offsets[4]; - errno = MolReader_CellOutputVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[5]; - inner.size = offsets[6] - offsets[5]; - errno = MolReader_BytesVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_Transaction_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 2) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 2) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_RawTransaction_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_BytesVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_UncleBlock_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 2) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 2) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Header_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_ProposalShortIdVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_Block_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 4) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 4) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Header_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_UncleBlockVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_TransactionVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_ProposalShortIdVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_BlockV1_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 5) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 5) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Header_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_UncleBlockVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_TransactionVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[3]; - inner.size = offsets[4] - offsets[3]; - errno = MolReader_ProposalShortIdVec_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[4]; - inner.size = offsets[5] - offsets[4]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_CellbaseWitness_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 2) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 2) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_Script_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_Bytes_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} -MOLECULE_API_DECORATOR mol_errno MolReader_WitnessArgs_verify (const mol_seg_t *input, bool compatible) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - uint8_t *ptr = input->ptr; - mol_num_t total_size = mol_unpack_number(ptr); - if (input->size != total_size) { - return MOL_ERR_TOTAL_SIZE; - } - if (input->size < MOL_NUM_T_SIZE * 2) { - return MOL_ERR_HEADER; - } - ptr += MOL_NUM_T_SIZE; - mol_num_t offset = mol_unpack_number(ptr); - if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { - return MOL_ERR_OFFSET; - } - mol_num_t field_count = offset / 4 - 1; - if (field_count < 3) { - return MOL_ERR_FIELD_COUNT; - } else if (!compatible && field_count > 3) { - return MOL_ERR_FIELD_COUNT; - } - if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ - return MOL_ERR_HEADER; - } - mol_num_t offsets[field_count+1]; - offsets[0] = offset; - for (mol_num_t i=1; i offsets[i]) { - return MOL_ERR_OFFSET; - } - } - if (offsets[field_count-1] > total_size) { - return MOL_ERR_OFFSET; - } - offsets[field_count] = total_size; - mol_seg_t inner; - mol_errno errno; - inner.ptr = input->ptr + offsets[0]; - inner.size = offsets[1] - offsets[0]; - errno = MolReader_BytesOpt_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[1]; - inner.size = offsets[2] - offsets[1]; - errno = MolReader_BytesOpt_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - inner.ptr = input->ptr + offsets[2]; - inner.size = offsets[3] - offsets[2]; - errno = MolReader_BytesOpt_verify(&inner, compatible); - if (errno != MOL_OK) { - return MOL_ERR_DATA; - } - return MOL_OK; -} - -/* - * Builder Functions - */ - -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Script_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 16; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 32 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 1 : len; - len = builder.number_ptr[5]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 32 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 1 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[5]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 32; - memcpy(dst, &MolDefault_Byte32, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 1; - *dst = 0; - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[5]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_Bytes, len); - } else { - mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_CellOutput_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 16; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 8 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 53 : len; - len = builder.number_ptr[5]; - res.seg.size += len == 0 ? 0 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 8 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 53 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[5]; - offset += len == 0 ? 0 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 8; - memcpy(dst, &MolDefault_Uint64, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 53; - memcpy(dst, &MolDefault_Script, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[5]; - if (len == 0) { - len = 0; - memcpy(dst, &MolDefault_ScriptOpt, len); - } else { - mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_RawTransaction_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 28; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[5]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[7]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[9]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[11]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[5]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[7]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[9]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[11]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_Uint32, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_CellDepVec, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[5]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_Byte32Vec, len); - } else { - mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[7]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_CellInputVec, len); - } else { - mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[9]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_CellOutputVec, len); - } else { - mol_num_t of = builder.number_ptr[8]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[11]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_BytesVec, len); - } else { - mol_num_t of = builder.number_ptr[10]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Transaction_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 12; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 52 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 52 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 52; - memcpy(dst, &MolDefault_RawTransaction, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_BytesVec, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_UncleBlock_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 12; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 208 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 208 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 208; - memcpy(dst, &MolDefault_Header, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_ProposalShortIdVec, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_Block_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 20; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 208 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[5]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[7]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 208 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[5]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[7]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 208; - memcpy(dst, &MolDefault_Header, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_UncleBlockVec, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[5]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_TransactionVec, len); - } else { - mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[7]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_ProposalShortIdVec, len); - } else { - mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_BlockV1_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 24; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 208 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[5]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[7]; - res.seg.size += len == 0 ? 4 : len; - len = builder.number_ptr[9]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 208 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[5]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[7]; - offset += len == 0 ? 4 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[9]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 208; - memcpy(dst, &MolDefault_Header, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_UncleBlockVec, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[5]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_TransactionVec, len); - } else { - mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[7]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_ProposalShortIdVec, len); - } else { - mol_num_t of = builder.number_ptr[6]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[9]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_Bytes, len); - } else { - mol_num_t of = builder.number_ptr[8]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_CellbaseWitness_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 12; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 53 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 4 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 53 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 4 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 53; - memcpy(dst, &MolDefault_Script, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 4; - memcpy(dst, &MolDefault_Bytes, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} -MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_WitnessArgs_build (mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - mol_num_t offset = 16; - mol_num_t len; - res.seg.size = offset; - len = builder.number_ptr[1]; - res.seg.size += len == 0 ? 0 : len; - len = builder.number_ptr[3]; - res.seg.size += len == 0 ? 0 : len; - len = builder.number_ptr[5]; - res.seg.size += len == 0 ? 0 : len; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - uint8_t *dst = res.seg.ptr; - mol_pack_number(dst, &res.seg.size); - dst += MOL_NUM_T_SIZE; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[1]; - offset += len == 0 ? 0 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[3]; - offset += len == 0 ? 0 : len; - mol_pack_number(dst, &offset); - dst += MOL_NUM_T_SIZE; - len = builder.number_ptr[5]; - offset += len == 0 ? 0 : len; - uint8_t *src = builder.data_ptr; - len = builder.number_ptr[1]; - if (len == 0) { - len = 0; - memcpy(dst, &MolDefault_BytesOpt, len); - } else { - mol_num_t of = builder.number_ptr[0]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[3]; - if (len == 0) { - len = 0; - memcpy(dst, &MolDefault_BytesOpt, len); - } else { - mol_num_t of = builder.number_ptr[2]; - memcpy(dst, src+of, len); - } - dst += len; - len = builder.number_ptr[5]; - if (len == 0) { - len = 0; - memcpy(dst, &MolDefault_BytesOpt, len); - } else { - mol_num_t of = builder.number_ptr[4]; - memcpy(dst, src+of, len); - } - dst += len; - mol_builder_discard(builder); - return res; -} - -#ifdef __DEFINE_MOLECULE_API_DECORATOR_BLOCKCHAIN -#undef MOLECULE_API_DECORATOR -#undef __DEFINE_MOLECULE_API_DECORATOR_BLOCKCHAIN -#endif /* __DEFINE_MOLECULE_API_DECORATOR_BLOCKCHAIN */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* BLOCKCHAIN_H */ diff --git a/include/ckb-c-stdlib/molecule/molecule2_reader.h b/include/ckb-c-stdlib/molecule/molecule2_reader.h deleted file mode 100644 index 28f715c..0000000 --- a/include/ckb-c-stdlib/molecule/molecule2_reader.h +++ /dev/null @@ -1,700 +0,0 @@ -#ifndef MOLECULE2_READER_H -#define MOLECULE2_READER_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -#define CKB_C_STDLIB_PRINTF -#include -#include -#include -#include -#include - -#ifndef mol2_printf -#define mol2_printf printf -#endif -#ifndef MOL2_EXIT -#define MOL2_EXIT exit -#endif - -#ifndef MOL2_PANIC -#define MOL2_PANIC(err) \ - do { \ - mol2_printf("Error at %s: %d\n", __FILE__, __LINE__); \ - MOL2_EXIT(err); \ - } while (0) -//#define MOL2_PANIC(err) do {printf("Error at %s: %d, %d\n", __FILE__, -//__LINE__, err); } while(0) -#endif - -#define MOLECULE2_API_VERSION 5000 -#define MOLECULEC2_VERSION_MIN 5000 - -#if MOLECULE2_API_VERSION < MOLECULE2_API_VERSION_MIN -#error This file was generated by a newer version of moleculec which is \ - incompatible with current headers in use. Please update the headers. -#endif - -#if MOLECULEC2_VERSION < MOLECULEC2_VERSION_MIN -#error This file was generated by an older version of moleculec which is \ - incompatible with current headers in use. Please regenerate this file \ - with a newer version of moleculec. -#endif - -/* - * This part is not for normal users. - */ -// -// referenced API or macros -// -#ifndef ASSERT -#define ASSERT(s) ((void)0) -#endif - -#ifndef MIN -#define MIN(a, b) ((a > b) ? (b) : (a)) -#endif -#ifndef MAX -#define MAX(a, b) ((a > b) ? (a) : (b)) -#endif - -typedef uint32_t mol2_num_t; // Item Id -typedef uint8_t mol2_errno; // Error Number -#define MOL2_NUM_T_SIZE 4 - -// predefined type -// If the types defined in schema is fundamental type: -// 1. dynvec of byte() or -// 2. array([byte; N]) -// They will be converted to the type mol2_cursor_t automatically -// 3. byte -// it will be converted to uint8_t. - -// predefined type -// If the types defined in schema: -// 1. the name is same as below (case insensitive) -// 2. the type is matched (e.g. Uint32 should have type with [byte; 4]) -// they will be converted to the corresponding types automatically instead of -// just returning raw byte array. -// -typedef uint64_t Uint64; // [byte; 8] -typedef int64_t Int64; // [byte; 8] -typedef uint32_t Uint32; // [byte; 4] -typedef int32_t Int32; // [byte; 4] -typedef uint16_t Uint16; // [byte; 2] -typedef int16_t Int16; // [byte; 2] -typedef uint8_t Uint8; // [byte; 1] -typedef int8_t Int8; // [byte; 1] - -/* Error Numbers */ - -#define MOL2_OK 0x00 -#define MOL2_ERR 0xff - -#define MOL2_ERR_TOTAL_SIZE 0x01 -#define MOL2_ERR_HEADER 0x02 -#define MOL2_ERR_OFFSET 0x03 -#define MOL2_ERR_UNKNOWN_ITEM 0x04 -#define MOL2_ERR_INDEX_OUT_OF_BOUNDS 0x05 -#define MOL2_ERR_FIELD_COUNT 0x06 -#define MOL2_ERR_DATA 0x07 -#define MOL2_ERR_OVERFLOW 0x08 - -// converting function -// format: convert_to_${Type} -#define SWAP(a, b, t) \ - { \ - (t) = (a); \ - (a) = (b); \ - (b) = (t); \ - } -#define is_le2() \ - ((union { \ - uint16_t i; \ - unsigned char c; \ - }){.i = 1} \ - .c) - -void change_endian(uint8_t *ptr, int size); -/** - * read from a data source, with offset, up to "len" bytes into ptr. - * the memory size of "ptr" is "len". - * - * Return the length actually written. It may be smaller than "len". - * - * The "args" will be passed into "read" function as the first argument. - */ -typedef uint32_t (*mol2_source_t)(uintptr_t arg[], uint8_t *ptr, uint32_t len, - uint32_t offset); - -#define MAX_CACHE_SIZE 2048 -#define MIN_CACHE_SIZE 64 - -// data source with cache support -typedef struct mol2_data_source_t { - // function "read" might have more arguments - uintptr_t args[4]; - // total size of the data source. It is always true: - // offset+size <= total_size - uint32_t total_size; - - mol2_source_t read; - // start point of the cache - // if [offset, size) is in [start_point, start_point+cache_size), it returns - // memory in cache directly otherwise, it will try to load first (like cache - // miss) - uint32_t start_point; - uint32_t cache_size; - // it's normally same as MAX_CACHE_SIZE. - // modify it for testing purpose - uint32_t max_cache_size; - // variable length structure - // it's true length is calculated by "MOL2_DATA_SOURCE_LEN". - uint8_t cache[]; -} mol2_data_source_t; - -#define MOL2_DATA_SOURCE_LEN(cache_size) \ - (sizeof(mol2_data_source_t) + (cache_size)) - -#define DEFAULT_DATA_SOURCE_LENGTH (sizeof(mol2_data_source_t) + MAX_CACHE_SIZE) - -/** - * --------------- MUST READ ---------------------- - * This is the most important data struct in this file, MUST READ! - * The data_source is to fetch data from external, like memory, disk, or some - * others. It is with cache support. You can get an idea how to implement one - * from functions: "mol2_source_memory" and "mol2_make_cursor_from_memory". - * - * The offset and size, is an "view"/"slice" of the data source. - * - * When a new cursor is generated from an old one, - * the "data_source" must be copied. The offset and size can be different. - * Currently, there is no way to convert one data source to another. - * - */ -typedef struct mol2_cursor_t { - uint32_t offset; // offset of slice - uint32_t size; // size of slice - mol2_data_source_t *data_source; -} mol2_cursor_t; - -// a sample source over memory -uint32_t mol2_source_memory(uintptr_t args[], uint8_t *ptr, uint32_t len, - uint32_t offset); -mol2_cursor_t mol2_make_cursor_from_memory(const void *memory, uint32_t size); - -uint32_t mol2_read_at(const mol2_cursor_t *cur, uint8_t *buff, - uint32_t buff_len); - -// Bytes segment. -typedef struct { - uint8_t *ptr; // Pointer - mol2_num_t size; // Full size -} mol2_seg_t; - -// Unpacked Union -typedef struct { - mol2_num_t item_id; // Item Id - mol2_cursor_t cursor; // Cursor -} mol2_union_t; - -// Result for returning segment. -typedef struct { - mol2_errno errno; // Error Number - mol2_cursor_t cur; // Cursor -} mol2_cursor_res_t; - -void mol2_add_offset(mol2_cursor_t *cur, uint32_t offset); -void mol2_sub_size(mol2_cursor_t *cur, uint32_t shrinked_size); -void mol2_validate(const mol2_cursor_t *cur); - -mol2_num_t mol2_unpack_number(const mol2_cursor_t *cursor); - -mol2_errno mol2_verify_fixed_size(const mol2_cursor_t *input, - mol2_num_t total_size); - -mol2_errno mol2_fixvec_verify(const mol2_cursor_t *input, mol2_num_t item_size); - -bool mol2_option_is_none(const mol2_cursor_t *input); -mol2_union_t mol2_union_unpack(const mol2_cursor_t *input); -mol2_num_t mol2_fixvec_length(const mol2_cursor_t *input); -mol2_num_t mol2_dynvec_length(const mol2_cursor_t *input); -mol2_num_t mol2_table_actual_field_count(const mol2_cursor_t *input); -bool mol2_table_has_extra_fields(const mol2_cursor_t *input, - mol2_num_t field_count); -mol2_cursor_t mol2_slice_by_offset(const mol2_cursor_t *input, - mol2_num_t offset, mol2_num_t size); - -mol2_cursor_res_t mol2_fixvec_slice_by_index(const mol2_cursor_t *input, - mol2_num_t item_size, - mol2_num_t item_index); - -mol2_cursor_res_t mol2_dynvec_slice_by_index(const mol2_cursor_t *input, - mol2_num_t item_index); - -mol2_cursor_t mol2_table_slice_by_index(const mol2_cursor_t *input, - mol2_num_t field_index); - -mol2_cursor_t mol2_fixvec_slice_raw_bytes(const mol2_cursor_t *input); -Uint64 convert_to_Uint64(mol2_cursor_t *cur); -Int64 convert_to_Int64(mol2_cursor_t *cur); -Uint32 convert_to_Uint32(mol2_cursor_t *cur); -Int32 convert_to_Int32(mol2_cursor_t *cur); -Uint16 convert_to_Uint16(mol2_cursor_t *cur); -Int16 convert_to_Int16(mol2_cursor_t *cur); -Uint8 convert_to_Uint8(mol2_cursor_t *cur); -Int8 convert_to_Int8(mol2_cursor_t *cur); -mol2_cursor_t convert_to_array(mol2_cursor_t *cur); -mol2_cursor_t convert_to_rawbytes(mol2_cursor_t *cur); - -#ifndef MOLECULEC_C2_DECLARATION_ONLY - -// cur->offset = cur->offset + offset -void mol2_add_offset(mol2_cursor_t *cur, uint32_t offset) { - uint32_t res; - if (__builtin_add_overflow(cur->offset, offset, &res)) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - } - cur->offset = res; -} - -// cur->size = cur->size - shrinked_size -void mol2_sub_size(mol2_cursor_t *cur, uint32_t shrinked_size) { - uint32_t res; - if (__builtin_sub_overflow(cur->size, shrinked_size, &res)) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - } - cur->size = res; -} - -// mol2_unpack_number(cur) / 4 - 1 -uint32_t mol2_get_item_count(mol2_cursor_t *cur) { - uint32_t count = mol2_unpack_number(cur) / 4; - if (count == 0) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - } - return count - 1; -} -// item_size * item_count + offset -uint32_t mol2_calculate_offset(uint32_t item_size, uint32_t item_count, - uint32_t offset) { - uint32_t mul_res; - if (__builtin_mul_overflow(item_size, item_count, &mul_res)) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - } - uint32_t sum_res; - if (__builtin_add_overflow(mul_res, offset, &sum_res)) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - } - return sum_res; -} - -void mol2_validate(const mol2_cursor_t *cur) { - uint32_t res; - if (__builtin_add_overflow(cur->offset, cur->size, &res)) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - } - if (res > cur->data_source->total_size) { - mol2_printf("total_size(%d) > offset(%d) + size(%d)\n", - cur->data_source->total_size, cur->offset, cur->size); - MOL2_PANIC(MOL2_ERR_INDEX_OUT_OF_BOUNDS); - } -} - -mol2_errno mol2_verify_fixed_size(const mol2_cursor_t *input, - mol2_num_t total_size) { - return input->size == total_size ? MOL2_OK : MOL2_ERR_TOTAL_SIZE; -} - -mol2_errno mol2_fixvec_verify(const mol2_cursor_t *input, - mol2_num_t item_size) { - if (input->size < MOL2_NUM_T_SIZE) { - return MOL2_ERR_HEADER; - } - mol2_num_t item_count = mol2_unpack_number(input); - if (item_count == 0) { - return input->size == MOL2_NUM_T_SIZE ? MOL2_OK : MOL2_ERR_TOTAL_SIZE; - } - // mol2_num_t total_size = mol2_NUM_T_SIZE + item_size * item_count; - mol2_num_t total_size = - mol2_calculate_offset(item_size, item_count, MOL2_NUM_T_SIZE); - return input->size == total_size ? MOL2_OK : MOL2_ERR_TOTAL_SIZE; -} - -bool mol2_option_is_none(const mol2_cursor_t *input) { - return input->size == 0; -} - -mol2_union_t mol2_union_unpack(const mol2_cursor_t *input) { - mol2_union_t ret; - ret.item_id = mol2_unpack_number(input); - ret.cursor = *input; // must copy - // ret.cursor.offset = input->offset + mol2_NUM_T_SIZE; - // ret.cursor.size = input->size - mol2_NUM_T_SIZE; - mol2_add_offset(&ret.cursor, MOL2_NUM_T_SIZE); - mol2_sub_size(&ret.cursor, MOL2_NUM_T_SIZE); - mol2_validate(&ret.cursor); - return ret; -} - -mol2_num_t mol2_fixvec_length(const mol2_cursor_t *input) { - return mol2_unpack_number(input); -} - -mol2_num_t mol2_dynvec_length(const mol2_cursor_t *input) { - if (input->size == MOL2_NUM_T_SIZE) { - return 0; - } else { - mol2_cursor_t cur = *input; - mol2_add_offset(&cur, MOL2_NUM_T_SIZE); - mol2_sub_size(&cur, MOL2_NUM_T_SIZE); - mol2_validate(&cur); - // return (mol2_unpack_number(&cur) / 4) - 1; - return mol2_get_item_count(&cur); - } -} - -mol2_num_t mol2_table_actual_field_count(const mol2_cursor_t *input) { - return mol2_dynvec_length(input); -} - -bool mol2_table_has_extra_fields(const mol2_cursor_t *input, - mol2_num_t field_count) { - return mol2_table_actual_field_count(input) > field_count; -} - -mol2_cursor_t mol2_slice_by_offset(const mol2_cursor_t *input, - mol2_num_t offset, mol2_num_t size) { - mol2_cursor_t cur = *input; - - // cur.offset = input->offset + offset; - mol2_add_offset(&cur, offset); - cur.size = size; - mol2_validate(&cur); - return cur; -} - -mol2_cursor_res_t mol2_slice_by_offset2(const mol2_cursor_t *input, - mol2_num_t offset, mol2_num_t size) { - mol2_cursor_t cur = *input; - - // cur.offset = input->offset + offset; - mol2_add_offset(&cur, offset); - cur.size = size; - mol2_validate(&cur); - - mol2_cursor_res_t res; - res.errno = MOL2_OK; - res.cur = cur; - return res; -} - -mol2_cursor_res_t mol2_fixvec_slice_by_index(const mol2_cursor_t *input, - mol2_num_t item_size, - mol2_num_t item_index) { - mol2_cursor_res_t res; - res.cur = *input; - mol2_num_t item_count = mol2_unpack_number(input); - if (item_index >= item_count) { - res.errno = MOL2_ERR_INDEX_OUT_OF_BOUNDS; - } else { - res.errno = MOL2_OK; - // res.cur.offset = input->offset + mol2_NUM_T_SIZE + item_size * - // item_index; - uint32_t offset = - mol2_calculate_offset(item_size, item_index, MOL2_NUM_T_SIZE); - mol2_add_offset(&res.cur, offset); - res.cur.size = item_size; - mol2_validate(&res.cur); - } - return res; -} - -mol2_cursor_res_t mol2_dynvec_slice_by_index(const mol2_cursor_t *input, - mol2_num_t item_index) { - mol2_cursor_res_t res; - res.cur = *input; - struct mol2_cursor_t temp = *input; - - mol2_num_t total_size = mol2_unpack_number(input); - if (total_size == MOL2_NUM_T_SIZE) { - res.errno = MOL2_ERR_INDEX_OUT_OF_BOUNDS; - } else { - // temp.offset = input->offset + mol2_NUM_T_SIZE; - mol2_add_offset(&temp, MOL2_NUM_T_SIZE); - // mol2_num_t item_count = (mol2_unpack_number(&temp) / 4) - 1; - mol2_num_t item_count = mol2_get_item_count(&temp); - - if (item_index >= item_count) { - res.errno = MOL2_ERR_INDEX_OUT_OF_BOUNDS; - } else { - temp.offset = input->offset; - uint32_t temp_offset = - mol2_calculate_offset(MOL2_NUM_T_SIZE, item_index + 1, 0); - mol2_add_offset(&temp, temp_offset); - - mol2_num_t item_start = mol2_unpack_number(&temp); - if (item_index + 1 == item_count) { - res.errno = MOL2_OK; - res.cur.offset = input->offset; - mol2_add_offset(&res.cur, item_start); - res.cur.size = total_size; - mol2_sub_size(&res.cur, item_start); - } else { - temp.offset = input->offset; - uint32_t calc_offset = - mol2_calculate_offset(MOL2_NUM_T_SIZE, item_index + 2, 0); - mol2_add_offset(&temp, calc_offset); - - mol2_num_t item_end = mol2_unpack_number(&temp); - res.errno = MOL2_OK; - res.cur.offset = input->offset; - mol2_add_offset(&res.cur, item_start); - res.cur.size = item_end; - mol2_sub_size(&res.cur, item_start); - } - } - } - if (res.errno == MOL2_OK) { - mol2_validate(&res.cur); - } - return res; -} - -mol2_cursor_t mol2_table_slice_by_index(const mol2_cursor_t *input, - mol2_num_t field_index) { - mol2_cursor_res_t res = mol2_dynvec_slice_by_index(input, field_index); - ASSERT(res.errno == 0); - return res.cur; -} - -mol2_cursor_t mol2_fixvec_slice_raw_bytes(const mol2_cursor_t *input) { - mol2_cursor_t cur = *input; - mol2_add_offset(&cur, MOL2_NUM_T_SIZE); - cur.size = mol2_unpack_number(input); - mol2_validate(&cur); - return cur; -} - -Uint64 convert_to_Uint64(mol2_cursor_t *cur) { - uint64_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -Int64 convert_to_Int64(mol2_cursor_t *cur) { - int64_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -Uint32 convert_to_Uint32(mol2_cursor_t *cur) { - uint32_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -Int32 convert_to_Int32(mol2_cursor_t *cur) { - int32_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -Uint16 convert_to_Uint16(mol2_cursor_t *cur) { - uint16_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -Int16 convert_to_Int16(mol2_cursor_t *cur) { - int16_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - ASSERT(len == sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - return ret; -} - -Uint8 convert_to_Uint8(mol2_cursor_t *cur) { - uint8_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -Int8 convert_to_Int8(mol2_cursor_t *cur) { - int8_t ret; - uint32_t len = mol2_read_at(cur, (uint8_t *)&ret, sizeof(ret)); - if (len != sizeof(ret)) { - MOL2_PANIC(MOL2_ERR_DATA); - } - change_endian((uint8_t *)&ret, sizeof(ret)); - return ret; -} - -mol2_cursor_t convert_to_array(mol2_cursor_t *cur) { return *cur; } - -mol2_cursor_t convert_to_rawbytes(mol2_cursor_t *cur) { - return mol2_fixvec_slice_raw_bytes(cur); -} - -void change_endian(uint8_t *ptr, int size) { - if (is_le2()) return; - if (size == 0) return; - - if (size % 2 != 0) { - MOL2_PANIC(MOL2_ERR_DATA); - } - uint8_t t = 0; - for (int i = 0; i < size / 2; i++) { - SWAP(ptr[i], ptr[size - 1 - i], t); - } -} - -// this is a sample implementation over memory -uint32_t mol2_source_memory(uintptr_t args[], uint8_t *ptr, uint32_t len, - uint32_t offset) { - uint32_t mem_len = (uint32_t)args[1]; - ASSERT(offset < mem_len); - uint32_t remaining_len = mem_len - offset; - - uint32_t min_len = MIN(remaining_len, len); - uint8_t *start_mem = (uint8_t *)args[0]; - ASSERT((offset + min_len) <= mem_len); - memcpy(ptr, start_mem + offset, min_len); - return min_len; -} - -// this is a sample implementation over memory -mol2_cursor_t mol2_make_cursor_from_memory(const void *memory, uint32_t size) { - mol2_cursor_t cur; - cur.offset = 0; - cur.size = size; - // init data source - static mol2_data_source_t s_data_source = {0}; - - s_data_source.read = mol2_source_memory; - s_data_source.total_size = size; - s_data_source.args[0] = (uintptr_t)memory; - s_data_source.args[1] = (uintptr_t)size; - - s_data_source.cache_size = 0; - s_data_source.start_point = 0; - s_data_source.max_cache_size = MAX_CACHE_SIZE; - cur.data_source = &s_data_source; - return cur; -} - -/** - * mol2_read_at reads MIN(cur->size, buff_len) bytes from data source - * "cur" into buff. It returns that number. - * - * If the return number is smaller than MIN(cur->size, buff_len), the data - * source might encounter problem. There are some reasons: - * 1. The data in data source is not consistent with molecule file (too - * small). - * 2. I/O error. It's impossible for memory data source or Syscall - * - * If a cache miss is triggered: use "read" to load from data source to the - * the cache. Then use copy from cache to "buff". - **/ -uint32_t mol2_read_at(const mol2_cursor_t *cur, uint8_t *buff, - uint32_t buff_len) { - uint32_t read_len = MIN(cur->size, buff_len); - - mol2_data_source_t *ds = cur->data_source; - // beyond cache size, "read" it directly. - if (read_len > ds->max_cache_size) { - return ds->read(ds->args, buff, read_len, cur->offset); - } - - // cache miss - if (cur->offset < ds->start_point || - ((cur->offset + read_len) > ds->start_point + ds->cache_size)) { - uint32_t size = - ds->read(ds->args, ds->cache, ds->max_cache_size, cur->offset); - if (size < read_len) { - MOL2_PANIC(MOL2_ERR_DATA); - return 0; - } - // update cache setting - ds->cache_size = size; - ds->start_point = cur->offset; - if (ds->cache_size > ds->max_cache_size) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - return 0; - } - } - // cache hit - if (cur->offset < ds->start_point || - (cur->offset - ds->start_point) > ds->max_cache_size) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - return 0; - } - uint8_t *read_point = ds->cache + cur->offset - ds->start_point; - if ((read_point + read_len) > (ds->cache + ds->cache_size)) { - MOL2_PANIC(MOL2_ERR_OVERFLOW); - return 0; - } - - memcpy(buff, read_point, read_len); - return read_len; -} - -mol2_num_t mol2_unpack_number(const mol2_cursor_t *cursor) { - uint8_t src[4]; - uint32_t len = mol2_read_at(cursor, src, 4); - if (len != 4) { - MOL2_PANIC(MOL2_ERR_DATA); - } - if (is_le2()) { - return *(const uint32_t *)src; - } else { - uint32_t output = 0; - uint8_t *dst = (uint8_t *)&output; - dst[3] = src[0]; - dst[2] = src[1]; - dst[1] = src[2]; - dst[0] = src[3]; - return output; - } -} - -#endif // MOLECULEC_C2_DECLARATION_ONLY - -/* - * Undef macros which are internal use only. - */ - -#undef is_le2 - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* MOLECULE2_READER_H */ diff --git a/include/ckb-c-stdlib/molecule/molecule_builder.h b/include/ckb-c-stdlib/molecule/molecule_builder.h deleted file mode 100644 index 30b3915..0000000 --- a/include/ckb-c-stdlib/molecule/molecule_builder.h +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef MOLECULE_BUILDER_H -#define MOLECULE_BUILDER_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include -#include - -#include "molecule_reader.h" - -#ifndef MOLECULE_API_DECORATOR -#define __DEFINE_MOLECULE_API_DECORATOR -#define MOLECULE_API_DECORATOR -#endif /* MOLECULE_API_DECORATOR */ - -/* - * This part is not for normal users. - */ - -// Test if the host is big endian machine. -#define is_le() ((union { uint16_t i; unsigned char c; }){ .i = 1 }.c) - -/* - * Definitions of types and simple utilities. - */ - -// The Builder. -// - Can be stack allocated -// - Must be initialized with `MolBuilder_Xxx_init` -// - Must be cleared with `MolBuilder_Xxx_build` or `MolBuilder_Xxx_clear` -// - Can be set with: -// - `MolBuilder_Xxx_set` (For Option) -// - `MolBuilder_Xxx_set_*` (For Union, Array, Struct, Table) -// - `MolBuilder_Xxx_push` (For FixVec, DynVec) -typedef struct { - uint8_t *data_ptr; // Data Pointer - mol_num_t data_used; // Data Used - mol_num_t data_cap; // Data Capacity - - mol_num_t *number_ptr; // A Pointer of Numbers - mol_num_t number_used; // Numbers used - mol_num_t number_cap; // Numbers Capacity -} mol_builder_t; - -/* Utilities. */ - -MOLECULE_API_DECORATOR void mol_pack_number(uint8_t *dst, mol_num_t *num) { - const uint8_t *src = (const uint8_t *)num; - if (is_le()) { - memcpy(dst, src, MOL_NUM_T_SIZE); - } else { - dst[3] = src[0]; - dst[2] = src[1]; - dst[1] = src[2]; - dst[0] = src[3]; - } -} - -/* - * Core functions. - */ - -MOLECULE_API_DECORATOR void mol_builder_discard(mol_builder_t builder) { - free(builder.data_ptr); - free(builder.number_ptr); -} - -MOLECULE_API_DECORATOR void mol_builder_initialize_fixed_size(mol_builder_t *builder, mol_num_t fixed_size) { - if (fixed_size == 0) { - builder->data_ptr = NULL; - builder->data_used = 0; - builder->data_cap = 0; - } else { - builder->data_ptr = (uint8_t*)malloc(fixed_size); - memset(builder->data_ptr, 0x00, fixed_size); - builder->data_used = fixed_size; - builder->data_cap = fixed_size; - } - builder->number_ptr = NULL; - builder->number_used = 0; - builder->number_cap = 0; -} - -MOLECULE_API_DECORATOR void mol_union_builder_initialize(mol_builder_t *builder, mol_num_t data_capacity, mol_num_t item_id, const uint8_t *default_ptr, mol_num_t default_len) { - builder->data_ptr = (uint8_t*)malloc(data_capacity); - builder->data_cap = data_capacity; - mol_pack_number(builder->data_ptr, &item_id); - builder->data_used = MOL_NUM_T_SIZE + default_len; - if (default_ptr == NULL) { - *(builder->data_ptr+MOL_NUM_T_SIZE) = 0; - } else { - memcpy(builder->data_ptr+MOL_NUM_T_SIZE, default_ptr, default_len); - } - builder->number_ptr = NULL; - builder->number_used = 0; - builder->number_cap = 0; -} - -MOLECULE_API_DECORATOR void mol_builder_initialize_with_capacity(mol_builder_t *builder, mol_num_t data_capacity, mol_num_t number_capacity) { - builder->data_ptr = (uint8_t*)malloc(data_capacity); - builder->data_used = 0; - builder->data_cap = data_capacity; - builder->number_ptr = (mol_num_t*)malloc(number_capacity); - builder->number_used = 0; - builder->number_cap = number_capacity; -} - -MOLECULE_API_DECORATOR void mol_fixvec_builder_initialize(mol_builder_t *builder, mol_num_t data_capacity) { - mol_builder_initialize_with_capacity(builder, data_capacity, MOL_NUM_T_SIZE); - builder->number_ptr[0] = 0; - builder->number_used = MOL_NUM_T_SIZE; -} - -MOLECULE_API_DECORATOR void mol_table_builder_initialize(mol_builder_t *builder, mol_num_t data_capacity, mol_num_t field_count) { - mol_builder_initialize_with_capacity(builder, data_capacity, MOL_NUM_T_SIZE * field_count * 2); - memset(builder->number_ptr, 0x00, builder->number_cap); - builder->number_used = builder->number_cap; -} - -MOLECULE_API_DECORATOR void mol_option_builder_set(mol_builder_t *builder, const uint8_t *data_ptr, mol_num_t data_len) { - builder->data_used = data_len; - if (builder->data_used == 0) { - builder->data_cap = 0; - free(builder->data_ptr); - builder->data_ptr = NULL; - } else { - if (builder->data_cap < builder->data_used) { - builder->data_cap = builder->data_used; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - memcpy(builder->data_ptr, data_ptr, builder->data_used); - } -} - -MOLECULE_API_DECORATOR void mol_union_builder_set_byte(mol_builder_t *builder, mol_num_t item_id, uint8_t data) { - builder->data_used = MOL_NUM_T_SIZE + 1; - if (builder->data_cap < builder->data_used) { - builder->data_cap = builder->data_used; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - mol_pack_number(builder->data_ptr, &item_id); - *(builder->data_ptr+MOL_NUM_T_SIZE) = data; -} - -MOLECULE_API_DECORATOR void mol_union_builder_set(mol_builder_t *builder, mol_num_t item_id, const uint8_t *data_ptr, mol_num_t data_len) { - builder->data_used = MOL_NUM_T_SIZE + data_len; - if (builder->data_cap < builder->data_used) { - builder->data_cap = builder->data_used; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - mol_pack_number(builder->data_ptr, &item_id); - memcpy(builder->data_ptr+MOL_NUM_T_SIZE, data_ptr, data_len); -} - -MOLECULE_API_DECORATOR void mol_builder_set_byte_by_offset(mol_builder_t *builder, mol_num_t offset, uint8_t data) { - *(builder->data_ptr+offset) = data; -} - -MOLECULE_API_DECORATOR void mol_builder_set_by_offset(mol_builder_t *builder, mol_num_t offset, const uint8_t *data_ptr, mol_num_t length) { - memcpy(builder->data_ptr+offset, data_ptr, length); -} - -MOLECULE_API_DECORATOR void mol_fixvec_builder_push_byte(mol_builder_t *builder, uint8_t data) { - while (builder->data_cap < builder->data_used + 1) { - builder->data_cap *= 2; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - builder->number_ptr[0] += 1; - *(builder->data_ptr+builder->data_used) = data; - builder->data_used += 1; -} - -MOLECULE_API_DECORATOR void mol_fixvec_builder_push(mol_builder_t *builder, const uint8_t *data_ptr, mol_num_t length) { - while (builder->data_cap < builder->data_used + length) { - builder->data_cap *= 2; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - builder->number_ptr[0] += 1; - memcpy(builder->data_ptr+builder->data_used, data_ptr, length); - builder->data_used += length; -} - -MOLECULE_API_DECORATOR void mol_dynvec_builder_push(mol_builder_t *builder, const uint8_t *data_ptr, mol_num_t data_len) { - while (builder->data_cap < builder->data_used + data_len) { - builder->data_cap *= 2; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - while (builder->number_cap < builder->number_used + MOL_NUM_T_SIZE) { - builder->number_cap *= 2; - builder->number_ptr = (mol_num_t*)realloc(builder->number_ptr, builder->number_cap); - } - - mol_num_t next_number_index = builder->number_used / MOL_NUM_T_SIZE; - builder->number_ptr[next_number_index] = builder->data_used; - builder->number_used += MOL_NUM_T_SIZE; - - if (data_len != 0) { - memcpy(builder->data_ptr+builder->data_used, data_ptr, data_len); - builder->data_used += data_len; - } -} - -MOLECULE_API_DECORATOR void mol_table_builder_add_byte(mol_builder_t *builder, mol_num_t field_index, uint8_t data) { - while (builder->data_cap < builder->data_used + 1) { - builder->data_cap *= 2; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - - builder->number_ptr[field_index * 2] = builder->data_used; - builder->number_ptr[field_index * 2 + 1] = 1; - *(builder->data_ptr+builder->data_used) = data; - builder->data_used += 1; -} - -MOLECULE_API_DECORATOR void mol_table_builder_add(mol_builder_t *builder, mol_num_t field_index, const uint8_t *data_ptr, mol_num_t data_len) { - if (data_len == 0) { - builder->number_ptr[field_index * 2] = 0; - builder->number_ptr[field_index * 2 + 1] = 0; - } else { - while (builder->data_cap < builder->data_used + data_len) { - builder->data_cap *= 2; - builder->data_ptr = (uint8_t*)realloc(builder->data_ptr, builder->data_cap); - } - - builder->number_ptr[field_index * 2] = builder->data_used; - builder->number_ptr[field_index * 2 + 1] = data_len; - memcpy(builder->data_ptr+builder->data_used, data_ptr, data_len); - builder->data_used += data_len; - } -} - -MOLECULE_API_DECORATOR mol_seg_res_t mol_builder_finalize_simple(mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - res.seg.ptr = builder.data_ptr; - res.seg.size = builder.data_used; - free(builder.number_ptr); - return res; -} - -MOLECULE_API_DECORATOR mol_seg_res_t mol_fixvec_builder_finalize(mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - res.seg.size = MOL_NUM_T_SIZE + builder.data_used; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - mol_pack_number(res.seg.ptr, &builder.number_ptr[0]); - if (builder.data_used > 0) { - memcpy((res.seg.ptr+MOL_NUM_T_SIZE), builder.data_ptr, builder.data_used); - } - mol_builder_discard(builder); - return res; -} - -MOLECULE_API_DECORATOR mol_seg_res_t mol_dynvec_builder_finalize(mol_builder_t builder) { - mol_seg_res_t res; - res.errno = MOL_OK; - res.seg.size = MOL_NUM_T_SIZE + builder.number_used + builder.data_used; - res.seg.ptr = (uint8_t*)malloc(res.seg.size); - mol_pack_number(res.seg.ptr, &res.seg.size); - mol_num_t number_count = builder.number_used / MOL_NUM_T_SIZE; - mol_num_t header_size = MOL_NUM_T_SIZE + builder.number_used; - for (mol_num_t number_index=0; number_index -#include - -#ifndef MOLECULE_API_DECORATOR -#define __DEFINE_MOLECULE_API_DECORATOR -#define MOLECULE_API_DECORATOR -#endif /* MOLECULE_API_DECORATOR */ - -#define MOLECULE_API_VERSION 7000 -#define MOLECULEC_VERSION_MIN 5000 - -#if MOLECULE_API_VERSION < MOLECULE_API_VERSION_MIN -#error This file was generated by a newer version of moleculec which is \ - incompatible with current headers in use. Please update the headers. -#endif - -#if MOLECULEC_VERSION < MOLECULEC_VERSION_MIN -#error This file was generated by an older version of moleculec which is \ - incompatible with current headers in use. Please regenerate this file \ - with a newer version of moleculec. -#endif - -/* - * This part is not for normal users. - */ - -// Test if the host is big endian machine. -#define is_le() ((union { uint16_t i; unsigned char c; }){ .i = 1 }.c) - -/* - * Definitions of types and simple utilities. - */ - -/* Core types */ - -typedef uint32_t mol_num_t; // Item Id - -typedef uint8_t mol_errno; // Error Number - -#define MolNum UINT32_C - -#define MOL_NUM_T_SIZE 4 - -// Bytes segment. -typedef struct { - uint8_t *ptr; // Pointer - mol_num_t size; // Full size -} mol_seg_t; - -// Unpacked Union -typedef struct { - mol_num_t item_id; // Item Id - mol_seg_t seg; // Segment -} mol_union_t; - -// Result for returning segment. -typedef struct { - mol_errno errno; // Error Number - mol_seg_t seg; // Segment -} mol_seg_res_t; - -/* Error Numbers */ - -#define MOL_OK 0x00 -#define MOL_ERR 0xff - -#define MOL_ERR_TOTAL_SIZE 0x01 -#define MOL_ERR_HEADER 0x02 -#define MOL_ERR_OFFSET 0x03 -#define MOL_ERR_UNKNOWN_ITEM 0x04 -#define MOL_ERR_INDEX_OUT_OF_BOUNDS 0x05 -#define MOL_ERR_FIELD_COUNT 0x06 -#define MOL_ERR_DATA 0x07 - -/* Utilities. */ - -MOLECULE_API_DECORATOR mol_num_t mol_unpack_number(const uint8_t *src) { - uint32_t output = 0; - uint8_t *dst = (uint8_t*) &output; - if (is_le()) { - dst[3] = src[3]; - dst[2] = src[2]; - dst[1] = src[1]; - dst[0] = src[0]; - } else { - dst[3] = src[0]; - dst[2] = src[1]; - dst[1] = src[2]; - dst[0] = src[3]; - } - return output; -} - - -/* - * Core functions. - */ - -/* Verify Functions. */ - -// Verify Array / Struct. -MOLECULE_API_DECORATOR mol_errno mol_verify_fixed_size(const mol_seg_t *input, mol_num_t total_size) { - return input->size == total_size ? MOL_OK : MOL_ERR_TOTAL_SIZE; -} - -// Verify FixVec. -MOLECULE_API_DECORATOR mol_errno mol_fixvec_verify(const mol_seg_t *input, mol_num_t item_size) { - if (input->size < MOL_NUM_T_SIZE) { - return MOL_ERR_HEADER; - } - mol_num_t item_count = mol_unpack_number(input->ptr); - if (item_count == 0) { - return input->size == MOL_NUM_T_SIZE ? MOL_OK : MOL_ERR_TOTAL_SIZE; - } - mol_num_t total_size = MOL_NUM_T_SIZE + item_size * item_count; - return input->size == total_size ? MOL_OK : MOL_ERR_TOTAL_SIZE; -} - -/* Getters. - * - * ### Notice - * - * The input of getters should be checked. - * - * These getters will raise segmentation fault if the input is illegal or - * return an incorrect result. - */ - -// Check if an Option is None. -MOLECULE_API_DECORATOR bool mol_option_is_none(const mol_seg_t *input) { - return input->size == 0; -} - -// Get the inner of a Union. -MOLECULE_API_DECORATOR mol_union_t mol_union_unpack(const mol_seg_t *input) { - mol_union_t ret; - ret.item_id = mol_unpack_number(input->ptr); - ret.seg.ptr = input->ptr + MOL_NUM_T_SIZE; - ret.seg.size = input->size - MOL_NUM_T_SIZE; - return ret; -} - -// Get the length of a FixVec. -MOLECULE_API_DECORATOR mol_num_t mol_fixvec_length(const mol_seg_t *input) { - return mol_unpack_number(input->ptr); -} - -// Get the length of a DynVec. -MOLECULE_API_DECORATOR mol_num_t mol_dynvec_length(const mol_seg_t *input) { - if (input->size == MOL_NUM_T_SIZE) { - return 0; - } else { - return (mol_unpack_number(input->ptr + MOL_NUM_T_SIZE) / 4) - 1; - } -} - -// Get the actual field count of a Table. -MOLECULE_API_DECORATOR mol_num_t mol_table_actual_field_count(const mol_seg_t *input) { - return mol_dynvec_length(input); -} - -// If a Table has extra fields. -MOLECULE_API_DECORATOR bool mol_table_has_extra_fields(const mol_seg_t *input, mol_num_t field_count) { - return mol_table_actual_field_count(input) > field_count; -} - -// Slice a segment for Array / Struct by offset. -MOLECULE_API_DECORATOR mol_seg_t mol_slice_by_offset(const mol_seg_t *input, mol_num_t offset, mol_num_t size) { - mol_seg_t seg; - seg.ptr = input->ptr + offset; - seg.size = size; - return seg; -} - -// Slice a segment for FixVec by index. -MOLECULE_API_DECORATOR mol_seg_res_t mol_fixvec_slice_by_index(const mol_seg_t *input, mol_num_t item_size, mol_num_t item_index) { - mol_seg_res_t res; - mol_num_t item_count = mol_unpack_number(input->ptr); - if (item_index >= item_count) { - res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS; - } else { - res.errno = MOL_OK; - res.seg.ptr = input->ptr + MOL_NUM_T_SIZE + item_size * item_index; - res.seg.size = item_size; - } - return res; -} - -// Slice a segment for DynVec by index. -MOLECULE_API_DECORATOR mol_seg_res_t mol_dynvec_slice_by_index(const mol_seg_t *input, mol_num_t item_index) { - mol_seg_res_t res; - mol_num_t total_size = mol_unpack_number(input->ptr); - if (total_size == MOL_NUM_T_SIZE) { - res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS; - } else { - mol_num_t item_count = (mol_unpack_number(input->ptr + MOL_NUM_T_SIZE) / 4) - 1; - if (item_index >= item_count) { - res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS; - } else { - mol_num_t item_start = mol_unpack_number(input->ptr + MOL_NUM_T_SIZE * (item_index + 1)); - if (item_index + 1 == item_count) { - res.errno = MOL_OK; - res.seg.ptr = input->ptr + item_start; - res.seg.size = total_size - item_start; - } else { - mol_num_t item_end = mol_unpack_number(input->ptr + MOL_NUM_T_SIZE * (item_index + 2)); - res.errno = MOL_OK; - res.seg.ptr = input->ptr + item_start; - res.seg.size = item_end - item_start; - } - } - } - return res; -} - - -// Slice a segment for Table by index. -MOLECULE_API_DECORATOR mol_seg_t mol_table_slice_by_index(const mol_seg_t *input, mol_num_t field_index) { - mol_seg_res_t res = mol_dynvec_slice_by_index(input, field_index); - return res.seg; -} - -// Slice the raw bytes from a `vector ` (FixVec, with a header). -MOLECULE_API_DECORATOR mol_seg_t mol_fixvec_slice_raw_bytes(const mol_seg_t *input) { - mol_seg_t seg; - seg.ptr = input->ptr + MOL_NUM_T_SIZE; - seg.size = mol_unpack_number(input->ptr); - return seg; -} - -/* - * Undef macros which are internal use only. - */ - -#undef is_le - -#ifdef __DEFINE_MOLECULE_API_DECORATOR -#undef MOLECULE_API_DECORATOR -#undef __DEFINE_MOLECULE_API_DECORATOR -#endif /* __DEFINE_MOLECULE_API_DECORATOR */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* MOLECULE_READER_H */ diff --git a/include/ckb-c-stdlib/simulator/README.md b/include/ckb-c-stdlib/simulator/README.md deleted file mode 100644 index 1d6ca18..0000000 --- a/include/ckb-c-stdlib/simulator/README.md +++ /dev/null @@ -1,64 +0,0 @@ - -# Simulator -The target of simulator is to compile, run code (which will be run on CKB-VM) on any OS and PC. -The we can use our favorite IDE and OS. It can only speed up development but don't skip necessary steps like testing on real CKB-VM. - -This is a library: see [ckb-miscellaneous-scripts](https://github.com/nervosnetwork/ckb-miscellaneous-scripts/tree/master/simulator) to get more idea about how to use it. - -## Changes -There some changes: -- All contents under simulator folder -- All code enabled by CKB_SIMULATOR macro - -If you don't want to use the simulator feature, just ignore the folder. - -## How to run -See more in run-simulator.sh script in [ckb-miscellaneous-scripts](https://github.com/nervosnetwork/ckb-miscellaneous-scripts/tree/master/simulator). - -## How to get json file -Dump json using [ckb-transaction-dumper](https://github.com/xxuejie/ckb-transaction-dumper). We need a running mainnet -on local machine to dump json. In the following example, we named the dumped json: "original.json". - -Then write a root json file manually (named it data.json): -```json -{ - "is_lock_script": true, - "script_index": 0, - "main": "0xa98c212cf055cedbbb665d475c0561b56c68ea735c8aa830c493264effaf18bd", - "0xa98c212cf055cedbbb665d475c0561b56c68ea735c8aa830c493264effaf18bd": "original.json" -} -``` -* is_lock_script, the script to run is "lock" script or "type" script -* script_index, the index of the script in "input" -* main, the tx hash of the dumped json -* "tx_hash": the file name of the dumped json. The key part should be same as the value part of "main". - -It might be possible to extend this json to support more TX data. - - -When run the executables, pass this json file name (data.json, not original.json) as first arguments. -See more in simulator/run-simulator.sh : - -```bash -../build.simulator/sighash_all data.json -../build.simulator/sighash_all data2.json -../build.simulator/sighash_all data3.json -../build.simulator/sudt sudt_data.json -``` - -There are more example data under simulator/data folder. - - -## Used as a library -The simulator is also compiled into library. After build, we can find -library file "libckb_simulator.a". (location simulator/build.simulator/libckb_simulator.a). -It must be used together with following files and macro: -- simulator/ckb_syscall_simulator.h -- optional simulator/blake2b_imp.c file -- macro: CKB_SIMULATOR, see example in secp256k1_blake2b_sighash_all_dual.c - - - -Explanation of extra blake2b_imp.c file: Some contracts include implementation of blake2b directly -but some don't. So we don't include implementation of blake2b source in library. -For example, simple_udt doesn't include it so we need to add it to project manually. diff --git a/include/ckb-c-stdlib/simulator/blake2b_decl_only.h b/include/ckb-c-stdlib/simulator/blake2b_decl_only.h deleted file mode 100644 index a9ac0ac..0000000 --- a/include/ckb-c-stdlib/simulator/blake2b_decl_only.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef CKB_MISCELLANEOUS_SCRIPTS_SIMULATOR_BLAKE2B_DECL_ONLY_H_ -#define CKB_MISCELLANEOUS_SCRIPTS_SIMULATOR_BLAKE2B_DECL_ONLY_H_ -#include -#include - -enum blake2b_constant { - BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, - BLAKE2B_PERSONALBYTES = 16 -}; - -typedef struct blake2b_state__ { - uint64_t h[8]; - uint64_t t[2]; - uint64_t f[2]; - uint8_t buf[BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; -} blake2b_state; - -/* Streaming API */ -int ckb_blake2b_init(blake2b_state *S, size_t outlen); -int blake2b_init(blake2b_state *S, size_t outlen); -int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, - size_t keylen); -int blake2b_update(blake2b_state *S, const void *in, size_t inlen); -int blake2b_final(blake2b_state *S, void *out, size_t outlen); -/* Simple API */ -int blake2b(void *out, size_t outlen, const void *in, size_t inlen, - const void *key, size_t keylen); - -/* This is simply an alias for blake2b */ -int blake2(void *out, size_t outlen, const void *in, size_t inlen, - const void *key, size_t keylen); - -#endif // CKB_MISCELLANEOUS_SCRIPTS_SIMULATOR_BLAKE2B_DECL_ONLY_H_ diff --git a/include/ckb-c-stdlib/simulator/blake2b_imp.c b/include/ckb-c-stdlib/simulator/blake2b_imp.c deleted file mode 100644 index 25647a8..0000000 --- a/include/ckb-c-stdlib/simulator/blake2b_imp.c +++ /dev/null @@ -1,2 +0,0 @@ - -#include "blake2b.h" diff --git a/include/ckb-c-stdlib/simulator/cJSON.c b/include/ckb-c-stdlib/simulator/cJSON.c deleted file mode 100644 index 1a8ac79..0000000 --- a/include/ckb-c-stdlib/simulator/cJSON.c +++ /dev/null @@ -1,2780 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) -#define _CRT_SECURE_NO_DEPRECATE -#endif - -#ifdef __GNUC__ -#pragma GCC visibility push(default) -#endif -#if defined(_MSC_VER) -#pragma warning(push) -/* disable warning about single line comments in system headers */ -#pragma warning(disable : 4001) -#endif - -#include -#include -#include -#include -#include -#include -#include - -// The ckb's C lib doesn't include these declarations. -// double strtod (const char* str, char** endptr); -// int sscanf ( const char * s, const char * format, ...); -// int strncmp ( const char * str1, const char * str2, size_t num ); -// int sprintf ( char * str, const char * format, ... ); - -#ifdef ENABLE_LOCALES -#include -#endif - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -#ifdef __GNUC__ -#pragma GCC visibility pop -#endif - -#include "cJSON.h" - -/* define our own boolean type */ -#ifdef true -#undef true -#endif -#define true 1 - -#ifdef false -#undef false -#endif -#define false 0 - -/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has - * been defined in math.h */ -#ifndef isinf -#define isinf(d) (isnan((d - d)) && !isnan(d)) -#endif -#ifndef isnan -#define isnan(d) (d != d) -#endif - -#ifndef NAN -#ifdef _WIN32 -#define NAN sqrt(-1.0) -#else -#define NAN 0.0 / 0.0 -#endif -#endif - -typedef struct { - const unsigned char *json; - size_t position; -} error; -static error global_error = {NULL, 0}; - -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { - return (const char *)(global_error.json + global_error.position); -} - -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) { - if (!cJSON_IsString(item)) { - return NULL; - } - - return item->valuestring; -} - -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) { - if (!cJSON_IsNumber(item)) { - return (double)NAN; - } - - return item->valuedouble; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and - * header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || \ - (CJSON_VERSION_PATCH != 14) -#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char *) cJSON_Version(void) { - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, - CJSON_VERSION_PATCH); - - return version; -} - -/* Case insensitive string comparison, doesn't consider two NULL pointers equal - * though */ -static int case_insensitive_strcmp(const unsigned char *string1, - const unsigned char *string2) { - if ((string1 == NULL) || (string2 == NULL)) { - return 1; - } - - if (string1 == string2) { - return 0; - } - - for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { - if (*string1 == '\0') { - return 0; - } - } - - return tolower(*string1) - tolower(*string2); -} - -typedef struct internal_hooks { - void *(CJSON_CDECL *allocate)(size_t size); - void(CJSON_CDECL *deallocate)(void *pointer); - void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); -} internal_hooks; - -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dllimport '...' is not static - */ -static void *CJSON_CDECL internal_malloc(size_t size) { return malloc(size); } -static void CJSON_CDECL internal_free(void *pointer) { free(pointer); } -static void *CJSON_CDECL internal_realloc(void *pointer, size_t size) { - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -/* strlen of character literals resolved at compile time */ -#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) - -static internal_hooks global_hooks = {internal_malloc, internal_free, - internal_realloc}; - -static unsigned char *cJSON_strdup(const unsigned char *string, - const internal_hooks *const hooks) { - size_t length = 0; - unsigned char *copy = NULL; - - if (string == NULL) { - return NULL; - } - - length = strlen((const char *)string) + sizeof(""); - copy = (unsigned char *)hooks->allocate(length); - if (copy == NULL) { - return NULL; - } - memcpy(copy, string, length); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks) { - if (hooks == NULL) { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks *const hooks) { - cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON)); - if (node) { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) { - cJSON *next = NULL; - while (item != NULL) { - next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { - cJSON_Delete(item->child); - } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { - global_hooks.deallocate(item->valuestring); - } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { - global_hooks.deallocate(item->string); - } - global_hooks.deallocate(item); - item = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) { -#ifdef ENABLE_LOCALES - struct lconv *lconv = localeconv(); - return (unsigned char)lconv->decimal_point[0]; -#else - return '.'; -#endif -} - -typedef struct { - const unsigned char *content; - size_t length; - size_t offset; - size_t depth; /* How deeply nested (in arrays/objects) is the input at the - current offset. */ - internal_hooks hooks; -} parse_buffer; - -/* check if the given size is left to read in a given parse buffer (starting - * with 1) */ -#define can_read(buffer, size) \ - ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) -/* check if the buffer can be accessed at the given index (starting with 0) */ -#define can_access_at_index(buffer, index) \ - ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) -#define cannot_access_at_index(buffer, index) \ - (!can_access_at_index(buffer, index)) -/* get a pointer to the buffer at the position */ -#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) - -/* Parse the input text to generate a number, and populate the result into item. - */ -static cJSON_bool parse_number(cJSON *const item, - parse_buffer *const input_buffer) { - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if ((input_buffer == NULL) || (input_buffer->content == NULL)) { - return false; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal - * point of the current locale (for strtod) This also takes care of '\0' not - * necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && - can_access_at_index(input_buffer, i); - i++) { - switch (buffer_at_offset(input_buffer)[i]) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = strtod((const char *)number_c_string, (char **)&after_end); - if (number_c_string == after_end) { - return false; /* parse_error */ - } - - item->valuedouble = number; - - /* use saturation in case of overflow */ - if (number >= INT_MAX) { - item->valueint = INT_MAX; - } else if (number <= (double)INT_MIN) { - item->valueint = INT_MIN; - } else { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - input_buffer->offset += (size_t)(after_end - number_c_string); - return true; -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or - * double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) { - if (number >= INT_MAX) { - object->valueint = INT_MAX; - } else if (number <= (double)INT_MIN) { - object->valueint = INT_MIN; - } else { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -CJSON_PUBLIC(char *) -cJSON_SetValuestring(cJSON *object, const char *valuestring) { - char *copy = NULL; - /* if object's type is not cJSON_String or is cJSON_IsReference, it should not - * set valuestring */ - if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { - return NULL; - } - if (strlen(valuestring) <= strlen(object->valuestring)) { - strcpy(object->valuestring, valuestring); - return object->valuestring; - } - copy = - (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); - if (copy == NULL) { - return NULL; - } - if (object->valuestring != NULL) { - cJSON_free(object->valuestring); - } - object->valuestring = copy; - - return copy; -} - -typedef struct { - unsigned char *buffer; - size_t length; - size_t offset; - size_t depth; /* current nesting depth (for formatted printing) */ - cJSON_bool noalloc; - cJSON_bool format; /* is this print a formatted print */ - internal_hooks hooks; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char *ensure(printbuffer *const p, size_t needed) { - unsigned char *newbuffer = NULL; - size_t newsize = 0; - - if ((p == NULL) || (p->buffer == NULL)) { - return NULL; - } - - if ((p->length > 0) && (p->offset >= p->length)) { - /* make sure that offset is valid */ - return NULL; - } - - if (needed > INT_MAX) { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if (needed <= p->length) { - return p->buffer + p->offset; - } - - if (p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) { - newsize = INT_MAX; - } else { - return NULL; - } - } else { - newsize = needed * 2; - } - - if (p->hooks.reallocate != NULL) { - /* reallocate with realloc if available */ - newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - } else { - /* otherwise reallocate manually */ - newbuffer = (unsigned char *)p->hooks.allocate(newsize); - if (!newbuffer) { - p->hooks.deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - if (newbuffer) { - memcpy(newbuffer, p->buffer, p->offset + 1); - } - p->hooks.deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset - */ -static void update_offset(printbuffer *const buffer) { - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char *)buffer_pointer); -} - -/* securely comparison of floating-point variables */ -static cJSON_bool compare_double(double a, double b) { - double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); - return (fabs(a - b) <= maxVal * DBL_EPSILON); -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON *const item, - printbuffer *const output_buffer) { - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - unsigned char number_buffer[26] = { - 0}; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - double test = 0.0; - - if (output_buffer == NULL) { - return false; - } - - /* This checks for NaN and Infinity */ - if (isnan(d) || isinf(d)) { - length = sprintf((char *)number_buffer, "null"); - } else { - /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits - */ - length = sprintf((char *)number_buffer, "%1.15g", d); - - /* Check whether the original double can be recovered */ - if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || - !compare_double((double)test, d)) { - /* If not, print with 17 decimal places of precision */ - length = sprintf((char *)number_buffer, "%1.17g", d); - } - } - - /* sprintf failed or buffer overrun occurred */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { - return false; - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) { - if (number_buffer[i] == decimal_point) { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char *const input) { - unsigned int h = 0; - size_t i = 0; - - for (i = 0; i < 4; i++) { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) { - h += (unsigned int)input[i] - '0'; - } else if ((input[i] >= 'A') && (input[i] <= 'F')) { - h += (unsigned int)10 + input[i] - 'A'; - } else if ((input[i] >= 'a') && (input[i] <= 'f')) { - h += (unsigned int)10 + input[i] - 'a'; - } else /* invalid */ - { - return 0; - } - - if (i < 3) { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8( - const unsigned char *const input_pointer, - const unsigned char *const input_end, unsigned char **output_pointer) { - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if ((input_end - first_sequence) < 6) { - /* input ends unexpectedly */ - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { - goto fail; - } - - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if ((input_end - second_sequence) < 6) { - /* input ends unexpectedly */ - goto fail; - } - - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { - /* missing second half of the surrogate pair */ - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { - /* invalid second half of the surrogate pair */ - goto fail; - } - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = - 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } else { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } else if (codepoint < 0x800) { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } else if (codepoint < 0x10000) { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } else if (codepoint <= 0x10FFFF) { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } else { - /* invalid unicode codepoint */ - goto fail; - } - - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; - utf8_position--) { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = - (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if (utf8_length > 1) { - (*output_pointer)[0] = - (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } else { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON *const item, - parse_buffer *const input_buffer) { - const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; - const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') { - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while ( - ((size_t)(input_end - input_buffer->content) < input_buffer->length) && - (*input_end != '\"')) { - /* is escape sequence */ - if (input_end[0] == '\\') { - if ((size_t)(input_end + 1 - input_buffer->content) >= - input_buffer->length) { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || - (*input_end != '\"')) { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = - (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + - sizeof("")); - if (output == NULL) { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) { - if (*input_pointer != '\\') { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else { - unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) { - goto fail; - } - - switch (input_pointer[1]) { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = - utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char *)output; - - input_buffer->offset = (size_t)(input_end - input_buffer->content); - input_buffer->offset++; - - return true; - -fail: - if (output != NULL) { - input_buffer->hooks.deallocate(output); - } - - if (input_pointer != NULL) { - input_buffer->offset = (size_t)(input_pointer - input_buffer->content); - } - - return false; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char *const input, - printbuffer *const output_buffer) { - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if (output_buffer == NULL) { - return false; - } - - /* empty string */ - if (input == NULL) { - output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) { - return false; - } - strcpy((char *)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) { - switch (*input_pointer) { - case '\"': - case '\\': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - /* one character escape sequence */ - escape_characters++; - break; - default: - if (*input_pointer < 32) { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - break; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) { - return false; - } - - /* no characters have to be escaped */ - if (escape_characters == 0) { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; - (void)input_pointer++, output_pointer++) { - if ((*input_pointer > 31) && (*input_pointer != '\"') && - (*input_pointer != '\\')) { - /* normal character, copy */ - *output_pointer = *input_pointer; - } else { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char *)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) { - return print_string_ptr((unsigned char *)item->valuestring, p); -} - -/* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON *const item, - parse_buffer *const input_buffer); -static cJSON_bool print_value(const cJSON *const item, - printbuffer *const output_buffer); -static cJSON_bool parse_array(cJSON *const item, - parse_buffer *const input_buffer); -static cJSON_bool print_array(const cJSON *const item, - printbuffer *const output_buffer); -static cJSON_bool parse_object(cJSON *const item, - parse_buffer *const input_buffer); -static cJSON_bool print_object(const cJSON *const item, - printbuffer *const output_buffer); - -/* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL)) { - return NULL; - } - - if (cannot_access_at_index(buffer, 0)) { - return buffer; - } - - while (can_access_at_index(buffer, 0) && - (buffer_at_offset(buffer)[0] <= 32)) { - buffer->offset++; - } - - if (buffer->offset == buffer->length) { - buffer->offset--; - } - - return buffer; -} - -/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { - return NULL; - } - - if (can_access_at_index(buffer, 4) && - (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == - 0)) { - buffer->offset += 3; - } - - return buffer; -} - -CJSON_PUBLIC(cJSON *) -cJSON_ParseWithOpts(const char *value, const char **return_parse_end, - cJSON_bool require_null_terminated) { - size_t buffer_length; - - if (NULL == value) { - return NULL; - } - - /* Adding null character size due to require_null_terminated. */ - buffer_length = strlen(value) + sizeof(""); - - return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, - require_null_terminated); -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) -cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, - const char **return_parse_end, - cJSON_bool require_null_terminated) { - parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}}; - cJSON *item = NULL; - - /* reset error position */ - global_error.json = NULL; - global_error.position = 0; - - if (value == NULL || 0 == buffer_length) { - goto fail; - } - - buffer.content = (const unsigned char *)value; - buffer.length = buffer_length; - buffer.offset = 0; - buffer.hooks = global_hooks; - - item = cJSON_New_Item(&global_hooks); - if (item == NULL) /* memory fail */ - { - goto fail; - } - - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { - /* parse failure. ep is set. */ - goto fail; - } - - /* if we require null-terminated JSON without appended garbage, skip and then - * check for a null terminator */ - if (require_null_terminated) { - buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || - buffer_at_offset(&buffer)[0] != '\0') { - goto fail; - } - } - if (return_parse_end) { - *return_parse_end = (const char *)buffer_at_offset(&buffer); - } - - return item; - -fail: - if (item != NULL) { - cJSON_Delete(item); - } - - if (value != NULL) { - error local_error; - local_error.json = (const unsigned char *)value; - local_error.position = 0; - - if (buffer.offset < buffer.length) { - local_error.position = buffer.offset; - } else if (buffer.length > 0) { - local_error.position = buffer.length - 1; - } - - if (return_parse_end != NULL) { - *return_parse_end = (const char *)local_error.json + local_error.position; - } - - global_error = local_error; - } - - return NULL; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) { - return cJSON_ParseWithOpts(value, 0, 0); -} - -CJSON_PUBLIC(cJSON *) -cJSON_ParseWithLength(const char *value, size_t buffer_length) { - return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); -} - -#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) - -static unsigned char *print(const cJSON *const item, cJSON_bool format, - const internal_hooks *const hooks) { - static const size_t default_buffer_size = 256; - printbuffer buffer[1]; - unsigned char *printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size); - buffer->length = default_buffer_size; - buffer->format = format; - buffer->hooks = *hooks; - if (buffer->buffer == NULL) { - goto fail; - } - - /* print the value */ - if (!print_value(item, buffer)) { - goto fail; - } - update_offset(buffer); - - /* check if reallocate is available */ - if (hooks->reallocate != NULL) { - printed = - (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1); - if (printed == NULL) { - goto fail; - } - buffer->buffer = NULL; - } else /* otherwise copy the JSON over to a new buffer */ - { - printed = (unsigned char *)hooks->allocate(buffer->offset + 1); - if (printed == NULL) { - goto fail; - } - memcpy(printed, buffer->buffer, - cjson_min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - } - - return printed; - -fail: - if (buffer->buffer != NULL) { - hooks->deallocate(buffer->buffer); - } - - if (printed != NULL) { - hooks->deallocate(printed); - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) { - return (char *)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) { - return (char *)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char *) -cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) { - printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}}; - - if (prebuffer < 0) { - return NULL; - } - - p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - p.format = fmt; - p.hooks = global_hooks; - - if (!print_value(item, &p)) { - global_hooks.deallocate(p.buffer); - return NULL; - } - - return (char *)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, - const cJSON_bool format) { - printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}}; - - if ((length < 0) || (buffer == NULL)) { - return false; - } - - p.buffer = (unsigned char *)buffer; - p.length = (size_t)length; - p.offset = 0; - p.noalloc = true; - p.format = format; - p.hooks = global_hooks; - - return print_value(item, &p); -} - -/* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON *const item, - parse_buffer *const input_buffer) { - if ((input_buffer == NULL) || (input_buffer->content == NULL)) { - return false; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if (can_read(input_buffer, 4) && - (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { - item->type = cJSON_NULL; - input_buffer->offset += 4; - return true; - } - /* false */ - if (can_read(input_buffer, 5) && - (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == - 0)) { - item->type = cJSON_False; - input_buffer->offset += 5; - return true; - } - /* true */ - if (can_read(input_buffer, 4) && - (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { - item->type = cJSON_True; - item->valueint = 1; - input_buffer->offset += 4; - return true; - } - /* string */ - if (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == '\"')) { - return parse_string(item, input_buffer); - } - /* number */ - if (can_access_at_index(input_buffer, 0) && - ((buffer_at_offset(input_buffer)[0] == '-') || - ((buffer_at_offset(input_buffer)[0] >= '0') && - (buffer_at_offset(input_buffer)[0] <= '9')))) { - return parse_number(item, input_buffer); - } - /* array */ - if (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == '[')) { - return parse_array(item, input_buffer); - } - /* object */ - if (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == '{')) { - return parse_object(item, input_buffer); - } - - return false; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON *const item, - printbuffer *const output_buffer) { - unsigned char *output = NULL; - - if ((item == NULL) || (output_buffer == NULL)) { - return false; - } - - switch ((item->type) & 0xFF) { - case cJSON_NULL: - output = ensure(output_buffer, 5); - if (output == NULL) { - return false; - } - strcpy((char *)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6); - if (output == NULL) { - return false; - } - strcpy((char *)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5); - if (output == NULL) { - return false; - } - strcpy((char *)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer); - - case cJSON_Raw: { - size_t raw_length = 0; - if (item->valuestring == NULL) { - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length); - if (output == NULL) { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer); - - case cJSON_Array: - return print_array(item, output_buffer); - - case cJSON_Object: - return print_object(item, output_buffer); - - default: - return false; - } -} - -/* Build an array from input text. */ -static cJSON_bool parse_array(cJSON *const item, - parse_buffer *const input_buffer) { - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (buffer_at_offset(input_buffer)[0] != '[') { - /* not an array */ - goto fail; - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == ']')) { - /* empty array */ - goto success; - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) { - /* start the linked list */ - current_item = head = new_item; - } else { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } while (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || - buffer_at_offset(input_buffer)[0] != ']') { - goto fail; /* expected end of array */ - } - -success: - input_buffer->depth--; - - if (head != NULL) { - head->prev = current_item; - } - - item->type = cJSON_Array; - item->child = head; - - input_buffer->offset++; - - return true; - -fail: - if (head != NULL) { - cJSON_Delete(head); - } - - return false; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON *const item, - printbuffer *const output_buffer) { - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; - - if (output_buffer == NULL) { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - output_buffer->depth++; - - while (current_element != NULL) { - if (!print_value(current_element, output_buffer)) { - return false; - } - update_offset(output_buffer); - if (current_element->next) { - length = (size_t)(output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) { - return false; - } - *output_pointer++ = ','; - if (output_buffer->format) { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Build an object from the text. */ -static cJSON_bool parse_object(cJSON *const item, - parse_buffer *const input_buffer) { - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; - - if (input_buffer->depth >= CJSON_NESTING_LIMIT) { - return false; /* to deeply nested */ - } - input_buffer->depth++; - - if (cannot_access_at_index(input_buffer, 0) || - (buffer_at_offset(input_buffer)[0] != '{')) { - goto fail; /* not an object */ - } - - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == '}')) { - goto success; /* empty object */ - } - - /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) { - input_buffer->offset--; - goto fail; - } - - /* step back to character in front of the first element */ - input_buffer->offset--; - /* loop through the comma separated array elements */ - do { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) { - /* start the linked list */ - current_item = head = new_item; - } else { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse the name of the child */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) { - goto fail; /* failed to parse name */ - } - buffer_skip_whitespace(input_buffer); - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if (cannot_access_at_index(input_buffer, 0) || - (buffer_at_offset(input_buffer)[0] != ':')) { - goto fail; /* invalid object */ - } - - /* parse the value */ - input_buffer->offset++; - buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) { - goto fail; /* failed to parse value */ - } - buffer_skip_whitespace(input_buffer); - } while (can_access_at_index(input_buffer, 0) && - (buffer_at_offset(input_buffer)[0] == ',')); - - if (cannot_access_at_index(input_buffer, 0) || - (buffer_at_offset(input_buffer)[0] != '}')) { - goto fail; /* expected end of object */ - } - -success: - input_buffer->depth--; - - if (head != NULL) { - head->prev = current_item; - } - - item->type = cJSON_Object; - item->child = head; - - input_buffer->offset++; - return true; - -fail: - if (head != NULL) { - cJSON_Delete(head); - } - - return false; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON *const item, - printbuffer *const output_buffer) { - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; - - if (output_buffer == NULL) { - return false; - } - - /* Compose the output: */ - length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) { - return false; - } - - *output_pointer++ = '{'; - output_buffer->depth++; - if (output_buffer->format) { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while (current_item) { - if (output_buffer->format) { - size_t i; - output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) { - return false; - } - for (i = 0; i < output_buffer->depth; i++) { - *output_pointer++ = '\t'; - } - output_buffer->offset += output_buffer->depth; - } - - /* print key */ - if (!print_string_ptr((unsigned char *)current_item->string, - output_buffer)) { - return false; - } - update_offset(output_buffer); - - length = (size_t)(output_buffer->format ? 2 : 1); - output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) { - return false; - } - *output_pointer++ = ':'; - if (output_buffer->format) { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if (!print_value(current_item, output_buffer)) { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = ((size_t)(output_buffer->format ? 1 : 0) + - (size_t)(current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) { - return false; - } - if (current_item->next) { - *output_pointer++ = ','; - } - - if (output_buffer->format) { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure( - output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) { - return false; - } - if (output_buffer->format) { - size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - output_buffer->depth--; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) { - cJSON *child = NULL; - size_t size = 0; - - if (array == NULL) { - return 0; - } - - child = array->child; - - while (child != NULL) { - size++; - child = child->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)size; -} - -static cJSON *get_array_item(const cJSON *array, size_t index) { - cJSON *current_child = NULL; - - if (array == NULL) { - return NULL; - } - - current_child = array->child; - while ((current_child != NULL) && (index > 0)) { - index--; - current_child = current_child->next; - } - - return current_child; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) { - if (index < 0) { - return NULL; - } - - return get_array_item(array, (size_t)index); -} - -static cJSON *get_object_item(const cJSON *const object, const char *const name, - const cJSON_bool case_sensitive) { - cJSON *current_element = NULL; - - if ((object == NULL) || (name == NULL)) { - return NULL; - } - - current_element = object->child; - if (case_sensitive) { - while ((current_element != NULL) && (current_element->string != NULL) && - (strcmp(name, current_element->string) != 0)) { - current_element = current_element->next; - } - } else { - while ((current_element != NULL) && - (case_insensitive_strcmp( - (const unsigned char *)name, - (const unsigned char *)(current_element->string)) != 0)) { - current_element = current_element->next; - } - } - - if ((current_element == NULL) || (current_element->string == NULL)) { - return NULL; - } - - return current_element; -} - -CJSON_PUBLIC(cJSON *) -cJSON_GetObjectItem(const cJSON *const object, const char *const string) { - return get_object_item(object, string, false); -} - -CJSON_PUBLIC(cJSON *) -cJSON_GetObjectItemCaseSensitive(const cJSON *const object, - const char *const string) { - return get_object_item(object, string, true); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_HasObjectItem(const cJSON *object, const char *string) { - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) { - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, - const internal_hooks *const hooks) { - cJSON *reference = NULL; - if (item == NULL) { - return NULL; - } - - reference = cJSON_New_Item(hooks); - if (reference == NULL) { - return NULL; - } - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; -} - -static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) { - cJSON *child = NULL; - - if ((item == NULL) || (array == NULL) || (array == item)) { - return false; - } - - child = array->child; - /* - * To find the last item in array quickly, we use prev in array - */ - if (child == NULL) { - /* list is empty, start new one */ - array->child = item; - item->prev = item; - item->next = NULL; - } else { - /* append to the end */ - if (child->prev) { - suffix_object(child->prev, item); - array->child->prev = item; - } - } - - return true; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) { - return add_item_to_array(array, item); -} - -#if defined(__clang__) || \ - (defined(__GNUC__) && \ - ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) -#pragma GCC diagnostic push -#endif -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -/* helper function to cast away const */ -static void *cast_away_const(const void *string) { return (void *)string; } -#if defined(__clang__) || \ - (defined(__GNUC__) && \ - ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) -#pragma GCC diagnostic pop -#endif - -static cJSON_bool add_item_to_object(cJSON *const object, - const char *const string, - cJSON *const item, - const internal_hooks *const hooks, - const cJSON_bool constant_key) { - char *new_key = NULL; - int new_type = cJSON_Invalid; - - if ((object == NULL) || (string == NULL) || (item == NULL) || - (object == item)) { - return false; - } - - if (constant_key) { - new_key = (char *)cast_away_const(string); - new_type = item->type | cJSON_StringIsConst; - } else { - new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks); - if (new_key == NULL) { - return false; - } - - new_type = item->type & ~cJSON_StringIsConst; - } - - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { - hooks->deallocate(item->string); - } - - item->string = new_key; - item->type = new_type; - - return add_item_to_array(object, item); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) { - return add_item_to_object(object, string, item, &global_hooks, false); -} - -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) { - return add_item_to_object(object, string, item, &global_hooks, true); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) { - if (array == NULL) { - return false; - } - - return add_item_to_array(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) { - if ((object == NULL) || (string == NULL)) { - return false; - } - - return add_item_to_object(object, string, - create_reference(item, &global_hooks), - &global_hooks, false); -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddNullToObject(cJSON *const object, const char *const name) { - cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) { - return null; - } - - cJSON_Delete(null); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddTrueToObject(cJSON *const object, const char *const name) { - cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) { - return true_item; - } - - cJSON_Delete(true_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddFalseToObject(cJSON *const object, const char *const name) { - cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) { - return false_item; - } - - cJSON_Delete(false_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddBoolToObject(cJSON *const object, const char *const name, - const cJSON_bool boolean) { - cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) { - return bool_item; - } - - cJSON_Delete(bool_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddNumberToObject(cJSON *const object, const char *const name, - const double number) { - cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) { - return number_item; - } - - cJSON_Delete(number_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddStringToObject(cJSON *const object, const char *const name, - const char *const string) { - cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) { - return string_item; - } - - cJSON_Delete(string_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddRawToObject(cJSON *const object, const char *const name, - const char *const raw) { - cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) { - return raw_item; - } - - cJSON_Delete(raw_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddObjectToObject(cJSON *const object, const char *const name) { - cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) { - return object_item; - } - - cJSON_Delete(object_item); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_AddArrayToObject(cJSON *const object, const char *const name) { - cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) { - return array; - } - - cJSON_Delete(array); - return NULL; -} - -CJSON_PUBLIC(cJSON *) -cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) { - if ((parent == NULL) || (item == NULL)) { - return NULL; - } - - if (item != parent->child) { - /* not the first element */ - item->prev->next = item->next; - } - if (item->next != NULL) { - /* not the last element */ - item->next->prev = item->prev; - } - - if (item == parent->child) { - /* first element */ - parent->child = item->next; - } else if (item->next == NULL) { - /* last element */ - parent->child->prev = item->prev; - } - - /* make sure the detached item doesn't point anywhere anymore */ - item->prev = NULL; - item->next = NULL; - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) { - if (which < 0) { - return NULL; - } - - return cJSON_DetachItemViaPointer(array, - get_array_item(array, (size_t)which)); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) { - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON *) -cJSON_DetachItemFromObject(cJSON *object, const char *string) { - cJSON *to_detach = cJSON_GetObjectItem(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(cJSON *) -cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) { - cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); - - return cJSON_DetachItemViaPointer(object, to_detach); -} - -CJSON_PUBLIC(void) -cJSON_DeleteItemFromObject(cJSON *object, const char *string) { - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -CJSON_PUBLIC(void) -cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) { - cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(cJSON_bool) -cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) { - cJSON *after_inserted = NULL; - - if (which < 0) { - return false; - } - - after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) { - return add_item_to_array(array, newitem); - } - - newitem->next = after_inserted; - newitem->prev = after_inserted->prev; - after_inserted->prev = newitem; - if (after_inserted == array->child) { - array->child = newitem; - } else { - newitem->prev->next = newitem; - } - return true; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, - cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { - return false; - } - - if (replacement == item) { - return true; - } - - replacement->next = item->next; - replacement->prev = item->prev; - - if (replacement->next != NULL) { - replacement->next->prev = replacement; - } - if (parent->child == item) { - if (parent->child->prev == parent->child) { - replacement->prev = replacement; - } - parent->child = replacement; - } else { /* - * To find the last item in array quickly, we use prev in array. - * We can't modify the last item's next pointer where this item was - * the parent's child - */ - if (replacement->prev != NULL) { - replacement->prev->next = replacement; - } - if (replacement->next == NULL) { - parent->child->prev = replacement; - } - } - - item->next = NULL; - item->prev = NULL; - cJSON_Delete(item); - - return true; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { - if (which < 0) { - return false; - } - - return cJSON_ReplaceItemViaPointer( - array, get_array_item(array, (size_t)which), newitem); -} - -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, - cJSON *replacement, - cJSON_bool case_sensitive) { - if ((replacement == NULL) || (string == NULL)) { - return false; - } - - /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && - (replacement->string != NULL)) { - cJSON_free(replacement->string); - } - replacement->string = - (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); - replacement->type &= ~cJSON_StringIsConst; - - return cJSON_ReplaceItemViaPointer( - object, get_object_item(object, string, case_sensitive), replacement); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) { - return replace_item_in_object(object, string, newitem, false); -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, - cJSON *newitem) { - return replace_item_in_object(object, string, newitem, true); -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = boolean ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if (num >= INT_MAX) { - item->valueint = INT_MAX; - } else if (num <= (double)INT_MIN) { - item->valueint = INT_MIN; - } else { - item->valueint = (int)num; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_String; - item->valuestring = - (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); - if (!item->valuestring) { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char *)cast_away_const(string); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON *)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) { - item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON *)cast_away_const(child); - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_Raw; - item->valuestring = - (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); - if (!item->valuestring) { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) { - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber(numbers[i]); - if (!n) { - cJSON_Delete(a); - return NULL; - } - if (!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - a->child->prev = n; - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber((double)numbers[i]); - if (!n) { - cJSON_Delete(a); - return NULL; - } - if (!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - a->child->prev = n; - - return a; -} - -CJSON_PUBLIC(cJSON *) -cJSON_CreateDoubleArray(const double *numbers, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (numbers == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateNumber(numbers[i]); - if (!n) { - cJSON_Delete(a); - return NULL; - } - if (!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - a->child->prev = n; - - return a; -} - -CJSON_PUBLIC(cJSON *) -cJSON_CreateStringArray(const char *const *strings, int count) { - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if ((count < 0) || (strings == NULL)) { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) { - n = cJSON_CreateString(strings[i]); - if (!n) { - cJSON_Delete(a); - return NULL; - } - if (!i) { - a->child = n; - } else { - suffix_object(p, n); - } - p = n; - } - a->child->prev = n; - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) { - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) { - newitem->valuestring = - (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); - if (!newitem->valuestring) { - goto fail; - } - } - if (item->string) { - newitem->string = (item->type & cJSON_StringIsConst) - ? item->string - : (char *)cJSON_strdup((unsigned char *)item->string, - &global_hooks); - if (!newitem->string) { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) { - newchild = cJSON_Duplicate( - child, - true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) { - goto fail; - } - if (next != NULL) { - /* If newitem->child already set, then crosswire ->prev and ->next and - * move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } else { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - if (newitem && newitem->child) { - newitem->child->prev = newchild; - } - - return newitem; - -fail: - if (newitem != NULL) { - cJSON_Delete(newitem); - } - - return NULL; -} - -static void skip_oneline_comment(char **input) { - *input += static_strlen("//"); - - for (; (*input)[0] != '\0'; ++(*input)) { - if ((*input)[0] == '\n') { - *input += static_strlen("\n"); - return; - } - } -} - -static void skip_multiline_comment(char **input) { - *input += static_strlen("/*"); - - for (; (*input)[0] != '\0'; ++(*input)) { - if (((*input)[0] == '*') && ((*input)[1] == '/')) { - *input += static_strlen("*/"); - return; - } - } -} - -static void minify_string(char **input, char **output) { - (*output)[0] = (*input)[0]; - *input += static_strlen("\""); - *output += static_strlen("\""); - - for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { - (*output)[0] = (*input)[0]; - - if ((*input)[0] == '\"') { - (*output)[0] = '\"'; - *input += static_strlen("\""); - *output += static_strlen("\""); - return; - } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { - (*output)[1] = (*input)[1]; - *input += static_strlen("\""); - *output += static_strlen("\""); - } - } -} - -CJSON_PUBLIC(void) cJSON_Minify(char *json) { - char *into = json; - - if (json == NULL) { - return; - } - - while (json[0] != '\0') { - switch (json[0]) { - case ' ': - case '\t': - case '\r': - case '\n': - json++; - break; - - case '/': - if (json[1] == '/') { - skip_oneline_comment(&json); - } else if (json[1] == '*') { - skip_multiline_comment(&json); - } else { - json++; - } - break; - - case '\"': - minify_string(&json, (char **)&into); - break; - - default: - into[0] = json[0]; - json++; - into++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) { - if (item == NULL) { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} - -CJSON_PUBLIC(cJSON_bool) -cJSON_Compare(const cJSON *const a, const cJSON *const b, - const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || - cJSON_IsInvalid(a)) { - return false; - } - - /* check if type is valid */ - switch (a->type & 0xFF) { - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - case cJSON_Number: - case cJSON_String: - case cJSON_Raw: - case cJSON_Array: - case cJSON_Object: - break; - - default: - return false; - } - - /* identical objects are equal */ - if (a == b) { - return true; - } - - switch (a->type & 0xFF) { - /* in these cases and equal type is enough */ - case cJSON_False: - case cJSON_True: - case cJSON_NULL: - return true; - - case cJSON_Number: - if (compare_double(a->valuedouble, b->valuedouble)) { - return true; - } - return false; - - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) { - return false; - } - if (strcmp(a->valuestring, b->valuestring) == 0) { - return true; - } - - return false; - - case cJSON_Array: { - cJSON *a_element = a->child; - cJSON *b_element = b->child; - - for (; (a_element != NULL) && (b_element != NULL);) { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) { - return false; - } - - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if (a_element != b_element) { - return false; - } - - return true; - } - - case cJSON_Object: { - cJSON *a_element = NULL; - cJSON *b_element = NULL; - cJSON_ArrayForEach(a_element, a) { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) { - return false; - } - - if (!cJSON_Compare(a_element, b_element, case_sensitive)) { - return false; - } - } - - /* doing this twice, once on a and b to prevent true comparison if a - * subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) { - return false; - } - } - - return true; - } - - default: - return false; - } -} - -CJSON_PUBLIC(void *) cJSON_malloc(size_t size) { - return global_hooks.allocate(size); -} - -CJSON_PUBLIC(void) cJSON_free(void *object) { global_hooks.deallocate(object); } diff --git a/include/ckb-c-stdlib/simulator/cJSON.h b/include/ckb-c-stdlib/simulator/cJSON.h deleted file mode 100644 index c3dd89c..0000000 --- a/include/ckb-c-stdlib/simulator/cJSON.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(__WINDOWS__) && \ - (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif - -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid -issues where we are being called from a project with a different default calling -convention. For windows you have 3 define options: - -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever -dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you -want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you -want to dllimport symbol - -For *nix builds that support visibility attribute, you can define similar -behavior by - -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS - -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way -CJSON_EXPORT_SYMBOLS does - -*/ - -#define CJSON_CDECL __cdecl -#define CJSON_STDCALL __stdcall - -/* export symbols by default, this is necessary for copy pasting the C and - * header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && \ - !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL -#endif -#else /* !__WINDOWS__ */ -#define CJSON_CDECL -#define CJSON_STDCALL - -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && \ - defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - -/* project version */ -#define CJSON_VERSION_MAJOR 1 -#define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 14 - -#include - -/* cJSON Types: */ -#define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON { - /* next/prev allow you to walk array/object chains. Alternatively, use - * GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *next; - struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of - * the items in the array/object. */ - struct cJSON *child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String and type == cJSON_Raw */ - char *valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of - * subitems of an object. */ - char *string; -} cJSON; - -typedef struct cJSON_Hooks { - /* malloc/free are CDECL on Windows regardless of the default calling - * convention of the compiler, so ensure the hooks allow passing those - * functions directly. */ - void *(CJSON_CDECL *malloc_fn)(size_t sz); - void(CJSON_CDECL *free_fn)(void *ptr); -} cJSON_Hooks; - -typedef int cJSON_bool; - -/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse - * them. This is to prevent stack overflows. */ -#ifndef CJSON_NESTING_LIMIT -#define CJSON_NESTING_LIMIT 1000 -#endif - -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char *) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); - -/* Memory Management: the caller is always responsible to free the results from - * all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib - * free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is - * cJSON_PrintPreallocated, where the caller has full responsibility of the - * buffer. */ -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. - */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); -CJSON_PUBLIC(cJSON *) -cJSON_ParseWithLength(const char *value, size_t buffer_length); -/* ParseWithOpts allows you to require (and check) that the JSON is null - * terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then - * return_parse_end will contain a pointer to the error so will match - * cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) -cJSON_ParseWithOpts(const char *value, const char **return_parse_end, - cJSON_bool require_null_terminated); -CJSON_PUBLIC(cJSON *) -cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, - const char **return_parse_end, - cJSON_bool require_null_terminated); - -/* Render a cJSON entity to text for transfer/storage. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. */ -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess - * at the final size. guessing well reduces reallocation. fmt=0 gives - * unformatted, =1 gives formatted */ -CJSON_PUBLIC(char *) -cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with - * given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will - * use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, - const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "index" from array "array". Returns NULL if - * unsuccessful. */ -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) -cJSON_GetObjectItem(const cJSON *const object, const char *const string); -CJSON_PUBLIC(cJSON *) -cJSON_GetObjectItemCaseSensitive(const cJSON *const object, - const char *const string); -CJSON_PUBLIC(cJSON_bool) -cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. - * You'll probably need to look a few chars back to make sense of it. Defined - * when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); - -/* Check item type and return its value */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); -/* raw json */ -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); - -/* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/array that only references it's elements so - * they will not be freed by cJSON_Delete */ -CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); - -/* These utilities create an Array of count items. - * The parameter count cannot be greater than the number of elements in the - * number array, otherwise array access will be out of bounds.*/ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) -cJSON_CreateStringArray(const char *const *strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and - * will definitely survive the cJSON object. WARNING: When this function was - * used, make sure to always check that (item->type & cJSON_StringIsConst) is - * zero before writing to `item->string` */ -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); -/* Append reference to item to the specified array/object. Use this when you - * want to add an existing cJSON to a new cJSON, but don't want to corrupt your - * existing cJSON. */ -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(cJSON_bool) -cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detach items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) -cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(cJSON *) -cJSON_DetachItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(cJSON *) -cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); -CJSON_PUBLIC(void) -cJSON_DeleteItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(void) -cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); - -/* Update array items. */ -CJSON_PUBLIC(cJSON_bool) -cJSON_InsertItemInArray( - cJSON *array, int which, - cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, - cJSON *replacement); -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) -cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, - cJSON *newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new - * memory that will need to be released. With recurse!=0, it will duplicate any - * children connected to the item. - * The item->next and ->prev pointers are always zero on return from Duplicate. - */ -/* Recursively compare two cJSON items for equality. If either a or b is NULL or - * invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or - * case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) -cJSON_Compare(const cJSON *const a, const cJSON *const b, - const cJSON_bool case_sensitive); - -/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from - * strings. The input pointer json cannot point to a read-only address area, - * such as a string constant, - * but should point to a readable and writable adress area. */ -CJSON_PUBLIC(void) cJSON_Minify(char *json); - -/* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON *) -cJSON_AddNullToObject(cJSON *const object, const char *const name); -CJSON_PUBLIC(cJSON *) -cJSON_AddTrueToObject(cJSON *const object, const char *const name); -CJSON_PUBLIC(cJSON *) -cJSON_AddFalseToObject(cJSON *const object, const char *const name); -CJSON_PUBLIC(cJSON *) -cJSON_AddBoolToObject(cJSON *const object, const char *const name, - const cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) -cJSON_AddNumberToObject(cJSON *const object, const char *const name, - const double number); -CJSON_PUBLIC(cJSON *) -cJSON_AddStringToObject(cJSON *const object, const char *const name, - const char *const string); -CJSON_PUBLIC(cJSON *) -cJSON_AddRawToObject(cJSON *const object, const char *const name, - const char *const raw); -CJSON_PUBLIC(cJSON *) -cJSON_AddObjectToObject(cJSON *const object, const char *const name); -CJSON_PUBLIC(cJSON *) -cJSON_AddArrayToObject(cJSON *const object, const char *const name); - -/* When assigning an integer value, it needs to be propagated to valuedouble - * too. */ -#define cJSON_SetIntValue(object, number) \ - ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) \ - ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) -/* Change the valuestring of a cJSON_String object, only takes effect when type - * of object is cJSON_String */ -CJSON_PUBLIC(char *) -cJSON_SetValuestring(cJSON *object, const char *valuestring); - -/* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) \ - for (element = (array != NULL) ? (array)->child : NULL; element != NULL; \ - element = element->next) - -/* malloc/free objects using the malloc/free functions that have been set with - * cJSON_InitHooks */ -CJSON_PUBLIC(void *) cJSON_malloc(size_t size); -CJSON_PUBLIC(void) cJSON_free(void *object); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/ckb-c-stdlib/simulator/ckb_syscall_sim.c b/include/ckb-c-stdlib/simulator/ckb_syscall_sim.c deleted file mode 100644 index c0909b9..0000000 --- a/include/ckb-c-stdlib/simulator/ckb_syscall_sim.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -static inline long __internal_syscall(long n, long _a0, long _a1, long _a2, - long _a3, long _a4, long _a5) { - return 0; -} - -#define syscall(n, a, b, c, d, e, f) \ - __internal_syscall(n, (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), \ - (long)(f)) - -int ckb_exit(int8_t code) { return 0; } - -int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset) { return 0; } - -int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset) { return 0; } - -int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -int ckb_load_script(void* addr, uint64_t* len, size_t offset) { return 0; } - -int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - return 0; -} - -int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - return 0; -} - -int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - return 0; -} - -int ckb_load_cell_code(void* addr, size_t memory_size, size_t content_offset, - size_t content_size, size_t index, size_t source) { - return 0; -} - -int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -int ckb_debug(const char* s) { return 0; } - -/* load the actual witness for the current type verify group. - use this instead of ckb_load_witness if type contract needs args to verify - input/output. - */ -int load_actual_type_witness(uint8_t* buf, uint64_t* len, size_t index, - size_t* type_source) { - return 0; -} - -int ckb_look_for_dep_with_hash(const uint8_t* data_hash, size_t* index) { - return 0; -} - -int ckb_calculate_inputs_len() { return 0; } diff --git a/include/ckb-c-stdlib/simulator/ckb_syscall_sim.h b/include/ckb-c-stdlib/simulator/ckb_syscall_sim.h deleted file mode 100644 index 80bf0ea..0000000 --- a/include/ckb-c-stdlib/simulator/ckb_syscall_sim.h +++ /dev/null @@ -1,144 +0,0 @@ -// note, this macro must be same as in ckb_syscall.h -#ifndef CKB_C_STDLIB_CKB_SYSCALLS_H_ -#define CKB_C_STDLIB_CKB_SYSCALLS_H_ -#include -#include -#include -#include - -static inline long __internal_syscall(long n, long _a0, long _a1, long _a2, - long _a3, long _a4, long _a5) { - return 0; -} - -#define syscall(n, a, b, c, d, e, f) \ - __internal_syscall(n, (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), \ - (long)(f)) - -int ckb_exit(int8_t code); - -int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset) { - assert(offset == 0); - uint8_t* p = (uint8_t*)addr; - for (int i = 0; i < 32; i++) { - p[i] = 0; - } - *len = 32; - return 0; -} - -int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset); - -int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - mol_builder_t b; - mol_seg_res_t res; - RsaInfo info; - info.algorithm_id = CKB_VERIFY_RSA; - info.key_size = 1024; - uint8_t* ptr = (uint8_t*)&info; - - if (index > 1) { - return 1; // CKB_INDEX_OUT_OF_BOUND; - } - - MolBuilder_Bytes_init(&b); - for (int i = 0; i < sizeof(info); i++) { - MolBuilder_Bytes_push(&b, ptr[i]); - } - - res = MolBuilder_Bytes_build(b); - assert(res.errno == 0); - assert(MolReader_Bytes_verify(&res.seg, false) == 0); - assert(*len > res.seg.size); - - mol_builder_t w; - MolBuilder_WitnessArgs_init(&w); - MolBuilder_WitnessArgs_set_lock(&w, res.seg.ptr, res.seg.size); - mol_seg_res_t res2 = MolBuilder_WitnessArgs_build(w); - assert(res2.errno == 0); - - memcpy(addr, res2.seg.ptr, res2.seg.size); - *len = res2.seg.size; - return 0; -} - -mol_seg_t build_args_bytes() { - // public key, size: 4+128 = 132 bytes - const int PUBLIC_KEY_SIZE = 132; - uint8_t public_key[132] = {1, 0, 1, 0, 0x56, 0x78}; - - mol_builder_t b; - mol_seg_res_t res; - MolBuilder_Bytes_init(&b); - for (int i = 0; i < PUBLIC_KEY_SIZE; i++) { - MolBuilder_Bytes_push(&b, public_key[i]); - } - res = MolBuilder_Bytes_build(b); - return res.seg; -} - -int ckb_load_script(void* addr, uint64_t* len, size_t offset) { - mol_builder_t b; - mol_seg_res_t res; - - assert(offset == 0); - - MolBuilder_Script_init(&b); - uint8_t code_hash[32] = {0}; - uint8_t hash_type = 0; - - MolBuilder_Script_set_code_hash(&b, code_hash, 32); - MolBuilder_Script_set_hash_type(&b, hash_type); - mol_seg_t bytes = build_args_bytes(); - MolBuilder_Script_set_args(&b, bytes.ptr, bytes.size); - - res = MolBuilder_Script_build(b); - assert(res.errno == 0); - - if (*len < res.seg.size) { - return -1; - } - memcpy(addr, res.seg.ptr, res.seg.size); - *len = res.seg.size; - return 0; -} - -int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -int ckb_load_cell_code(void* addr, size_t memory_size, size_t content_offset, - size_t content_size, size_t index, size_t source); - -int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_debug(const char* s); - -/* load the actual witness for the current type verify group. - use this instead of ckb_load_witness if type contract needs args to verify - input/output. - */ -int load_actual_type_witness(uint8_t* buf, uint64_t* len, size_t index, - size_t* type_source); - -int ckb_look_for_dep_with_hash(const uint8_t* data_hash, size_t* index); - -int ckb_calculate_inputs_len() { return 0; } - -#endif diff --git a/include/ckb-c-stdlib/simulator/ckb_syscall_simulator.c b/include/ckb-c-stdlib/simulator/ckb_syscall_simulator.c deleted file mode 100644 index b4c3114..0000000 --- a/include/ckb-c-stdlib/simulator/ckb_syscall_simulator.c +++ /dev/null @@ -1,743 +0,0 @@ - -// make assert working under release -#undef NDEBUG -//#define CKB_SIMULATOR_VERBOSE - -#include "ckb_syscall_simulator.h" - -#include -#include -#include -#include - -#include "blake2b_decl_only.h" -#include "blockchain-api2.h" -#include "cJSON.h" -#include "molecule_decl_only.h" - -#define FAIL(msg) \ - do { \ - assert(false); \ - printf("Failed at %s:%d: %s\n", __FILE__, __LINE__, (msg)); \ - } while (0) - -#define MAX_GRROUP_SIZE 1024 -#define HASH_SIZE 32 -#define BLAKE160_SIZE 20 -#define SCRIPT_SIZE 32768 - -static cJSON* s_json = NULL; -static cJSON* s_tx_json = NULL; -static uint8_t s_tx_hash[HASH_SIZE] = {0}; -// true: lock script -// false: type script -static bool s_is_lock_script = true; -// index of lock script or type script -static uint32_t s_script_index = 0; - -static uint32_t s_in_group_index[MAX_GRROUP_SIZE]; -static uint32_t s_in_group_size = 0; - -#define MAX_HASH_ITEM_SIZE 1024 -typedef struct data_hash_item_t { - uint8_t hash[HASH_SIZE]; - uint64_t len; - uint8_t* data; -} data_hash_item_t; -data_hash_item_t s_data_hash[MAX_HASH_ITEM_SIZE] = {0}; -size_t s_data_hash_len = 0; - -// ----------------------- -bool is_in_group(uint32_t index); -int init_json_data_source(const char* file_name); -int load_script(void* addr, uint64_t* len, size_t offset, bool is_lock, - uint32_t script_index, bool from_cell_deps); - -cJSON* get_item_at(cJSON* j, size_t index) { - if (j == NULL) { - FAIL("It can't be NULL"); - return NULL; - } - cJSON* elm = j->child; - size_t target = 0; - while (elm != NULL) { - if (target == index) return elm; - elm = elm->next; - target++; - } - return NULL; -} - -unsigned char decode_hex(char s) { - if (s >= '0' && s <= '9') { - return s - '0'; - } else if (s >= 'a' && s <= 'f') { - return s - 'a' + 10; - } else if (s >= 'A' && s <= 'F') { - return s - 'A' + 10; - } else { - FAIL("Invalid hex character"); - } - return 0; -} - -unsigned char compose_byte(const char* s) { - return decode_hex(s[0]) << 4 | decode_hex(s[1]); -} - -void load_data(const char* str, unsigned char* addr, uint64_t* len, - size_t offset) { - size_t str_len = strlen(str); - if (str_len < 2 || str[0] != '0' || str[1] != 'x') { - FAIL("The data part must be started with 0x"); - return; - } - ASSERT((str_len % 2) == 0); - size_t data_len = (str_len - 2) / 2; - ASSERT(offset <= data_len); - - size_t start = 2 + offset * 2; - for (size_t i = 0; i < *len; i++) { - if ((offset + i) >= data_len) { - *len = i; - break; - } - addr[i] = compose_byte(&str[start + i * 2]); - } -} - -size_t calculate_size(const char* str) { - assert(strlen(str) % 2 == 0); - return (strlen(str) - 2) / 2; -} - -void load_offset(uint8_t* source_buff, uint64_t source_size, void* addr, - uint64_t* len, size_t offset) { - assert(source_size > offset); - assert(*len > 0); - - uint64_t size = MIN(source_size - offset, *len); - memcpy(addr, source_buff + offset, size); - *len = size; -} - -void blake2b_hash(void* ptr, size_t size, uint8_t* hash) { - blake2b_state ctx; - ckb_blake2b_init(&ctx, HASH_SIZE); - blake2b_update(&ctx, ptr, size); - blake2b_final(&ctx, hash, HASH_SIZE); -} - -void print_hex(uint8_t* ptr, size_t size) { - printf("0x"); - for (size_t i = 0; i < size; i++) { - printf("%02x", ptr[i]); - } - printf("\n"); -} - -// todo: free -mol_seg_t build_Bytes(uint8_t* ptr, uint32_t len) { - mol_builder_t b; - mol_seg_res_t res; - MolBuilder_Bytes_init(&b); - for (uint32_t i = 0; i < len; i++) { - MolBuilder_Bytes_push(&b, ptr[i]); - } - res = MolBuilder_Bytes_build(b); - assert(res.errno == 0); - return res.seg; -} - -mol_seg_t build_script(uint8_t* code_hash, uint8_t hash_type, uint8_t* args, - uint32_t args_len) { - mol_builder_t b; - mol_seg_res_t res; - - MolBuilder_Script_init(&b); - MolBuilder_Script_set_code_hash(&b, code_hash, 32); - MolBuilder_Script_set_hash_type(&b, hash_type); - mol_seg_t bytes = build_Bytes(args, args_len); - MolBuilder_Script_set_args(&b, bytes.ptr, bytes.size); - - res = MolBuilder_Script_build(b); - assert(res.errno == 0); - return res.seg; -} - -int ckb_exit(int8_t code) { - printf("ckb_exit\n"); - exit(0); - return CKB_SUCCESS; -} - -int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset) { - load_offset(s_tx_hash, HASH_SIZE, addr, len, offset); - return CKB_SUCCESS; -} - -int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset) { - assert(*len >= HASH_SIZE); - - uint8_t script[SCRIPT_SIZE]; - uint64_t script_size = 0; - int ret = ckb_load_script(script, &script_size, 0); - assert(ret == CKB_SUCCESS); - - uint8_t hash[HASH_SIZE]; - blake2b_hash(script, script_size, hash); - - load_offset(hash, HASH_SIZE, addr, len, offset); - return CKB_SUCCESS; -} - -// TODO: currently it's not used, will be implemented -int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -// TODO: currently it's not used, will be implemented -int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -// TODO: currently it's not used, will be implemented -int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - return 0; -} - -int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - cJSON* tx = cJSON_GetObjectItem(s_tx_json, "tx"); - cJSON* witness = cJSON_GetObjectItem(tx, "witnesses"); - size_t new_index = index; - if (source == CKB_SOURCE_GROUP_INPUT) { - if (index >= s_in_group_size) return CKB_INDEX_OUT_OF_BOUND; - new_index = s_in_group_index[index]; - } else { - assert(source == CKB_SOURCE_INPUT); - } - - cJSON* witness_item = get_item_at(witness, new_index); - if (witness_item == NULL) { - return CKB_INDEX_OUT_OF_BOUND; - } - load_data(witness_item->valuestring, addr, len, offset); - return CKB_SUCCESS; -} - -bool compare_script(cJSON* a, cJSON* b) { - assert(a); - assert(b); - cJSON* a_args = cJSON_GetObjectItem(a, "args"); - cJSON* a_code_hash = cJSON_GetObjectItem(a, "code_hash"); - cJSON* a_hash_type = cJSON_GetObjectItem(a, "hash_type"); - - cJSON* b_args = cJSON_GetObjectItem(b, "args"); - cJSON* b_code_hash = cJSON_GetObjectItem(b, "code_hash"); - cJSON* b_hash_type = cJSON_GetObjectItem(b, "hash_type"); - - return (strcmp(a_args->valuestring, b_args->valuestring) == 0) && - (strcmp(a_code_hash->valuestring, b_code_hash->valuestring) == 0) && - (strcmp(a_hash_type->valuestring, b_hash_type->valuestring) == 0); -} - -void prepare_group(bool is_lock_script, uint32_t script_index) { - cJSON* mock_info = cJSON_GetObjectItem(s_tx_json, "mock_info"); - assert(mock_info); - cJSON* inputs = cJSON_GetObjectItem(mock_info, "inputs"); - assert(inputs); - - cJSON* input = get_item_at(inputs, script_index); - assert(input); - cJSON* output = cJSON_GetObjectItem(input, "output"); - assert(output); - const char* lock_or_type = is_lock_script ? "lock" : "type"; - cJSON* target = cJSON_GetObjectItem(output, lock_or_type); - - uint32_t index = 0; - cJSON_ArrayForEach(input, inputs) { - output = cJSON_GetObjectItem(input, "output"); - cJSON* temp = cJSON_GetObjectItem(output, lock_or_type); - if (compare_script(temp, target)) { - s_in_group_index[s_in_group_size] = index; - s_in_group_size++; - } - index++; - } -} - -bool is_in_group(uint32_t index) { - for (uint32_t i = 0; i < s_in_group_size; i++) { - if (index == s_in_group_index[i]) return true; - } - return false; -} - -void prepare_hash(void) { - cJSON* mock_info = cJSON_GetObjectItem(s_tx_json, "mock_info"); - assert(mock_info); - cJSON* cell_deps = cJSON_GetObjectItem(mock_info, "cell_deps"); - assert(cell_deps); - size_t index = 0; - for (cJSON* it = cell_deps->child; it != NULL; it = it->next) { - assert(index < MAX_HASH_ITEM_SIZE); - data_hash_item_t* item = &s_data_hash[index]; - - cJSON* data = cJSON_GetObjectItem(it, "data"); - item->len = calculate_size(data->valuestring); - item->data = malloc(item->len); - load_data(data->valuestring, item->data, &item->len, 0); - blake2b_hash(item->data, item->len, item->hash); -#ifdef CKB_SIMULATOR_VERBOSE - printf("Cell data hash at index %zu:", index); - print_hex(item->hash, HASH_SIZE); -#endif - index++; - } - s_data_hash_len = index; - - uint8_t script[SCRIPT_SIZE]; - uint64_t script_size = SCRIPT_SIZE; - uint32_t idx = 0; - uint8_t hash[HASH_SIZE] = {0}; - while (true) { - int ret = load_script(script, &script_size, 0, false, idx, true); - if (ret == CKB_INDEX_OUT_OF_BOUND) break; - if (ret == CKB_ITEM_MISSING) { - // it's null - } else { - assert(ret == CKB_SUCCESS); - blake2b_hash(script, script_size, hash); -#ifdef CKB_SIMULATOR_VERBOSE - printf("script hash at index %d: ", idx); - print_hex(hash, HASH_SIZE); -#endif - } - idx++; - } -} - -int load_script(void* addr, uint64_t* len, size_t offset, bool is_lock, - uint32_t script_index, bool from_cell_deps) { - cJSON* mock_info = cJSON_GetObjectItem(s_tx_json, "mock_info"); - const char* field = from_cell_deps ? "cell_deps" : "inputs"; - cJSON* inputs = cJSON_GetObjectItem(mock_info, field); - cJSON* input_at_index = get_item_at(inputs, script_index); - if (input_at_index == NULL) return CKB_INDEX_OUT_OF_BOUND; - - cJSON* output = cJSON_GetObjectItem(input_at_index, "output"); - const char* lock_or_type = is_lock ? "lock" : "type"; - cJSON* lock_or_type_json = cJSON_GetObjectItem(output, lock_or_type); - assert(lock_or_type_json != NULL); - if (cJSON_IsNull(lock_or_type_json)) { - return CKB_ITEM_MISSING; - } - cJSON* args_json = cJSON_GetObjectItem(lock_or_type_json, "args"); - cJSON* code_hash_json = cJSON_GetObjectItem(lock_or_type_json, "code_hash"); - cJSON* hash_type_json = cJSON_GetObjectItem(lock_or_type_json, "hash_type"); - // to be confirmed - int hash_type = 0; - if (strcmp(hash_type_json->valuestring, "type") == 0) { - hash_type = 1; - } - - uint8_t code_hash[HASH_SIZE] = {0}; - uint64_t code_hash_len = HASH_SIZE; - load_data(code_hash_json->valuestring, code_hash, &code_hash_len, 0); - - uint64_t args_len = calculate_size(args_json->valuestring); - uint8_t args[args_len]; - load_data(args_json->valuestring, args, &args_len, 0); - mol_seg_t script = build_script(code_hash, hash_type, args, args_len); - - load_offset(script.ptr, script.size, addr, len, offset); - return CKB_SUCCESS; -} - -int ckb_load_script(void* addr, uint64_t* len, size_t offset) { - return load_script(addr, len, offset, s_is_lock_script, s_script_index, - false); -} - -int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - if (source == CKB_SOURCE_CELL_DEP) { - if (field == CKB_CELL_FIELD_DATA_HASH) { - if (index >= s_data_hash_len) { - return CKB_INDEX_OUT_OF_BOUND; - } - load_offset(s_data_hash[index].hash, HASH_SIZE, addr, len, offset); - } else { - assert(false); - } - } else if (source == CKB_SOURCE_INPUT) { - if (field == CKB_CELL_FIELD_LOCK_HASH) { - // make sure it's from 0, otherwise, it consumes a lot of cpu. (computer - // hash size more than once) - assert(offset == 0); - assert(*len >= HASH_SIZE); - - uint8_t lock_script[SCRIPT_SIZE]; - uint64_t lock_script_len = SCRIPT_SIZE; - int ret = load_script(lock_script, &lock_script_len, 0, s_is_lock_script, - index, false); - if (ret != CKB_SUCCESS) return ret; - - uint8_t hash[HASH_SIZE]; - blake2b_hash(lock_script, lock_script_len, hash); - - load_offset(hash, HASH_SIZE, addr, len, 0); - } else { - // TODO: currently it's not used, will be implemented - assert(false); - } - } else { - assert(false); - } - - return 0; -} - -// TODO: currently it's not used, will be implemented -int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - return 0; -} - -int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - if (field == CKB_INPUT_FIELD_SINCE) { - cJSON* tx = cJSON_GetObjectItem(s_tx_json, "tx"); - cJSON* inputs = cJSON_GetObjectItem(tx, "inputs"); - assert(inputs != NULL); - size_t new_index = index; - if (source == CKB_SOURCE_GROUP_INPUT) { - if (index >= s_in_group_size) return CKB_INDEX_OUT_OF_BOUND; - new_index = s_in_group_index[index]; - } else { - assert(source == CKB_SOURCE_INPUT); - } - - cJSON* input = get_item_at(inputs, new_index); - if (input == NULL) { - return CKB_INDEX_OUT_OF_BOUND; - } else { - cJSON* since = cJSON_GetObjectItem(input, "since"); - load_data(since->valuestring, addr, len, offset); - } - } else { - assert(false); - } - return CKB_SUCCESS; -} - -// TODO: currently it's not used, will be implemented -int ckb_load_cell_code(void* addr, size_t memory_size, size_t content_offset, - size_t content_size, size_t index, size_t source) { - return 0; -} - -int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source) { - if (source == CKB_SOURCE_CELL_DEP) { - if (index >= s_data_hash_len) { - return CKB_INDEX_OUT_OF_BOUND; - } - load_offset(s_data_hash[index].data, s_data_hash[index].len, addr, len, - offset); - } else if (source == CKB_SOURCE_GROUP_INPUT) { - cJSON* mock_info = cJSON_GetObjectItem(s_tx_json, "mock_info"); - cJSON* inputs = cJSON_GetObjectItem(mock_info, "inputs"); - cJSON* input_at_index = get_item_at(inputs, index); - if (input_at_index == NULL) return CKB_INDEX_OUT_OF_BOUND; - cJSON* data = cJSON_GetObjectItem(input_at_index, "data"); - load_data(data->valuestring, addr, len, offset); - } else if (source == CKB_SOURCE_GROUP_OUTPUT) { - cJSON* tx = cJSON_GetObjectItem(s_tx_json, "tx"); - cJSON* outputs_data = cJSON_GetObjectItem(tx, "outputs_data"); - cJSON* output_at_index = get_item_at(outputs_data, index); - if (output_at_index == NULL) return CKB_INDEX_OUT_OF_BOUND; - load_data(output_at_index->valuestring, addr, len, offset); - } else { - assert(false); - } - return 0; -} - -int ckb_debug(const char* s) { return 0; } - -// TODO: currently it's not used, will be implemented -int load_actual_type_witness(uint8_t* buf, uint64_t* len, size_t index, - size_t* type_source) { - return 0; -} - -int ckb_look_for_dep_with_hash(const uint8_t* data_hash, size_t* index) { - return ckb_look_for_dep_with_hash2(data_hash, 0, index); -} - -int ckb_checked_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field) { - uint64_t old_len = *len; - int ret = ckb_load_cell_by_field(addr, len, offset, index, source, field); - if (ret == CKB_SUCCESS && (*len) > old_len) { - ret = CKB_LENGTH_NOT_ENOUGH; - } - return ret; -} - -int ckb_calculate_inputs_len() { - uint64_t len = 0; - /* lower bound, at least tx has one input */ - int lo = 0; - /* higher bound */ - int hi = 4; - int ret; - /* try to load input until failing to increase lo and hi */ - while (1) { - ret = ckb_load_input_by_field(NULL, &len, 0, hi, CKB_SOURCE_INPUT, - CKB_INPUT_FIELD_SINCE); - if (ret == CKB_SUCCESS) { - lo = hi; - hi *= 2; - } else { - break; - } - } - - /* now we get our lower bound and higher bound, - count number of inputs by binary search */ - int i; - while (lo + 1 != hi) { - i = (lo + hi) / 2; - ret = ckb_load_input_by_field(NULL, &len, 0, i, CKB_SOURCE_INPUT, - CKB_INPUT_FIELD_SINCE); - if (ret == CKB_SUCCESS) { - lo = i; - } else { - hi = i; - } - } - /* now lo is last input index and hi is length of inputs */ - return hi; -} - -int ckb_look_for_dep_with_hash2(const uint8_t* code_hash, uint8_t hash_type, - size_t* index) { - size_t current = 0; - size_t field = - (hash_type == 1) ? CKB_CELL_FIELD_TYPE_HASH : CKB_CELL_FIELD_DATA_HASH; - while (current < SIZE_MAX) { - uint64_t len = 32; - uint8_t hash[32]; - - int ret = ckb_load_cell_by_field(hash, &len, 0, current, - CKB_SOURCE_CELL_DEP, field); - switch (ret) { - case CKB_ITEM_MISSING: - break; - case CKB_SUCCESS: - if (memcmp(code_hash, hash, 32) == 0) { - /* Found a match */ - *index = current; - return CKB_SUCCESS; - } - break; - default: - return CKB_INDEX_OUT_OF_BOUND; - } - current++; - } - return CKB_INDEX_OUT_OF_BOUND; -} - -#define READALL_CHUNK 262144 -#define READALL_OK 0 /* Success */ -#define READALL_INVALID -1 /* Invalid parameters */ -#define READALL_ERROR -2 /* Stream error */ -#define READALL_TOOMUCH -3 /* Too much input */ -#define READALL_NOMEM -4 /* Out of memory */ - -int readall(FILE* in, char** dataptr, size_t* sizeptr) { - char *data = NULL, *temp = NULL; - size_t size = 0; - size_t used = 0; - size_t n = 0; - - /* None of the parameters can be NULL. */ - if (in == NULL || dataptr == NULL || sizeptr == NULL) return READALL_INVALID; - - /* A read error already occurred? */ - if (ferror(in)) return READALL_ERROR; - - while (1) { - if (used + READALL_CHUNK + 1 > size) { - size = used + READALL_CHUNK + 1; - - if (size <= used) { - free(data); - return READALL_TOOMUCH; - } - - temp = realloc(data, size); - if (temp == NULL) { - free(data); - return READALL_NOMEM; - } - data = temp; - } - - n = fread(data + used, 1, READALL_CHUNK, in); - if (n == 0) break; - - used += n; - } - - if (ferror(in)) { - free(data); - return READALL_ERROR; - } - - temp = realloc(data, used + 1); - if (temp == NULL) { - free(data); - return READALL_NOMEM; - } - data = temp; - data[used] = '\0'; - - *dataptr = data; - *sizeptr = used; - - return READALL_OK; -} - -int init_json_data_source(const char* file_name) { - FILE* input = NULL; - if (file_name == NULL) { - input = stdin; - } else { - input = fopen(file_name, "rb"); - } - char* json_ptr = NULL; - size_t json_size = 0; - int ret = readall(input, &json_ptr, &json_size); - if (ret != 0) { - return ret; - } - s_json = cJSON_ParseWithLength(json_ptr, json_size); - if (s_json == NULL) { - char msg[128] = {0}; - sprintf(msg, "Failed to parse json file: %s", file_name); - FAIL(msg); - return -1; - } - fclose(input); - free(json_ptr); - - // --------- - - cJSON* tx_hash = cJSON_GetObjectItem(s_json, "main"); - cJSON* fn = cJSON_GetObjectItem(s_json, tx_hash->valuestring); - input = fopen(fn->valuestring, "rb"); - ret = readall(input, &json_ptr, &json_size); - assert(ret == READALL_OK); - s_tx_json = cJSON_ParseWithLength(json_ptr, json_size); - if (s_tx_json == NULL) { - char msg[128] = {0}; - sprintf(msg, "Failed to parse json file: %s", fn->valuestring); - FAIL(msg); - return -1; - } - uint64_t tx_hash_len = HASH_SIZE; - load_data(tx_hash->valuestring, s_tx_hash, &tx_hash_len, 0); - assert(tx_hash_len == HASH_SIZE); - - cJSON* is_lock_script = cJSON_GetObjectItem(s_json, "is_lock_script"); - assert(is_lock_script != NULL); - assert(cJSON_IsBool(is_lock_script)); - s_is_lock_script = cJSON_IsTrue(is_lock_script); - - cJSON* script_index = cJSON_GetObjectItem(s_json, "script_index"); - assert(script_index != NULL); - s_script_index = script_index->valueint; - - prepare_group(s_is_lock_script, s_script_index); - fclose(input); - free(json_ptr); - - return 0; -} - -void test_script(void) { - unsigned char script[SCRIPT_SIZE]; - uint64_t len = SCRIPT_SIZE; - int ret = ckb_load_script(script, &len, 0); - assert(ret == CKB_SUCCESS); - assert(len < SCRIPT_SIZE); - - mol_seg_t script_seg; - script_seg.ptr = (uint8_t*)script; - script_seg.size = len; - - assert(MolReader_Script_verify(&script_seg, false) == MOL_OK); - - mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); - mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); - assert(args_bytes_seg.size == BLAKE160_SIZE); - - assert(args_bytes_seg.ptr[0] == 0x27); - assert(args_bytes_seg.ptr[1] == 0xf5); - assert(args_bytes_seg.ptr[18] == 0x9e); - assert(args_bytes_seg.ptr[19] == 0xc9); -} - -// the test data is from: -// npx ckb-transaction-dumper -x -// 0xa98c212cf055cedbbb665d475c0561b56c68ea735c8aa830c493264effaf18bd - -int unit_test(int argc, const char* argv[]) { - unsigned char witness[1024] = {0}; - uint64_t witness_len = 1024; - ckb_load_witness(witness, &witness_len, 0, 0, 0); - assert(witness_len == 85); - assert(witness[0] == 0x55); - assert(witness[1] == 0x00); - assert(witness[83] == 0xe7); - assert(witness[84] == 0x01); - test_script(); - return 0; -} - -// this is the entry function of contract. -extern int simulator_main(void); - -int main(int argc, const char* argv[]) { - const char* file_name = NULL; - if (argc == 2 && argv[1] != NULL) file_name = argv[1]; - if (file_name == NULL) { - printf("Running with stdin ...\n"); - } else { - printf("Running with file: %s\n", file_name); - } - int ret = init_json_data_source(file_name); - assert(ret == 0); - prepare_hash(); - - if (false) { - ret = unit_test(argc, argv); - } else { - ret = simulator_main(); - } - - if (ret == 0) { - printf("succeeded!\n"); - } else { - printf("failed, error code: %d\n", ret); - } - return ret; -} diff --git a/include/ckb-c-stdlib/simulator/ckb_syscall_simulator.h b/include/ckb-c-stdlib/simulator/ckb_syscall_simulator.h deleted file mode 100644 index bde0fed..0000000 --- a/include/ckb-c-stdlib/simulator/ckb_syscall_simulator.h +++ /dev/null @@ -1,59 +0,0 @@ -// note, this macro must be same as in ckb_syscall.h -#ifndef CKB_C_STDLIB_CKB_SYSCALLS_H_ -#define CKB_C_STDLIB_CKB_SYSCALLS_H_ -#include -#include - -#include "ckb_consts.h" - -int ckb_exit(int8_t code); - -int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset); - -int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset); - -int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_load_script(void* addr, uint64_t* len, size_t offset); - -int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -int ckb_load_cell_code(void* addr, size_t memory_size, size_t content_offset, - size_t content_size, size_t index, size_t source); - -int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index, - size_t source); - -int ckb_debug(const char* s); - -int load_actual_type_witness(uint8_t* buf, uint64_t* len, size_t index, - size_t* type_source); - -int ckb_look_for_dep_with_hash(const uint8_t* data_hash, size_t* index); - -int ckb_calculate_inputs_len(); - -int ckb_look_for_dep_with_hash2(const uint8_t* code_hash, uint8_t hash_type, - size_t* index); - -int ckb_checked_load_cell_by_field(void* addr, uint64_t* len, size_t offset, - size_t index, size_t source, size_t field); - -#endif diff --git a/include/ckb-c-stdlib/simulator/molecule_decl_only.h b/include/ckb-c-stdlib/simulator/molecule_decl_only.h deleted file mode 100644 index 152e89c..0000000 --- a/include/ckb-c-stdlib/simulator/molecule_decl_only.h +++ /dev/null @@ -1,757 +0,0 @@ -#ifndef CKB_MISCELLANEOUS_SCRIPTS_SIMULATOR_MOLECULE_DECL_ONLY_H_ -#define CKB_MISCELLANEOUS_SCRIPTS_SIMULATOR_MOLECULE_DECL_ONLY_H_ - -#include -#include - -#define is_le() (*(unsigned char *)&(uint16_t){1}) -typedef uint32_t mol_num_t; // Item Id -typedef uint8_t mol_errno; // Error Number -#define MolNum UINT32_C -#define MOL_NUM_T_SIZE 4 - -// Bytes segment. -typedef struct { - uint8_t *ptr; // Pointer - mol_num_t size; // Full size -} mol_seg_t; - -// Unpacked Union -typedef struct { - mol_num_t item_id; // Item Id - mol_seg_t seg; // Segment -} mol_union_t; - -// Result for returning segment. -typedef struct { - mol_errno errno; // Error Number - mol_seg_t seg; // Segment -} mol_seg_res_t; - -/* Error Numbers */ - -#define MOL_OK 0x00 -#define MOL_ERR 0xff - -#define MOL_ERR_TOTAL_SIZE 0x01 -#define MOL_ERR_HEADER 0x02 -#define MOL_ERR_OFFSET 0x03 -#define MOL_ERR_UNKNOWN_ITEM 0x04 -#define MOL_ERR_INDEX_OUT_OF_BOUNDS 0x05 -#define MOL_ERR_FIELD_COUNT 0x06 -#define MOL_ERR_DATA 0x07 - -/* Utilities. */ - -mol_num_t mol_unpack_number(const uint8_t *src); - -/* - * Core functions. - */ - -/* Verify Functions. */ - -// Verify Array / Struct. -mol_errno mol_verify_fixed_size(const mol_seg_t *input, mol_num_t total_size); - -// Verify FixVec. -mol_errno mol_fixvec_verify(const mol_seg_t *input, mol_num_t item_size); -bool mol_option_is_none(const mol_seg_t *input); -mol_union_t mol_union_unpack(const mol_seg_t *input); -mol_num_t mol_fixvec_length(const mol_seg_t *input); -mol_num_t mol_dynvec_length(const mol_seg_t *input); -mol_num_t mol_table_actual_field_count(const mol_seg_t *input); -bool mol_table_has_extra_fields(const mol_seg_t *input, mol_num_t field_count); -mol_seg_t mol_slice_by_offset(const mol_seg_t *input, mol_num_t offset, - mol_num_t size); -mol_seg_res_t mol_fixvec_slice_by_index(const mol_seg_t *input, - mol_num_t item_size, - mol_num_t item_index); -mol_seg_res_t mol_dynvec_slice_by_index(const mol_seg_t *input, - mol_num_t item_index); -mol_seg_t mol_table_slice_by_index(const mol_seg_t *input, - mol_num_t field_index); - -mol_seg_t mol_fixvec_slice_raw_bytes(const mol_seg_t *input); - -// molecule-builder.h -typedef struct { - uint8_t *data_ptr; // Data Pointer - mol_num_t data_used; // Data Used - mol_num_t data_cap; // Data Capacity - - mol_num_t *number_ptr; // A Pointer of Numbers - mol_num_t number_used; // Numbers used - mol_num_t number_cap; // Numbers Capacity -} mol_builder_t; - -/* Utilities. */ - -void mol_pack_number(uint8_t *dst, mol_num_t *num); -/* - * Core functions. - */ - -void mol_builder_discard(mol_builder_t builder); - -void mol_builder_initialize_fixed_size(mol_builder_t *builder, - mol_num_t fixed_size); - -void mol_union_builder_initialize(mol_builder_t *builder, - mol_num_t data_capacity, mol_num_t item_id, - const uint8_t *default_ptr, - mol_num_t default_len); - -void mol_builder_initialize_with_capacity(mol_builder_t *builder, - mol_num_t data_capacity, - mol_num_t number_capacity); - -void mol_fixvec_builder_initialize(mol_builder_t *builder, - mol_num_t data_capacity); - -void mol_table_builder_initialize(mol_builder_t *builder, - mol_num_t data_capacity, - mol_num_t field_count); - -void mol_option_builder_set(mol_builder_t *builder, const uint8_t *data_ptr, - mol_num_t data_len); - -void mol_union_builder_set_byte(mol_builder_t *builder, mol_num_t item_id, - uint8_t data); - -void mol_union_builder_set(mol_builder_t *builder, mol_num_t item_id, - const uint8_t *data_ptr, mol_num_t data_len); - -void mol_builder_set_byte_by_offset(mol_builder_t *builder, mol_num_t offset, - uint8_t data); - -void mol_builder_set_by_offset(mol_builder_t *builder, mol_num_t offset, - const uint8_t *data_ptr, mol_num_t length); - -void mol_fixvec_builder_push_byte(mol_builder_t *builder, uint8_t data); - -void mol_fixvec_builder_push(mol_builder_t *builder, const uint8_t *data_ptr, - mol_num_t length); - -void mol_dynvec_builder_push(mol_builder_t *builder, const uint8_t *data_ptr, - mol_num_t data_len); -void mol_table_builder_add_byte(mol_builder_t *builder, mol_num_t field_index, - uint8_t data); - -void mol_table_builder_add(mol_builder_t *builder, mol_num_t field_index, - const uint8_t *data_ptr, mol_num_t data_len); -mol_seg_res_t mol_builder_finalize_simple(mol_builder_t builder); - -mol_seg_res_t mol_fixvec_builder_finalize(mol_builder_t builder); -mol_seg_res_t mol_dynvec_builder_finalize(mol_builder_t builder); - -// blockchain-api.h -#define MolReader_Uint32_verify(s, c) mol_verify_fixed_size(s, 4) -#define MolReader_Uint32_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint32_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint32_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint32_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint64_verify(s, c) mol_verify_fixed_size(s, 8) -#define MolReader_Uint64_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint64_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint64_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint64_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint64_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Uint64_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Uint64_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Uint64_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Uint128_verify(s, c) mol_verify_fixed_size(s, 16) -#define MolReader_Uint128_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint128_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint128_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint128_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint128_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Uint128_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Uint128_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Uint128_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Uint128_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_Uint128_get_nth9(s) mol_slice_by_offset(s, 9, 1) -#define MolReader_Uint128_get_nth10(s) mol_slice_by_offset(s, 10, 1) -#define MolReader_Uint128_get_nth11(s) mol_slice_by_offset(s, 11, 1) -#define MolReader_Uint128_get_nth12(s) mol_slice_by_offset(s, 12, 1) -#define MolReader_Uint128_get_nth13(s) mol_slice_by_offset(s, 13, 1) -#define MolReader_Uint128_get_nth14(s) mol_slice_by_offset(s, 14, 1) -#define MolReader_Uint128_get_nth15(s) mol_slice_by_offset(s, 15, 1) -#define MolReader_Byte32_verify(s, c) mol_verify_fixed_size(s, 32) -#define MolReader_Byte32_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Byte32_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Byte32_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Byte32_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Byte32_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Byte32_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Byte32_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Byte32_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Byte32_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_Byte32_get_nth9(s) mol_slice_by_offset(s, 9, 1) -#define MolReader_Byte32_get_nth10(s) mol_slice_by_offset(s, 10, 1) -#define MolReader_Byte32_get_nth11(s) mol_slice_by_offset(s, 11, 1) -#define MolReader_Byte32_get_nth12(s) mol_slice_by_offset(s, 12, 1) -#define MolReader_Byte32_get_nth13(s) mol_slice_by_offset(s, 13, 1) -#define MolReader_Byte32_get_nth14(s) mol_slice_by_offset(s, 14, 1) -#define MolReader_Byte32_get_nth15(s) mol_slice_by_offset(s, 15, 1) -#define MolReader_Byte32_get_nth16(s) mol_slice_by_offset(s, 16, 1) -#define MolReader_Byte32_get_nth17(s) mol_slice_by_offset(s, 17, 1) -#define MolReader_Byte32_get_nth18(s) mol_slice_by_offset(s, 18, 1) -#define MolReader_Byte32_get_nth19(s) mol_slice_by_offset(s, 19, 1) -#define MolReader_Byte32_get_nth20(s) mol_slice_by_offset(s, 20, 1) -#define MolReader_Byte32_get_nth21(s) mol_slice_by_offset(s, 21, 1) -#define MolReader_Byte32_get_nth22(s) mol_slice_by_offset(s, 22, 1) -#define MolReader_Byte32_get_nth23(s) mol_slice_by_offset(s, 23, 1) -#define MolReader_Byte32_get_nth24(s) mol_slice_by_offset(s, 24, 1) -#define MolReader_Byte32_get_nth25(s) mol_slice_by_offset(s, 25, 1) -#define MolReader_Byte32_get_nth26(s) mol_slice_by_offset(s, 26, 1) -#define MolReader_Byte32_get_nth27(s) mol_slice_by_offset(s, 27, 1) -#define MolReader_Byte32_get_nth28(s) mol_slice_by_offset(s, 28, 1) -#define MolReader_Byte32_get_nth29(s) mol_slice_by_offset(s, 29, 1) -#define MolReader_Byte32_get_nth30(s) mol_slice_by_offset(s, 30, 1) -#define MolReader_Byte32_get_nth31(s) mol_slice_by_offset(s, 31, 1) -#define MolReader_Uint256_verify(s, c) mol_verify_fixed_size(s, 32) -#define MolReader_Uint256_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_Uint256_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_Uint256_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_Uint256_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_Uint256_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_Uint256_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_Uint256_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_Uint256_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_Uint256_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_Uint256_get_nth9(s) mol_slice_by_offset(s, 9, 1) -#define MolReader_Uint256_get_nth10(s) mol_slice_by_offset(s, 10, 1) -#define MolReader_Uint256_get_nth11(s) mol_slice_by_offset(s, 11, 1) -#define MolReader_Uint256_get_nth12(s) mol_slice_by_offset(s, 12, 1) -#define MolReader_Uint256_get_nth13(s) mol_slice_by_offset(s, 13, 1) -#define MolReader_Uint256_get_nth14(s) mol_slice_by_offset(s, 14, 1) -#define MolReader_Uint256_get_nth15(s) mol_slice_by_offset(s, 15, 1) -#define MolReader_Uint256_get_nth16(s) mol_slice_by_offset(s, 16, 1) -#define MolReader_Uint256_get_nth17(s) mol_slice_by_offset(s, 17, 1) -#define MolReader_Uint256_get_nth18(s) mol_slice_by_offset(s, 18, 1) -#define MolReader_Uint256_get_nth19(s) mol_slice_by_offset(s, 19, 1) -#define MolReader_Uint256_get_nth20(s) mol_slice_by_offset(s, 20, 1) -#define MolReader_Uint256_get_nth21(s) mol_slice_by_offset(s, 21, 1) -#define MolReader_Uint256_get_nth22(s) mol_slice_by_offset(s, 22, 1) -#define MolReader_Uint256_get_nth23(s) mol_slice_by_offset(s, 23, 1) -#define MolReader_Uint256_get_nth24(s) mol_slice_by_offset(s, 24, 1) -#define MolReader_Uint256_get_nth25(s) mol_slice_by_offset(s, 25, 1) -#define MolReader_Uint256_get_nth26(s) mol_slice_by_offset(s, 26, 1) -#define MolReader_Uint256_get_nth27(s) mol_slice_by_offset(s, 27, 1) -#define MolReader_Uint256_get_nth28(s) mol_slice_by_offset(s, 28, 1) -#define MolReader_Uint256_get_nth29(s) mol_slice_by_offset(s, 29, 1) -#define MolReader_Uint256_get_nth30(s) mol_slice_by_offset(s, 30, 1) -#define MolReader_Uint256_get_nth31(s) mol_slice_by_offset(s, 31, 1) -#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) -#define MolReader_Bytes_length(s) mol_fixvec_length(s) -#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) -#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) -mol_errno MolReader_BytesOpt_verify(const mol_seg_t *, bool); -#define MolReader_BytesOpt_is_none(s) mol_option_is_none(s) -mol_errno MolReader_BytesVec_verify(const mol_seg_t *, bool); -#define MolReader_BytesVec_length(s) mol_dynvec_length(s) -#define MolReader_BytesVec_get(s, i) mol_dynvec_slice_by_index(s, i) -#define MolReader_Byte32Vec_verify(s, c) mol_fixvec_verify(s, 32) -#define MolReader_Byte32Vec_length(s) mol_fixvec_length(s) -#define MolReader_Byte32Vec_get(s, i) mol_fixvec_slice_by_index(s, 32, i) -mol_errno MolReader_ScriptOpt_verify(const mol_seg_t *, bool); -#define MolReader_ScriptOpt_is_none(s) mol_option_is_none(s) -#define MolReader_ProposalShortId_verify(s, c) mol_verify_fixed_size(s, 10) -#define MolReader_ProposalShortId_get_nth0(s) mol_slice_by_offset(s, 0, 1) -#define MolReader_ProposalShortId_get_nth1(s) mol_slice_by_offset(s, 1, 1) -#define MolReader_ProposalShortId_get_nth2(s) mol_slice_by_offset(s, 2, 1) -#define MolReader_ProposalShortId_get_nth3(s) mol_slice_by_offset(s, 3, 1) -#define MolReader_ProposalShortId_get_nth4(s) mol_slice_by_offset(s, 4, 1) -#define MolReader_ProposalShortId_get_nth5(s) mol_slice_by_offset(s, 5, 1) -#define MolReader_ProposalShortId_get_nth6(s) mol_slice_by_offset(s, 6, 1) -#define MolReader_ProposalShortId_get_nth7(s) mol_slice_by_offset(s, 7, 1) -#define MolReader_ProposalShortId_get_nth8(s) mol_slice_by_offset(s, 8, 1) -#define MolReader_ProposalShortId_get_nth9(s) mol_slice_by_offset(s, 9, 1) -mol_errno MolReader_UncleBlockVec_verify(const mol_seg_t *, bool); -#define MolReader_UncleBlockVec_length(s) mol_dynvec_length(s) -#define MolReader_UncleBlockVec_get(s, i) mol_dynvec_slice_by_index(s, i) -mol_errno MolReader_TransactionVec_verify(const mol_seg_t *, bool); -#define MolReader_TransactionVec_length(s) mol_dynvec_length(s) -#define MolReader_TransactionVec_get(s, i) mol_dynvec_slice_by_index(s, i) -#define MolReader_ProposalShortIdVec_verify(s, c) mol_fixvec_verify(s, 10) -#define MolReader_ProposalShortIdVec_length(s) mol_fixvec_length(s) -#define MolReader_ProposalShortIdVec_get(s, i) \ - mol_fixvec_slice_by_index(s, 10, i) -#define MolReader_CellDepVec_verify(s, c) mol_fixvec_verify(s, 37) -#define MolReader_CellDepVec_length(s) mol_fixvec_length(s) -#define MolReader_CellDepVec_get(s, i) mol_fixvec_slice_by_index(s, 37, i) -#define MolReader_CellInputVec_verify(s, c) mol_fixvec_verify(s, 44) -#define MolReader_CellInputVec_length(s) mol_fixvec_length(s) -#define MolReader_CellInputVec_get(s, i) mol_fixvec_slice_by_index(s, 44, i) -mol_errno MolReader_CellOutputVec_verify(const mol_seg_t *, bool); -#define MolReader_CellOutputVec_length(s) mol_dynvec_length(s) -#define MolReader_CellOutputVec_get(s, i) mol_dynvec_slice_by_index(s, i) -mol_errno MolReader_Script_verify(const mol_seg_t *, bool); -#define MolReader_Script_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Script_has_extra_fields(s) mol_table_has_extra_fields(s, 3) -#define MolReader_Script_get_code_hash(s) mol_table_slice_by_index(s, 0) -#define MolReader_Script_get_hash_type(s) mol_table_slice_by_index(s, 1) -#define MolReader_Script_get_args(s) mol_table_slice_by_index(s, 2) -#define MolReader_OutPoint_verify(s, c) mol_verify_fixed_size(s, 36) -#define MolReader_OutPoint_get_tx_hash(s) mol_slice_by_offset(s, 0, 32) -#define MolReader_OutPoint_get_index(s) mol_slice_by_offset(s, 32, 4) -#define MolReader_CellInput_verify(s, c) mol_verify_fixed_size(s, 44) -#define MolReader_CellInput_get_since(s) mol_slice_by_offset(s, 0, 8) -#define MolReader_CellInput_get_previous_output(s) mol_slice_by_offset(s, 8, 36) -mol_errno MolReader_CellOutput_verify(const mol_seg_t *, bool); -#define MolReader_CellOutput_actual_field_count(s) \ - mol_table_actual_field_count(s) -#define MolReader_CellOutput_has_extra_fields(s) \ - mol_table_has_extra_fields(s, 3) -#define MolReader_CellOutput_get_capacity(s) mol_table_slice_by_index(s, 0) -#define MolReader_CellOutput_get_lock(s) mol_table_slice_by_index(s, 1) -#define MolReader_CellOutput_get_type_(s) mol_table_slice_by_index(s, 2) -#define MolReader_CellDep_verify(s, c) mol_verify_fixed_size(s, 37) -#define MolReader_CellDep_get_out_point(s) mol_slice_by_offset(s, 0, 36) -#define MolReader_CellDep_get_dep_type(s) mol_slice_by_offset(s, 36, 1) -mol_errno MolReader_RawTransaction_verify(const mol_seg_t *, bool); -#define MolReader_RawTransaction_actual_field_count(s) \ - mol_table_actual_field_count(s) -#define MolReader_RawTransaction_has_extra_fields(s) \ - mol_table_has_extra_fields(s, 6) -#define MolReader_RawTransaction_get_version(s) mol_table_slice_by_index(s, 0) -#define MolReader_RawTransaction_get_cell_deps(s) mol_table_slice_by_index(s, 1) -#define MolReader_RawTransaction_get_header_deps(s) \ - mol_table_slice_by_index(s, 2) -#define MolReader_RawTransaction_get_inputs(s) mol_table_slice_by_index(s, 3) -#define MolReader_RawTransaction_get_outputs(s) mol_table_slice_by_index(s, 4) -#define MolReader_RawTransaction_get_outputs_data(s) \ - mol_table_slice_by_index(s, 5) -mol_errno MolReader_Transaction_verify(const mol_seg_t *, bool); -#define MolReader_Transaction_actual_field_count(s) \ - mol_table_actual_field_count(s) -#define MolReader_Transaction_has_extra_fields(s) \ - mol_table_has_extra_fields(s, 2) -#define MolReader_Transaction_get_raw(s) mol_table_slice_by_index(s, 0) -#define MolReader_Transaction_get_witnesses(s) mol_table_slice_by_index(s, 1) -#define MolReader_RawHeader_verify(s, c) mol_verify_fixed_size(s, 192) -#define MolReader_RawHeader_get_version(s) mol_slice_by_offset(s, 0, 4) -#define MolReader_RawHeader_get_compact_target(s) mol_slice_by_offset(s, 4, 4) -#define MolReader_RawHeader_get_timestamp(s) mol_slice_by_offset(s, 8, 8) -#define MolReader_RawHeader_get_number(s) mol_slice_by_offset(s, 16, 8) -#define MolReader_RawHeader_get_epoch(s) mol_slice_by_offset(s, 24, 8) -#define MolReader_RawHeader_get_parent_hash(s) mol_slice_by_offset(s, 32, 32) -#define MolReader_RawHeader_get_transactions_root(s) \ - mol_slice_by_offset(s, 64, 32) -#define MolReader_RawHeader_get_proposals_hash(s) mol_slice_by_offset(s, 96, 32) -#define MolReader_RawHeader_get_uncles_hash(s) mol_slice_by_offset(s, 128, 32) -#define MolReader_RawHeader_get_dao(s) mol_slice_by_offset(s, 160, 32) -#define MolReader_Header_verify(s, c) mol_verify_fixed_size(s, 208) -#define MolReader_Header_get_raw(s) mol_slice_by_offset(s, 0, 192) -#define MolReader_Header_get_nonce(s) mol_slice_by_offset(s, 192, 16) -mol_errno MolReader_UncleBlock_verify(const mol_seg_t *, bool); -#define MolReader_UncleBlock_actual_field_count(s) \ - mol_table_actual_field_count(s) -#define MolReader_UncleBlock_has_extra_fields(s) \ - mol_table_has_extra_fields(s, 2) -#define MolReader_UncleBlock_get_header(s) mol_table_slice_by_index(s, 0) -#define MolReader_UncleBlock_get_proposals(s) mol_table_slice_by_index(s, 1) -mol_errno MolReader_Block_verify(const mol_seg_t *, bool); -#define MolReader_Block_actual_field_count(s) mol_table_actual_field_count(s) -#define MolReader_Block_has_extra_fields(s) mol_table_has_extra_fields(s, 4) -#define MolReader_Block_get_header(s) mol_table_slice_by_index(s, 0) -#define MolReader_Block_get_uncles(s) mol_table_slice_by_index(s, 1) -#define MolReader_Block_get_transactions(s) mol_table_slice_by_index(s, 2) -#define MolReader_Block_get_proposals(s) mol_table_slice_by_index(s, 3) -mol_errno MolReader_CellbaseWitness_verify(const mol_seg_t *, bool); -#define MolReader_CellbaseWitness_actual_field_count(s) \ - mol_table_actual_field_count(s) -#define MolReader_CellbaseWitness_has_extra_fields(s) \ - mol_table_has_extra_fields(s, 2) -#define MolReader_CellbaseWitness_get_lock(s) mol_table_slice_by_index(s, 0) -#define MolReader_CellbaseWitness_get_message(s) mol_table_slice_by_index(s, 1) -mol_errno MolReader_WitnessArgs_verify(const mol_seg_t *, bool); -#define MolReader_WitnessArgs_actual_field_count(s) \ - mol_table_actual_field_count(s) -#define MolReader_WitnessArgs_has_extra_fields(s) \ - mol_table_has_extra_fields(s, 3) -#define MolReader_WitnessArgs_get_lock(s) mol_table_slice_by_index(s, 0) -#define MolReader_WitnessArgs_get_input_type(s) mol_table_slice_by_index(s, 1) -#define MolReader_WitnessArgs_get_output_type(s) mol_table_slice_by_index(s, 2) - -/* - * Builder APIs - */ - -#define MolBuilder_Uint32_init(b) mol_builder_initialize_fixed_size(b, 4) -#define MolBuilder_Uint32_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint32_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint32_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint32_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint32_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint32_clear(b) mol_builder_discard(b) -#define MolBuilder_Uint64_init(b) mol_builder_initialize_fixed_size(b, 8) -#define MolBuilder_Uint64_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint64_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint64_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint64_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint64_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Uint64_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Uint64_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Uint64_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Uint64_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint64_clear(b) mol_builder_discard(b) -#define MolBuilder_Uint128_init(b) mol_builder_initialize_fixed_size(b, 16) -#define MolBuilder_Uint128_set_nth0(b, p) \ - mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint128_set_nth1(b, p) \ - mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint128_set_nth2(b, p) \ - mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint128_set_nth3(b, p) \ - mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint128_set_nth4(b, p) \ - mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Uint128_set_nth5(b, p) \ - mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Uint128_set_nth6(b, p) \ - mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Uint128_set_nth7(b, p) \ - mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Uint128_set_nth8(b, p) \ - mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_Uint128_set_nth9(b, p) \ - mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_Uint128_set_nth10(b, p) \ - mol_builder_set_byte_by_offset(b, 10, p) -#define MolBuilder_Uint128_set_nth11(b, p) \ - mol_builder_set_byte_by_offset(b, 11, p) -#define MolBuilder_Uint128_set_nth12(b, p) \ - mol_builder_set_byte_by_offset(b, 12, p) -#define MolBuilder_Uint128_set_nth13(b, p) \ - mol_builder_set_byte_by_offset(b, 13, p) -#define MolBuilder_Uint128_set_nth14(b, p) \ - mol_builder_set_byte_by_offset(b, 14, p) -#define MolBuilder_Uint128_set_nth15(b, p) \ - mol_builder_set_byte_by_offset(b, 15, p) -#define MolBuilder_Uint128_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint128_clear(b) mol_builder_discard(b) -#define MolBuilder_Byte32_init(b) mol_builder_initialize_fixed_size(b, 32) -#define MolBuilder_Byte32_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Byte32_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Byte32_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Byte32_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Byte32_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Byte32_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Byte32_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Byte32_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Byte32_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_Byte32_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_Byte32_set_nth10(b, p) \ - mol_builder_set_byte_by_offset(b, 10, p) -#define MolBuilder_Byte32_set_nth11(b, p) \ - mol_builder_set_byte_by_offset(b, 11, p) -#define MolBuilder_Byte32_set_nth12(b, p) \ - mol_builder_set_byte_by_offset(b, 12, p) -#define MolBuilder_Byte32_set_nth13(b, p) \ - mol_builder_set_byte_by_offset(b, 13, p) -#define MolBuilder_Byte32_set_nth14(b, p) \ - mol_builder_set_byte_by_offset(b, 14, p) -#define MolBuilder_Byte32_set_nth15(b, p) \ - mol_builder_set_byte_by_offset(b, 15, p) -#define MolBuilder_Byte32_set_nth16(b, p) \ - mol_builder_set_byte_by_offset(b, 16, p) -#define MolBuilder_Byte32_set_nth17(b, p) \ - mol_builder_set_byte_by_offset(b, 17, p) -#define MolBuilder_Byte32_set_nth18(b, p) \ - mol_builder_set_byte_by_offset(b, 18, p) -#define MolBuilder_Byte32_set_nth19(b, p) \ - mol_builder_set_byte_by_offset(b, 19, p) -#define MolBuilder_Byte32_set_nth20(b, p) \ - mol_builder_set_byte_by_offset(b, 20, p) -#define MolBuilder_Byte32_set_nth21(b, p) \ - mol_builder_set_byte_by_offset(b, 21, p) -#define MolBuilder_Byte32_set_nth22(b, p) \ - mol_builder_set_byte_by_offset(b, 22, p) -#define MolBuilder_Byte32_set_nth23(b, p) \ - mol_builder_set_byte_by_offset(b, 23, p) -#define MolBuilder_Byte32_set_nth24(b, p) \ - mol_builder_set_byte_by_offset(b, 24, p) -#define MolBuilder_Byte32_set_nth25(b, p) \ - mol_builder_set_byte_by_offset(b, 25, p) -#define MolBuilder_Byte32_set_nth26(b, p) \ - mol_builder_set_byte_by_offset(b, 26, p) -#define MolBuilder_Byte32_set_nth27(b, p) \ - mol_builder_set_byte_by_offset(b, 27, p) -#define MolBuilder_Byte32_set_nth28(b, p) \ - mol_builder_set_byte_by_offset(b, 28, p) -#define MolBuilder_Byte32_set_nth29(b, p) \ - mol_builder_set_byte_by_offset(b, 29, p) -#define MolBuilder_Byte32_set_nth30(b, p) \ - mol_builder_set_byte_by_offset(b, 30, p) -#define MolBuilder_Byte32_set_nth31(b, p) \ - mol_builder_set_byte_by_offset(b, 31, p) -#define MolBuilder_Byte32_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Byte32_clear(b) mol_builder_discard(b) -#define MolBuilder_Uint256_init(b) mol_builder_initialize_fixed_size(b, 32) -#define MolBuilder_Uint256_set_nth0(b, p) \ - mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_Uint256_set_nth1(b, p) \ - mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_Uint256_set_nth2(b, p) \ - mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_Uint256_set_nth3(b, p) \ - mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_Uint256_set_nth4(b, p) \ - mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_Uint256_set_nth5(b, p) \ - mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_Uint256_set_nth6(b, p) \ - mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_Uint256_set_nth7(b, p) \ - mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_Uint256_set_nth8(b, p) \ - mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_Uint256_set_nth9(b, p) \ - mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_Uint256_set_nth10(b, p) \ - mol_builder_set_byte_by_offset(b, 10, p) -#define MolBuilder_Uint256_set_nth11(b, p) \ - mol_builder_set_byte_by_offset(b, 11, p) -#define MolBuilder_Uint256_set_nth12(b, p) \ - mol_builder_set_byte_by_offset(b, 12, p) -#define MolBuilder_Uint256_set_nth13(b, p) \ - mol_builder_set_byte_by_offset(b, 13, p) -#define MolBuilder_Uint256_set_nth14(b, p) \ - mol_builder_set_byte_by_offset(b, 14, p) -#define MolBuilder_Uint256_set_nth15(b, p) \ - mol_builder_set_byte_by_offset(b, 15, p) -#define MolBuilder_Uint256_set_nth16(b, p) \ - mol_builder_set_byte_by_offset(b, 16, p) -#define MolBuilder_Uint256_set_nth17(b, p) \ - mol_builder_set_byte_by_offset(b, 17, p) -#define MolBuilder_Uint256_set_nth18(b, p) \ - mol_builder_set_byte_by_offset(b, 18, p) -#define MolBuilder_Uint256_set_nth19(b, p) \ - mol_builder_set_byte_by_offset(b, 19, p) -#define MolBuilder_Uint256_set_nth20(b, p) \ - mol_builder_set_byte_by_offset(b, 20, p) -#define MolBuilder_Uint256_set_nth21(b, p) \ - mol_builder_set_byte_by_offset(b, 21, p) -#define MolBuilder_Uint256_set_nth22(b, p) \ - mol_builder_set_byte_by_offset(b, 22, p) -#define MolBuilder_Uint256_set_nth23(b, p) \ - mol_builder_set_byte_by_offset(b, 23, p) -#define MolBuilder_Uint256_set_nth24(b, p) \ - mol_builder_set_byte_by_offset(b, 24, p) -#define MolBuilder_Uint256_set_nth25(b, p) \ - mol_builder_set_byte_by_offset(b, 25, p) -#define MolBuilder_Uint256_set_nth26(b, p) \ - mol_builder_set_byte_by_offset(b, 26, p) -#define MolBuilder_Uint256_set_nth27(b, p) \ - mol_builder_set_byte_by_offset(b, 27, p) -#define MolBuilder_Uint256_set_nth28(b, p) \ - mol_builder_set_byte_by_offset(b, 28, p) -#define MolBuilder_Uint256_set_nth29(b, p) \ - mol_builder_set_byte_by_offset(b, 29, p) -#define MolBuilder_Uint256_set_nth30(b, p) \ - mol_builder_set_byte_by_offset(b, 30, p) -#define MolBuilder_Uint256_set_nth31(b, p) \ - mol_builder_set_byte_by_offset(b, 31, p) -#define MolBuilder_Uint256_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Uint256_clear(b) mol_builder_discard(b) -#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) -#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) -#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) -#define MolBuilder_BytesOpt_init(b) mol_builder_initialize_fixed_size(b, 0) -#define MolBuilder_BytesOpt_set(b, p, l) mol_option_builder_set(b, p, l) -#define MolBuilder_BytesOpt_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_BytesOpt_clear(b) mol_builder_discard(b) -#define MolBuilder_BytesVec_init(b) \ - mol_builder_initialize_with_capacity(b, 64, 64) -#define MolBuilder_BytesVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_BytesVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_BytesVec_clear(b) mol_builder_discard(b) -#define MolBuilder_Byte32Vec_init(b) mol_fixvec_builder_initialize(b, 512) -#define MolBuilder_Byte32Vec_push(b, p) mol_fixvec_builder_push(b, p, 32) -#define MolBuilder_Byte32Vec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_Byte32Vec_clear(b) mol_builder_discard(b) -#define MolBuilder_ScriptOpt_init(b) mol_builder_initialize_fixed_size(b, 0) -#define MolBuilder_ScriptOpt_set(b, p, l) mol_option_builder_set(b, p, l) -#define MolBuilder_ScriptOpt_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_ScriptOpt_clear(b) mol_builder_discard(b) -#define MolBuilder_ProposalShortId_init(b) \ - mol_builder_initialize_fixed_size(b, 10) -#define MolBuilder_ProposalShortId_set_nth0(b, p) \ - mol_builder_set_byte_by_offset(b, 0, p) -#define MolBuilder_ProposalShortId_set_nth1(b, p) \ - mol_builder_set_byte_by_offset(b, 1, p) -#define MolBuilder_ProposalShortId_set_nth2(b, p) \ - mol_builder_set_byte_by_offset(b, 2, p) -#define MolBuilder_ProposalShortId_set_nth3(b, p) \ - mol_builder_set_byte_by_offset(b, 3, p) -#define MolBuilder_ProposalShortId_set_nth4(b, p) \ - mol_builder_set_byte_by_offset(b, 4, p) -#define MolBuilder_ProposalShortId_set_nth5(b, p) \ - mol_builder_set_byte_by_offset(b, 5, p) -#define MolBuilder_ProposalShortId_set_nth6(b, p) \ - mol_builder_set_byte_by_offset(b, 6, p) -#define MolBuilder_ProposalShortId_set_nth7(b, p) \ - mol_builder_set_byte_by_offset(b, 7, p) -#define MolBuilder_ProposalShortId_set_nth8(b, p) \ - mol_builder_set_byte_by_offset(b, 8, p) -#define MolBuilder_ProposalShortId_set_nth9(b, p) \ - mol_builder_set_byte_by_offset(b, 9, p) -#define MolBuilder_ProposalShortId_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_ProposalShortId_clear(b) mol_builder_discard(b) -#define MolBuilder_UncleBlockVec_init(b) \ - mol_builder_initialize_with_capacity(b, 4096, 64) -#define MolBuilder_UncleBlockVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_UncleBlockVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_UncleBlockVec_clear(b) mol_builder_discard(b) -#define MolBuilder_TransactionVec_init(b) \ - mol_builder_initialize_with_capacity(b, 2048, 64) -#define MolBuilder_TransactionVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_TransactionVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_TransactionVec_clear(b) mol_builder_discard(b) -#define MolBuilder_ProposalShortIdVec_init(b) \ - mol_fixvec_builder_initialize(b, 256) -#define MolBuilder_ProposalShortIdVec_push(b, p) \ - mol_fixvec_builder_push(b, p, 10) -#define MolBuilder_ProposalShortIdVec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_ProposalShortIdVec_clear(b) mol_builder_discard(b) -#define MolBuilder_CellDepVec_init(b) mol_fixvec_builder_initialize(b, 1024) -#define MolBuilder_CellDepVec_push(b, p) mol_fixvec_builder_push(b, p, 37) -#define MolBuilder_CellDepVec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_CellDepVec_clear(b) mol_builder_discard(b) -#define MolBuilder_CellInputVec_init(b) mol_fixvec_builder_initialize(b, 1024) -#define MolBuilder_CellInputVec_push(b, p) mol_fixvec_builder_push(b, p, 44) -#define MolBuilder_CellInputVec_build(b) mol_fixvec_builder_finalize(b) -#define MolBuilder_CellInputVec_clear(b) mol_builder_discard(b) -#define MolBuilder_CellOutputVec_init(b) \ - mol_builder_initialize_with_capacity(b, 2048, 64) -#define MolBuilder_CellOutputVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) -#define MolBuilder_CellOutputVec_build(b) mol_dynvec_builder_finalize(b) -#define MolBuilder_CellOutputVec_clear(b) mol_builder_discard(b) -#define MolBuilder_Script_init(b) mol_table_builder_initialize(b, 256, 3) -#define MolBuilder_Script_set_code_hash(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Script_set_hash_type(b, p) \ - mol_table_builder_add_byte(b, 1, p) -#define MolBuilder_Script_set_args(b, p, l) mol_table_builder_add(b, 2, p, l) -mol_seg_res_t MolBuilder_Script_build(mol_builder_t); -#define MolBuilder_Script_clear(b) mol_builder_discard(b) -#define MolBuilder_OutPoint_init(b) mol_builder_initialize_fixed_size(b, 36) -#define MolBuilder_OutPoint_set_tx_hash(b, p) \ - mol_builder_set_by_offset(b, 0, p, 32) -#define MolBuilder_OutPoint_set_index(b, p) \ - mol_builder_set_by_offset(b, 32, p, 4) -#define MolBuilder_OutPoint_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_OutPoint_clear(b) mol_builder_discard(b) -#define MolBuilder_CellInput_init(b) mol_builder_initialize_fixed_size(b, 44) -#define MolBuilder_CellInput_set_since(b, p) \ - mol_builder_set_by_offset(b, 0, p, 8) -#define MolBuilder_CellInput_set_previous_output(b, p) \ - mol_builder_set_by_offset(b, 8, p, 36) -#define MolBuilder_CellInput_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_CellInput_clear(b) mol_builder_discard(b) -#define MolBuilder_CellOutput_init(b) mol_table_builder_initialize(b, 512, 3) -#define MolBuilder_CellOutput_set_capacity(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_CellOutput_set_lock(b, p, l) \ - mol_table_builder_add(b, 1, p, l) -#define MolBuilder_CellOutput_set_type_(b, p, l) \ - mol_table_builder_add(b, 2, p, l) -mol_seg_res_t MolBuilder_CellOutput_build(mol_builder_t); -#define MolBuilder_CellOutput_clear(b) mol_builder_discard(b) -#define MolBuilder_CellDep_init(b) mol_builder_initialize_fixed_size(b, 37) -#define MolBuilder_CellDep_set_out_point(b, p) \ - mol_builder_set_by_offset(b, 0, p, 36) -#define MolBuilder_CellDep_set_dep_type(b, p) \ - mol_builder_set_byte_by_offset(b, 36, p) -#define MolBuilder_CellDep_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_CellDep_clear(b) mol_builder_discard(b) -#define MolBuilder_RawTransaction_init(b) \ - mol_table_builder_initialize(b, 256, 6) -#define MolBuilder_RawTransaction_set_version(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_RawTransaction_set_cell_deps(b, p, l) \ - mol_table_builder_add(b, 1, p, l) -#define MolBuilder_RawTransaction_set_header_deps(b, p, l) \ - mol_table_builder_add(b, 2, p, l) -#define MolBuilder_RawTransaction_set_inputs(b, p, l) \ - mol_table_builder_add(b, 3, p, l) -#define MolBuilder_RawTransaction_set_outputs(b, p, l) \ - mol_table_builder_add(b, 4, p, l) -#define MolBuilder_RawTransaction_set_outputs_data(b, p, l) \ - mol_table_builder_add(b, 5, p, l) -mol_seg_res_t MolBuilder_RawTransaction_build(mol_builder_t); -#define MolBuilder_RawTransaction_clear(b) mol_builder_discard(b) -#define MolBuilder_Transaction_init(b) mol_table_builder_initialize(b, 512, 2) -#define MolBuilder_Transaction_set_raw(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Transaction_set_witnesses(b, p, l) \ - mol_table_builder_add(b, 1, p, l) -mol_seg_res_t MolBuilder_Transaction_build(mol_builder_t); -#define MolBuilder_Transaction_clear(b) mol_builder_discard(b) -#define MolBuilder_RawHeader_init(b) mol_builder_initialize_fixed_size(b, 192) -#define MolBuilder_RawHeader_set_version(b, p) \ - mol_builder_set_by_offset(b, 0, p, 4) -#define MolBuilder_RawHeader_set_compact_target(b, p) \ - mol_builder_set_by_offset(b, 4, p, 4) -#define MolBuilder_RawHeader_set_timestamp(b, p) \ - mol_builder_set_by_offset(b, 8, p, 8) -#define MolBuilder_RawHeader_set_number(b, p) \ - mol_builder_set_by_offset(b, 16, p, 8) -#define MolBuilder_RawHeader_set_epoch(b, p) \ - mol_builder_set_by_offset(b, 24, p, 8) -#define MolBuilder_RawHeader_set_parent_hash(b, p) \ - mol_builder_set_by_offset(b, 32, p, 32) -#define MolBuilder_RawHeader_set_transactions_root(b, p) \ - mol_builder_set_by_offset(b, 64, p, 32) -#define MolBuilder_RawHeader_set_proposals_hash(b, p) \ - mol_builder_set_by_offset(b, 96, p, 32) -#define MolBuilder_RawHeader_set_uncles_hash(b, p) \ - mol_builder_set_by_offset(b, 128, p, 32) -#define MolBuilder_RawHeader_set_dao(b, p) \ - mol_builder_set_by_offset(b, 160, p, 32) -#define MolBuilder_RawHeader_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_RawHeader_clear(b) mol_builder_discard(b) -#define MolBuilder_Header_init(b) mol_builder_initialize_fixed_size(b, 208) -#define MolBuilder_Header_set_raw(b, p) mol_builder_set_by_offset(b, 0, p, 192) -#define MolBuilder_Header_set_nonce(b, p) \ - mol_builder_set_by_offset(b, 192, p, 16) -#define MolBuilder_Header_build(b) mol_builder_finalize_simple(b) -#define MolBuilder_Header_clear(b) mol_builder_discard(b) -#define MolBuilder_UncleBlock_init(b) mol_table_builder_initialize(b, 1024, 2) -#define MolBuilder_UncleBlock_set_header(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_UncleBlock_set_proposals(b, p, l) \ - mol_table_builder_add(b, 1, p, l) -mol_seg_res_t MolBuilder_UncleBlock_build(mol_builder_t); -#define MolBuilder_UncleBlock_clear(b) mol_builder_discard(b) -#define MolBuilder_Block_init(b) mol_table_builder_initialize(b, 1024, 4) -#define MolBuilder_Block_set_header(b, p, l) mol_table_builder_add(b, 0, p, l) -#define MolBuilder_Block_set_uncles(b, p, l) mol_table_builder_add(b, 1, p, l) -#define MolBuilder_Block_set_transactions(b, p, l) \ - mol_table_builder_add(b, 2, p, l) -#define MolBuilder_Block_set_proposals(b, p, l) \ - mol_table_builder_add(b, 3, p, l) -mol_seg_res_t MolBuilder_Block_build(mol_builder_t); -#define MolBuilder_Block_clear(b) mol_builder_discard(b) -#define MolBuilder_CellbaseWitness_init(b) \ - mol_table_builder_initialize(b, 512, 2) -#define MolBuilder_CellbaseWitness_set_lock(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_CellbaseWitness_set_message(b, p, l) \ - mol_table_builder_add(b, 1, p, l) -mol_seg_res_t MolBuilder_CellbaseWitness_build(mol_builder_t); -#define MolBuilder_CellbaseWitness_clear(b) mol_builder_discard(b) -#define MolBuilder_WitnessArgs_init(b) mol_table_builder_initialize(b, 64, 3) -#define MolBuilder_WitnessArgs_set_lock(b, p, l) \ - mol_table_builder_add(b, 0, p, l) -#define MolBuilder_WitnessArgs_set_input_type(b, p, l) \ - mol_table_builder_add(b, 1, p, l) -#define MolBuilder_WitnessArgs_set_output_type(b, p, l) \ - mol_table_builder_add(b, 2, p, l) -mol_seg_res_t MolBuilder_WitnessArgs_build(mol_builder_t); -#define MolBuilder_WitnessArgs_clear(b) mol_builder_discard(b) - -#endif // CKB_MISCELLANEOUS_SCRIPTS_SIMULATOR_MOLECULE_DECL_ONLY_H_ diff --git a/include/ckb-c-stdlib/simulator/rsa_sighash_all_usesim.c b/include/ckb-c-stdlib/simulator/rsa_sighash_all_usesim.c deleted file mode 100644 index 74ec868..0000000 --- a/include/ckb-c-stdlib/simulator/rsa_sighash_all_usesim.c +++ /dev/null @@ -1,543 +0,0 @@ -#include -#define ASSERT assert - -#include "../c/rsa_sighash_all.c" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/entropy.h" -#include "mbedtls/md.h" - -void dump_as_carray(uint8_t* ptr, size_t size) { - for (size_t i = 0; i < size; i++) { - if (i == (size - 1)) { - mbedtls_printf("0x%02X\n", ptr[i]); - } else { - mbedtls_printf("0x%02X,", ptr[i]); - } - } -} - -static unsigned char get_hex(unsigned char c) { - if (c >= '0' && c <= '9') - return c - '0'; - else if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - else if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - else - return 0; -} - -static int scan_hex(const char* s, unsigned char* value) { - if (s[0] == '\0' || s[1] == '\0') return 0; - - unsigned char high_part = get_hex(s[0]); - unsigned char low_part = get_hex(s[1]); - - *value = (high_part << 4) + low_part; - return 1; -} - -static uint32_t read_string(const char* str, uint8_t* buf, uint32_t buf_size) { - size_t sig_len = strlen(str); - const char* ptr = str; - const char* end = str + sig_len; - - uint32_t i = 0; - while (1) { - unsigned char c = 0; - int consumed = scan_hex(ptr, &c); - if (consumed == 0) break; - if (i >= buf_size) break; - buf[i++] = (uint8_t)c; - ptr += consumed * 2; - if (ptr >= end) break; - } - return i; -} - -void mbedtls_mpi_dump(const char* prefix, const mbedtls_mpi* X) { - size_t n; - char s[1024]; - memset(s, 0, sizeof(s)); - - mbedtls_mpi_write_string(X, 16, s, sizeof(s) - 2, &n); - mbedtls_printf("%s%s\n", prefix, s); -} - -void dup_buffer(const unsigned char* src, int src_len, unsigned char* dest, - int dup_count) { - for (int i = 0; i < dup_count; i++) { - for (int j = 0; j < src_len; j++) { - dest[i * src_len + j] = src[j]; - } - } -} - -int ecdsa_sighash_random(void); - -typedef struct mbedtls_test_rnd_pseudo_info { - uint32_t key[16]; - uint32_t v0, v1; -} mbedtls_test_rnd_pseudo_info; - -int mbedtls_test_rnd_pseudo_rand(void* rng_state, unsigned char* output, - size_t len) { - for (size_t i = 0; i < len; i++) { - output[i] = (unsigned char)rand(); - } - return 0; -} - -void srand(unsigned seed); -long time(long*); - -int ecdsa_sighash_random(void) { - int err = 0; - int id = MBEDTLS_ECP_DP_SECP256R1; - Secp256r1Info info; - mbedtls_ecp_group grp; - mbedtls_ecp_point Q; - mbedtls_mpi d, r, s; - mbedtls_test_rnd_pseudo_info rnd_info; - unsigned char buf[32]; - - int alloc_buff_size = 1024 * 1024; - unsigned char alloc_buff[alloc_buff_size]; - mbedtls_memory_buffer_alloc_init(alloc_buff, alloc_buff_size); - - srand(time(NULL)); - - mbedtls_ecp_group_init(&grp); - mbedtls_ecp_point_init(&Q); - mbedtls_mpi_init(&d); - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); - memset(buf, 0, sizeof(buf)); - - ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info, buf, sizeof(buf)) == 0); - ASSERT(mbedtls_ecp_group_load(&grp, id) == 0); - ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q, &mbedtls_test_rnd_pseudo_rand, - &rnd_info) == 0); - - ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf), - &mbedtls_test_rnd_pseudo_rand, &rnd_info) == 0); - - serialize_secp256r1info(&Q, &r, &s, &info); - - mbedtls_ecp_group_free(&grp); - mbedtls_ecp_point_free(&Q); - mbedtls_mpi_free(&d); - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - - if (false) { - mbedtls_ecp_point new_Q; - mbedtls_mpi new_r; - mbedtls_mpi new_s; - - deserialize_secp256r1info(&new_Q, &new_r, &new_s, &info); - ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &new_Q, &new_r, - &new_s) == 0); - } else { - info.algorithm_id = CKB_VERIFY_SECP256R1; - // dump_as_carray((uint8_t *)&info, sizeof(info)); - // dump_as_carray(buf, sizeof(buf)); - err = validate_signature_secp256r1(NULL, (const unsigned char*)&info, - sizeof(info), buf, sizeof(buf), NULL, - NULL); - CHECK(err); - } - err = CKB_SUCCESS; -exit: - if (err == CKB_SUCCESS) { - mbedtls_printf("ecdsa_sighash_random() passed.\n"); - } else { - mbedtls_printf("ecdsa_sighash_random() failed.\n"); - } - return err; -} - -#define EXPONENT 65537 - -int fake_random_entropy_poll(void* data, unsigned char* output, size_t len, - size_t* olen) { - *output = (unsigned char)rand(); - *olen = len; - return 0; -} - -int gen_rsa_key(uint32_t key_size, mbedtls_rsa_context* rsa) { - int err = 0; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - const char* pers = "rsa_genkey"; - - mbedtls_ctr_drbg_init(&ctr_drbg); - mbedtls_entropy_init(&entropy); - mbedtls_rsa_init(rsa, MBEDTLS_RSA_PKCS_V15, 0); - - err = mbedtls_entropy_add_source(&entropy, fake_random_entropy_poll, NULL, 32, - MBEDTLS_ENTROPY_SOURCE_STRONG); - CHECK(err); - - err = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, - (const unsigned char*)pers, strlen(pers)); - CHECK(err); - - err = mbedtls_rsa_gen_key(rsa, mbedtls_ctr_drbg_random, &ctr_drbg, key_size, - EXPONENT); - CHECK(err); - - err = 0; - -exit: - mbedtls_ctr_drbg_free(&ctr_drbg); - mbedtls_entropy_free(&entropy); - return err; -} - -int rsa_sign(mbedtls_rsa_context* rsa, const uint8_t* msg_buf, - uint32_t msg_size, uint8_t* sig) { - int err = 0; - - uint8_t hash_buf[32] = {0}; - uint32_t hash_size = 32; - unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; - mbedtls_mpi N, P, Q, E; - mbedtls_test_rnd_pseudo_info rnd_info; - - memset(&rnd_info, 0, sizeof(mbedtls_test_rnd_pseudo_info)); - ASSERT(mbedtls_rsa_check_privkey(rsa) == 0); - err = md_string(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), msg_buf, - msg_size, hash_buf); - CHECK(err); - - err = mbedtls_rsa_pkcs1_sign(rsa, &mbedtls_test_rnd_pseudo_rand, &rnd_info, - MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, - hash_size, hash_buf, sig); - CHECK(err); - err = CKB_SUCCESS; -exit: - return err; -} - -int rsa_verify(mbedtls_rsa_context* rsa, const uint8_t* msg_buf, - uint32_t msg_size, const uint8_t* sig) { - int err = 0; - uint8_t hash_buf[32] = {0}; - uint32_t hash_size = 32; - - ASSERT(mbedtls_rsa_check_pubkey(rsa) == 0); - err = md_string(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), msg_buf, - msg_size, hash_buf); - CHECK(err); - err = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, - MBEDTLS_MD_SHA256, hash_size, hash_buf, sig); - CHECK(err); - - err = 0; -exit: - return err; -} - -int rsa_random(void) { - int err = 0; - - int alloc_buff_size = 1024 * 1024; - unsigned char alloc_buff[alloc_buff_size]; - mbedtls_memory_buffer_alloc_init(alloc_buff, alloc_buff_size); - - uint32_t key_size = 1024; - uint32_t byte_size = key_size / 8; - - uint8_t msg[32] = {1, 2, 3, 4}; - uint8_t sig[byte_size]; - mbedtls_rsa_context rsa; - err = gen_rsa_key(key_size, &rsa); - CHECK(err); - - err = rsa_sign(&rsa, msg, sizeof(msg), sig); - CHECK(err); - - err = rsa_verify(&rsa, msg, sizeof(msg), sig); - CHECK(err); - - err = 0; -exit: - if (err == CKB_SUCCESS) { - mbedtls_printf("rsa_random() passed.\n"); - } else { - mbedtls_printf("rsa_random() failed.\n"); - } - return err; -} - -void export_public_key(const mbedtls_rsa_context* rsa, RsaInfo* info) { - mbedtls_mpi N, E; - mbedtls_mpi_init(&N); - mbedtls_mpi_init(&E); - int ret = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E); - ASSERT(ret == 0); - mbedtls_mpi_write_binary_le(&N, info->N, info->key_size / 8); - mbedtls_mpi_write_binary_le(&E, (unsigned char*)&info->E, sizeof(info->E)); -} - -int rsa_sighash_random(void) { - int err = 0; - - int alloc_buff_size = 1024 * 1024; - unsigned char alloc_buff[alloc_buff_size]; - mbedtls_memory_buffer_alloc_init(alloc_buff, alloc_buff_size); - - uint32_t key_size = 1024; - uint32_t byte_size = key_size / 8; - - uint8_t msg[32] = {1, 2, 3, 4}; - uint8_t sig[byte_size]; - mbedtls_rsa_context rsa; - err = gen_rsa_key(key_size, &rsa); - CHECK(err); - - err = rsa_sign(&rsa, msg, sizeof(msg), sig); - CHECK(err); - - RsaInfo info; - info.algorithm_id = CKB_VERIFY_RSA; - info.key_size = key_size; - export_public_key(&rsa, &info); - - uint8_t* ptr = get_rsa_signature(&info); - memcpy(ptr, sig, sizeof(sig)); - - uint8_t output[20]; - size_t output_len = 20; - err = validate_signature(NULL, (uint8_t*)&info, sizeof(info), msg, - sizeof(msg), output, &output_len); - CHECK(err); - - err = 0; -exit: - if (err == CKB_SUCCESS) { - mbedtls_printf("rsa_sighash_random() passed.\n"); - } else { - mbedtls_printf("rsa_sighash_random() failed.\n"); - } - return err; -} - -int rsa_sighash_all(void) { - int err = 0; - uint8_t output[BLAKE160_SIZE]; - - err = validate_rsa_sighash_all(output); - CHECK2(err == ERROR_RSA_VERIFY_FAILED, err); - - err = 0; -exit: - if (err == 0) { - mbedtls_printf( - "rsa_sighash_all() passed. (Ignore the failed messages above)\n"); - } else { - mbedtls_printf("rsa_sighash_all() failed.\n"); - } - return err; -} - -int iso97962_test2(void) { - int err = 0; - const char* N_str = - "9cf68418644a5418529373350bafd57ddbf5626527b95e8ea3217d8dac8fbcb7db107eda" - "5e47979b7e4343ed6441950f7fbd921075579104ba081f1a9af950b4c0ee67c2eef2068d" - "9fe2d9d0cfdcbb9be7066e19cc945600e9fd41fc50e771f437ce4bdde63e7acf2a828a4b" - "f38b9f907a252b3dfef550919da1819033f9c619"; - const char* E_str = "10001"; - const char* msg_str = "B30D0D9FA0C8BBDF"; - const char* sig_str = - "46E52F52599A97B7DBBB8BCDD3A3BE6857F4CEF41B0723BE9FBD404DCF471DFC00D2DBF2" - "F5DA6A9B8C1A41893A569873CAD2E90EECEC84DEE85DCDE76041390D1E1328751F2832C8" - "3699986744AF68087EFFB21CD9526317424C136911144AE31B00F1764F1C5CCD974D52F6" - "278B029197C5746E62F67C544FA5C9B66E2A8AFB"; - const char* plaintext_str = - "6A51762ED9802385DD5AE676C603778A037FFDCCD2BA92E32DD3AECE0C31AF76CFF88F75" - "B257930255EA361218BEDCC4B1A96BBC9BCCF77BF6BA4B4A7F847F475F81C1FDD30C74B6" - "AC97732C32D4B23C4BF8200270F5F15FED198E80AA5089807B9861E374D3871509C9965A" - "AD886D9FB5A345873A4EB58EEFA5C35A4C3B55BC"; - - mbedtls_rsa_context rsa; - mbedtls_mpi N; - mbedtls_mpi E; - - uint8_t msg[8]; - uint8_t sig[128]; - uint8_t block[128]; - uint32_t sig_len = 0; - uint32_t msg_len = 0; - uint8_t m1[128]; - uint32_t m1_len = 128; - uint8_t full_msg[1024]; - uint8_t new_msg[1024]; - uint32_t new_msg_len = 1024; - - int alloc_buff_size = 1024 * 1024; - unsigned char alloc_buff[alloc_buff_size]; - mbedtls_memory_buffer_alloc_init(alloc_buff, alloc_buff_size); - - mbedtls_mpi_init(&N); - mbedtls_mpi_init(&E); - - mbedtls_mpi_read_string(&N, 16, N_str); - mbedtls_mpi_read_string(&E, 16, E_str); - mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); - mbedtls_rsa_import(&rsa, &N, NULL, NULL, NULL, &E); - - sig_len = read_string(sig_str, sig, sizeof(sig)); - ASSERT(sig_len == 128); - msg_len = read_string(msg_str, msg, sizeof(msg)); - ASSERT(msg_len == 8); - - err = mbedtls_rsa_public(&rsa, sig, block); - CHECK(err); - - ISO97962Encoding enc = {0}; - iso97962_init(&enc, 1024, MBEDTLS_MD_SHA1, false); - err = iso97962_verify(&enc, block, sizeof(block), msg, msg_len, m1, &m1_len); - CHECK2(err == 0 || err == ERROR_ISO97962_MISMATCH_HASH, - ERROR_ISO97962_INVALID_ARG9); - - memcpy(full_msg, m1, m1_len); - memcpy(full_msg + m1_len, msg, sizeof(msg)); - - err = iso97962_verify(&enc, block, sizeof(block), full_msg, - m1_len + sizeof(msg), new_msg, &new_msg_len); - CHECK(err); - - err = 0; -exit: - if (err == 0) { - mbedtls_printf("iso97962_test2() passed.\n"); - } else { - mbedtls_printf("iso97962_test2() failed.\n"); - } - return err; -} - -int iso97962_test(void) { - int err = 0; - ISO97962Encoding enc = {0}; - iso97962_init(&enc, 1024, MBEDTLS_MD_SHA1, false); - uint8_t msg[] = {1, 2, 3, 4, 5, 6, 7, 8}; - uint32_t msg_len = sizeof(msg); - - uint8_t block[128] = {0}; - err = iso97962_sign(&enc, msg, sizeof(msg), block, sizeof(block)); - CHECK(err); - uint8_t new_msg[128]; - uint32_t new_msg_len = 128; - err = iso97962_verify(&enc, block, sizeof(block), NULL, 0, new_msg, - &new_msg_len); - CHECK(err); - ASSERT(new_msg_len == msg_len); - ASSERT(memcmp(msg, new_msg, msg_len) == 0); - - err = 0; -exit: - if (err == 0) { - mbedtls_printf("iso97962_test() passed.\n"); - } else { - mbedtls_printf("iso97962_test() failed.\n"); - } - return err; -} - -int iso97962_test3(uint32_t key_size, const char* N_str, const char* E_str, - const char* msg_str, const char* sig_str) { - int err = 0; - - mbedtls_mpi N; - mbedtls_mpi E; - - uint8_t msg[4096]; - uint32_t msg_len = 0; - - uint8_t sig[4096]; - uint32_t sig_len = 0; - - uint8_t new_msg[1024]; - size_t new_msg_len = 1024; - - int alloc_buff_size = 1024 * 1024; - unsigned char alloc_buff[alloc_buff_size]; - mbedtls_memory_buffer_alloc_init(alloc_buff, alloc_buff_size); - - mbedtls_mpi_init(&N); - mbedtls_mpi_init(&E); - mbedtls_mpi_read_string(&N, 16, N_str); - mbedtls_mpi_read_string(&E, 16, E_str); - - sig_len = read_string(sig_str, sig, sizeof(sig)); - ASSERT(sig_len == key_size); - msg_len = read_string(msg_str, msg, sizeof(msg)); - ASSERT(msg_len > 0 && msg_len < key_size); - - RsaInfo info; - info.key_size = key_size * 8; // in bit - info.algorithm_id = CKB_VERIFY_ISO9796_2; - mbedtls_mpi_write_binary_le(&N, (uint8_t*)info.N, key_size); - mbedtls_mpi_write_binary_le(&E, (uint8_t*)&info.E, sizeof(info.E)); - - ASSERT(sig_len == key_size); - memcpy(info.sig, sig, sig_len); - - err = validate_signature(NULL, (uint8_t*)&info, sizeof(info), msg, msg_len, - new_msg, &new_msg_len); - CHECK(err); - - err = 0; -exit: - return err; -} - -int main(int argc, const char* argv[]) { - int err = 0; - err = ecdsa_sighash_random(); - CHECK(err); - - err = rsa_random(); - CHECK(err); - - err = rsa_sighash_random(); - CHECK(err); - - err = rsa_sighash_all(); - CHECK(err); - - err = iso97962_test(); - CHECK(err); - - err = iso97962_test2(); - CHECK(err); - - // RSA public key, N - const char* N_str = - "9cf68418644a5418529373350bafd57ddbf5626527b95e8ea3217d8dac8fbcb7db107eda" - "5e47979b7e4343ed6441950f7fbd921075579104ba081f1a9af950b4c0ee67c2eef2068d" - "9fe2d9d0cfdcbb9be7066e19cc945600e9fd41fc50e771f437ce4bdde63e7acf2a828a4b" - "f38b9f907a252b3dfef550919da1819033f9c619"; - // RSA public key, E, 65537 - const char* E_str = "10001"; - // input small message - const char* msg_str = "B30D0D9FA0C8BBDF"; - // input signature - const char* sig_str = - "46E52F52599A97B7DBBB8BCDD3A3BE6857F4CEF41B0723BE9FBD404DCF471DFC00D2DBF2" - "F5DA6A9B8C1A41893A569873CAD2E90EECEC84DEE85DCDE76041390D1E1328751F2832C8" - "3699986744AF68087EFFB21CD9526317424C136911144AE31B00F1764F1C5CCD974D52F6" - "278B029197C5746E62F67C544FA5C9B66E2A8AFB"; - err = iso97962_test3(128, N_str, E_str, msg_str, sig_str); - CHECK(err); - - err = 0; -exit: - return err; -} From 56ac98b8a5585178210f2fe503e1fb978501d5e3 Mon Sep 17 00:00:00 2001 From: YI Date: Wed, 6 Sep 2023 22:10:21 +0800 Subject: [PATCH 05/18] use ckb-c-stdlib as submodule fetch submodule in github actions --- .github/workflows/ci.yml | 4 +++- .gitmodules | 3 +++ include/ckb-c-stdlib | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) create mode 160000 include/ckb-c-stdlib diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a00dde..93588bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 + with: + submodules: true - uses: leafo/gh-actions-lua@v9 with: luaVersion: "5.4" diff --git a/.gitmodules b/.gitmodules index e69de29..f12c637 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "include/ckb-c-stdlib"] + path = include/ckb-c-stdlib + url = https://github.com/contrun/ckb-c-stdlib.git diff --git a/include/ckb-c-stdlib b/include/ckb-c-stdlib new file mode 160000 index 0000000..cf1624e --- /dev/null +++ b/include/ckb-c-stdlib @@ -0,0 +1 @@ +Subproject commit cf1624ef9fdf1ee5488f689746e2485ef9242e64 From 4c807735f75de8179c678b3b4e4ad5e002ba0a70 Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 09:12:17 +0800 Subject: [PATCH 06/18] lock rust toolchain version otherwise procmacro2 will fail to build --- tests/test_cases/tests_rust/rust-toolchain.toml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/test_cases/tests_rust/rust-toolchain.toml diff --git a/tests/test_cases/tests_rust/rust-toolchain.toml b/tests/test_cases/tests_rust/rust-toolchain.toml new file mode 100644 index 0000000..f0263f9 --- /dev/null +++ b/tests/test_cases/tests_rust/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.72.0" +components = [ "rustfmt", "clippy" ] +profile = "minimal" From 50e1d07402757599ef1f233ed53f0eeac1de8895 Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 09:27:57 +0800 Subject: [PATCH 07/18] use ckb-c-stdlib with minimal changes --- include/ckb-c-stdlib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ckb-c-stdlib b/include/ckb-c-stdlib index cf1624e..aba7f2b 160000 --- a/include/ckb-c-stdlib +++ b/include/ckb-c-stdlib @@ -1 +1 @@ -Subproject commit cf1624ef9fdf1ee5488f689746e2485ef9242e64 +Subproject commit aba7f2bf1b2ff1b4a60a5cd0988215bd4eca3431 From e02420d42d6d131e56aff5fbf38b7d715a7704dd Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 12:09:21 +0800 Subject: [PATCH 08/18] add stdlib function locally --- Makefile | 2 +- lua-loader/lua-loader.c | 5 +- lualib/Makefile | 8 +- lualib/c-stdlib/my_ctype.h | 16 + lualib/c-stdlib/my_errno.h | 18 + lualib/c-stdlib/my_features.h | 40 ++ lualib/c-stdlib/my_locale.h | 41 ++ lualib/c-stdlib/my_math.h | 63 ++ lualib/c-stdlib/my_setjmp.h | 46 ++ lualib/c-stdlib/my_stddef.h | 6 + lualib/c-stdlib/my_stdlib.h | 10 + lualib/c-stdlib/my_string.h | 17 + lualib/c-stdlib/src/impl.c | 933 ++++++++++++++++++++++++++++++ lualib/c-stdlib/src/malloc_impl.h | 421 ++++++++++++++ lualib/luaconf.h | 1 + 15 files changed, 1622 insertions(+), 5 deletions(-) create mode 100644 lualib/c-stdlib/my_ctype.h create mode 100644 lualib/c-stdlib/my_errno.h create mode 100644 lualib/c-stdlib/my_features.h create mode 100644 lualib/c-stdlib/my_locale.h create mode 100644 lualib/c-stdlib/my_math.h create mode 100644 lualib/c-stdlib/my_setjmp.h create mode 100644 lualib/c-stdlib/my_stddef.h create mode 100644 lualib/c-stdlib/my_stdlib.h create mode 100644 lualib/c-stdlib/my_string.h create mode 100644 lualib/c-stdlib/src/impl.c create mode 100644 lualib/c-stdlib/src/malloc_impl.h diff --git a/Makefile b/Makefile index 3f3504f..b6ce695 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CC := $(TARGET)-gcc LD := $(TARGET)-gcc OBJCOPY := $(TARGET)-objcopy -CFLAGS := -D__ISO_C_VISIBLE=1999 -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I lualib -I include/ckb-c-stdlib -I include/ckb-c-stdlib/libc -I include/ckb-c-stdlib/molecule -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g +CFLAGS := -D__ISO_C_VISIBLE=1999 -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I lualib -I lualib/c-stdlib -I include/ckb-c-stdlib -I include/ckb-c-stdlib/libc -I include/ckb-c-stdlib/molecule -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -Wno-error=maybe-uninitialized -g LDFLAGS := -nostdlib -nostartfiles -fno-builtin -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections diff --git a/lua-loader/lua-loader.c b/lua-loader/lua-loader.c index a49dfd8..9aa2d68 100644 --- a/lua-loader/lua-loader.c +++ b/lua-loader/lua-loader.c @@ -1,5 +1,5 @@ -#define CKB_C_STDLIB_MALLOC 1 #define CKB_C_STDLIB_PRINTF 1 +#define CKB_MALLOC_DECLARATION_ONLY 1 #define lua_c @@ -7,6 +7,7 @@ #include #include #include +#include "my_string.h" #include "lauxlib.h" #include "lprefix.h" @@ -24,6 +25,8 @@ #define LUA_LOADER_ARGS_SIZE 2 #define BLAKE2B_BLOCK_SIZE 32 +extern void malloc_config(uintptr_t min, uintptr_t max); + int exit(int c) { ckb_exit(c); return 0; diff --git a/lualib/Makefile b/lualib/Makefile index 30d68ac..e4fe75e 100644 --- a/lualib/Makefile +++ b/lualib/Makefile @@ -10,7 +10,7 @@ CC=riscv64-unknown-linux-gnu-gcc # -ULUA_USE_LINUX -ULUA_USE_POSIX to make lua dependencies minimal, # otherwise, we may unable to find various platform dependent symbols, e.g. # setsignal. -CFLAGS= -D__ISO_C_VISIBLE=1999 -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) +CFLAGS= -Ic-stdlib -DCKB_MALLOC_DECLARATION_ONLY=1 -D__ISO_C_VISIBLE=1999 -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) LIBS= -lm $(SYSLIBS) $(MYLIBS) @@ -37,7 +37,7 @@ PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix LUA_A= liblua.a CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o lstrlib.o ltablib.o lutf8lib.o linit.o mocked_stdio.o mocked_math.o +LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o lstrlib.o ltablib.o lutf8lib.o linit.o mocked_stdio.o mocked_math.o stdlib.o BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) LUA_T= lua @@ -156,6 +156,9 @@ lparser.o: lcode.o: $(CC) $(CFLAGS) $(CMCFLAGS) -c lcode.c +stdlib.o: + $(CC) $(CFLAGS) $(CMCFLAGS) -o $@ -c c-stdlib/src/impl.c + # DO NOT DELETE lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \ @@ -220,6 +223,5 @@ lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \ ltable.h lvm.h ljumptab.h lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \ lobject.h ltm.h lzio.h -mocked_stdio.o: mocked_stdio.h mocked_stdio.c # (end of Makefile) diff --git a/lualib/c-stdlib/my_ctype.h b/lualib/c-stdlib/my_ctype.h new file mode 100644 index 0000000..a771c88 --- /dev/null +++ b/lualib/c-stdlib/my_ctype.h @@ -0,0 +1,16 @@ +#ifndef LUA_C_STDLIB_CTYPE_H_ +#define LUA_C_STDLIB_CTYPE_H_ +#ifdef __cplusplus +extern "C" { +#endif + +int islower(int); +int isupper(int); + +int tolower(int); +int toupper(int); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lualib/c-stdlib/my_errno.h b/lualib/c-stdlib/my_errno.h new file mode 100644 index 0000000..b2a4825 --- /dev/null +++ b/lualib/c-stdlib/my_errno.h @@ -0,0 +1,18 @@ +#ifndef LUA_C_STDLIB_ERRNO_H_ +#define LUA_C_STDLIB_ERRNO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ +__attribute__((const)) +#endif +int *__errno_location(void); +#define errno (*__errno_location()) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lualib/c-stdlib/my_features.h b/lualib/c-stdlib/my_features.h new file mode 100644 index 0000000..85cfb72 --- /dev/null +++ b/lualib/c-stdlib/my_features.h @@ -0,0 +1,40 @@ +#ifndef _FEATURES_H +#define _FEATURES_H + +#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE 1 +#endif + +#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ + && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ + && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) +#define _BSD_SOURCE 1 +#define _XOPEN_SOURCE 700 +#endif + +#if __STDC_VERSION__ >= 199901L +#define __restrict restrict +#elif !defined(__GNUC__) +#define __restrict +#endif + +#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) +#define __inline inline +#elif !defined(__GNUC__) +#define __inline +#endif + +#if __STDC_VERSION__ >= 201112L +#elif defined(__GNUC__) +#define _Noreturn __attribute__((__noreturn__)) +#else +#define _Noreturn +#endif + +#define __REDIR(x,y) __typeof__(x) x __asm__(#y) + +#endif diff --git a/lualib/c-stdlib/my_locale.h b/lualib/c-stdlib/my_locale.h new file mode 100644 index 0000000..5b22701 --- /dev/null +++ b/lualib/c-stdlib/my_locale.h @@ -0,0 +1,41 @@ +#ifndef LUA_C_STDLIB_LOCALE_H_ +#define LUA_C_STDLIB_LOCALE_H_ +#ifdef __cplusplus +extern "C" { +#endif + +struct lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_p_cs_precedes; + char int_p_sep_by_space; + char int_n_cs_precedes; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + +struct lconv *localeconv(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lualib/c-stdlib/my_math.h b/lualib/c-stdlib/my_math.h new file mode 100644 index 0000000..9bc8f7f --- /dev/null +++ b/lualib/c-stdlib/my_math.h @@ -0,0 +1,63 @@ +#ifndef LUA_C_STDLIB_MATH_H_ +#define LUA_C_STDLIB_MATH_H_ + +#define DBL_MAX 1.79769313486231570815e+308 + +#ifdef __cplusplus +extern "C" { +#endif + +/* fp_force_eval ensures that the input value is computed when that's + otherwise unused. To prevent the constant folding of the input + expression, an additional fp_barrier may be needed or a compilation + mode that does so (e.g. -frounding-math in gcc). Then it can be + used to evaluate an expression for its fenv side-effects only. */ + +#ifndef fp_force_evalf +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; + (void)y; +} +#endif + +#ifndef fp_force_eval +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; + (void)y; +} +#endif + +#ifndef fp_force_evall +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) +{ + volatile long double y; + y = x; + (void)y; +} +#endif + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) + +double fmod(double, double); +double frexp(double, int *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lualib/c-stdlib/my_setjmp.h b/lualib/c-stdlib/my_setjmp.h new file mode 100644 index 0000000..675e953 --- /dev/null +++ b/lualib/c-stdlib/my_setjmp.h @@ -0,0 +1,46 @@ +#ifndef LUA_C_STDLIB_SETJMP_H_ +#define LUA_C_STDLIB_SETJMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef unsigned long __jmp_buf[26]; + +typedef struct __jmp_buf_tag { + __jmp_buf __jb; + unsigned long __fl; + unsigned long __ss[128 / sizeof(long)]; +} jmp_buf[1]; + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) +#define __setjmp_attr __attribute__((__returns_twice__)) +#else +#define __setjmp_attr +#endif + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \ + defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef jmp_buf sigjmp_buf; +int sigsetjmp(sigjmp_buf, int) __setjmp_attr; +_Noreturn void siglongjmp(sigjmp_buf, int); +#endif + +int _setjmp(jmp_buf) __setjmp_attr; + +_Noreturn void _longjmp(jmp_buf, int); + +int setjmp(jmp_buf) __setjmp_attr; +_Noreturn void longjmp(jmp_buf, int); + +#define setjmp setjmp + +#undef __setjmp_attr + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lualib/c-stdlib/my_stddef.h b/lualib/c-stdlib/my_stddef.h new file mode 100644 index 0000000..0edfc8d --- /dev/null +++ b/lualib/c-stdlib/my_stddef.h @@ -0,0 +1,6 @@ +#ifndef LUA_C_STDLIB_STDDEF_H_ +#define LUA_C_STDLIB_STDDEF_H_ + +typedef signed long ptrdiff_t; + +#endif /* LUA_C_STDLIB_STDDEF_H_ */ diff --git a/lualib/c-stdlib/my_stdlib.h b/lualib/c-stdlib/my_stdlib.h new file mode 100644 index 0000000..df6c58e --- /dev/null +++ b/lualib/c-stdlib/my_stdlib.h @@ -0,0 +1,10 @@ +#ifndef LUA_C_STDLIB_STDLIB_H_ +#define LUA_C_STDLIB_STDLIB_H_ + +float strtof(const char *__restrict, char **__restrict); +double strtod(const char *__restrict, char **__restrict); +long double strtold(const char *__restrict, char **__restrict); + +int abs (int); + +#endif /* LUA_C_STDLIB_STDLIB_H_ */ diff --git a/lualib/c-stdlib/my_string.h b/lualib/c-stdlib/my_string.h new file mode 100644 index 0000000..61310e0 --- /dev/null +++ b/lualib/c-stdlib/my_string.h @@ -0,0 +1,17 @@ +#ifndef LUA_C_STDLIB_STRING_H_ +#define LUA_C_STDLIB_STRING_H_ + +#include + +char *strchr (const char *, int); +int strncmp(const char *_l, const char *_r, size_t n); +char *strpbrk (const char *, const char *); +size_t strcspn (const char *, const char *); +size_t strspn (const char *, const char *); +void *memchr (const void *, int, size_t); + +int strcoll (const char *, const char *); + +char *strerror (int); + +#endif /* LUA_C_STDLIB_STRING_H_ */ diff --git a/lualib/c-stdlib/src/impl.c b/lualib/c-stdlib/src/impl.c new file mode 100644 index 0000000..122dfcc --- /dev/null +++ b/lualib/c-stdlib/src/impl.c @@ -0,0 +1,933 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CKB_SS (sizeof(size_t)) +#define CKB_ALIGN (sizeof(size_t) - 1) +#define CKB_ONES ((size_t)-1 / UCHAR_MAX) +#define CKB_HIGHS (CKB_ONES * (UCHAR_MAX / 2 + 1)) +#define CKB_HASZERO(x) (((x)-CKB_ONES) & ~(x)&CKB_HIGHS) + +void *memchr(const void *src, int c, size_t n) { + const unsigned char *s = src; + c = (unsigned char)c; +#ifdef __GNUC__ + for (; ((uintptr_t)s & CKB_ALIGN) && n && *s != c; s++, n--) + ; + if (n && *s != c) { + typedef size_t __attribute__((__may_alias__)) word; + const word *w; + size_t k = CKB_ONES * c; + for (w = (const void *)s; n >= CKB_SS && !CKB_HASZERO(*w ^ k); + w++, n -= CKB_SS) + ; + s = (const void *)w; + } +#endif + for (; n && *s != c; s++, n--) + ; + return n ? (void *)s : 0; +} + +#define BITOP(a, b, op) \ + ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ + << ((size_t)(b) % (8 * sizeof *(a)))) + +char *__strchrnul(const char *s, int c) { + c = (unsigned char)c; + if (!c) + return (char *)s + strlen(s); + + for (; *s && *(unsigned char *)s != c; s++) + ; + return (char *)s; +} + +char *strchr(const char *s, int c) { + char *r = __strchrnul(s, c); + return *(unsigned char *)r == (unsigned char)c ? r : 0; +} + +int strncmp(const char *_l, const char *_r, size_t n) { + const unsigned char *l = (void *)_l, *r = (void *)_r; + if (!n--) + return 0; + for (; *l && *r && n && *l == *r; l++, r++, n--) + ; + return *l - *r; +} + +size_t strspn(const char *s, const char *c) { + const char *a = s; + size_t byteset[32 / sizeof(size_t)] = {0}; + + if (!c[0]) + return 0; + if (!c[1]) { + for (; *s == *c; s++) + ; + return s - a; + } + + for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) + ; + for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++) + ; + return s - a; +} + +size_t strcspn(const char *s, const char *c) { + const char *a = s; + size_t byteset[32 / sizeof(size_t)]; + + if (!c[0] || !c[1]) + return __strchrnul(s, *c) - a; + + memset(byteset, 0, sizeof byteset); + for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++) + ; + for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++) + ; + return s - a; +} + +char *strpbrk(const char *s, const char *b) { + s += strcspn(s, b); + return *s ? (char *)s : 0; +} + +static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) { + uint16_t nw = n[0] << 8 | n[1], hw = h[0] << 8 | h[1]; + for (h++; *h && hw != nw; hw = hw << 8 | *++h) + ; + return *h ? (char *)h - 1 : 0; +} + +static char *threebyte_strstr(const unsigned char *h, const unsigned char *n) { + uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8; + uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8; + for (h += 2; *h && hw != nw; hw = (hw | *++h) << 8) + ; + return *h ? (char *)h - 2 : 0; +} + +static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n) { + uint32_t nw = (uint32_t)n[0] << 24 | n[1] << 16 | n[2] << 8 | n[3]; + uint32_t hw = (uint32_t)h[0] << 24 | h[1] << 16 | h[2] << 8 | h[3]; + for (h += 3; *h && hw != nw; hw = hw << 8 | *++h) + ; + return *h ? (char *)h - 3 : 0; +} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define BITOP(a, b, op) \ + ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 \ + << ((size_t)(b) % (8 * sizeof *(a)))) + +static char *twoway_strstr(const unsigned char *h, const unsigned char *n) { + const unsigned char *z; + size_t l, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = {0}; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (l = 0; n[l] && h[l]; l++) + BITOP(byteset, n[l], |=), shift[n[l]] = l + 1; + if (n[l]) + return 0; /* hit the end of h */ + + /* Compute maximal suffix */ + ip = -1; + jp = 0; + k = p = 1; + while (jp + k < l) { + if (n[ip + k] == n[jp + k]) { + if (k == p) { + jp += p; + k = 1; + } else + k++; + } else if (n[ip + k] > n[jp + k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; + jp = 0; + k = p = 1; + while (jp + k < l) { + if (n[ip + k] == n[jp + k]) { + if (k == p) { + jp += p; + k = 1; + } else + k++; + } else if (n[ip + k] < n[jp + k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + if (ip + 1 > ms + 1) + ms = ip; + else + p = p0; + + /* Periodic needle? */ + if (memcmp(n, n + p, ms + 1)) { + mem0 = 0; + p = MAX(ms, l - ms - 1) + 1; + } else + mem0 = l - p; + mem = 0; + + /* Initialize incremental end-of-haystack pointer */ + z = h; + + /* Search loop */ + for (;;) { + /* Update incremental end-of-haystack pointer */ + if (z - h < l) { + /* Fast estimate for MAX(l,63) */ + size_t grow = l | 63; + const unsigned char *z2 = memchr(z, 0, grow); + if (z2) { + z = z2; + if (z - h < l) + return 0; + } else + z += grow; + } + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l - 1], &)) { + k = l - shift[h[l - 1]]; + if (k) { + if (k < mem) + k = mem; + h += k; + mem = 0; + continue; + } + } else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k = MAX(ms + 1, mem); n[k] && n[k] == h[k]; k++) + ; + if (n[k]) { + h += k - ms; + mem = 0; + continue; + } + /* Compare left half */ + for (k = ms + 1; k > mem && n[k - 1] == h[k - 1]; k--) + ; + if (k <= mem) + return (char *)h; + h += p; + mem = mem0; + } +} + +char *strstr(const char *h, const char *n) { + /* Return immediately on empty needle */ + if (!n[0]) + return (char *)h; + + /* Use faster algorithms for short needles */ + h = strchr(h, *n); + if (!h || !n[1]) + return (char *)h; + if (!h[1]) + return 0; + if (!n[2]) + return twobyte_strstr((void *)h, (void *)n); + if (!h[2]) + return 0; + if (!n[3]) + return threebyte_strstr((void *)h, (void *)n); + if (!h[3]) + return 0; + if (!n[4]) + return fourbyte_strstr((void *)h, (void *)n); + + return twoway_strstr((void *)h, (void *)n); +} + +static const struct lconv posix_lconv = { + .decimal_point = ".", + .thousands_sep = "", + .grouping = "", + .int_curr_symbol = "", + .currency_symbol = "", + .mon_decimal_point = "", + .mon_thousands_sep = "", + .mon_grouping = "", + .positive_sign = "", + .negative_sign = "", + .int_frac_digits = CHAR_MAX, + .frac_digits = CHAR_MAX, + .p_cs_precedes = CHAR_MAX, + .p_sep_by_space = CHAR_MAX, + .n_cs_precedes = CHAR_MAX, + .n_sep_by_space = CHAR_MAX, + .p_sign_posn = CHAR_MAX, + .n_sign_posn = CHAR_MAX, + .int_p_cs_precedes = CHAR_MAX, + .int_p_sep_by_space = CHAR_MAX, + .int_n_cs_precedes = CHAR_MAX, + .int_n_sep_by_space = CHAR_MAX, + .int_p_sign_posn = CHAR_MAX, + .int_n_sign_posn = CHAR_MAX, +}; + +struct lconv *localeconv(void) { + return (void *)&posix_lconv; +} + +#ifdef CKB_C_STDLIB_MALLOC +#include "malloc_impl.h" +#else +void *malloc(size_t size) { return NULL; } +void free(void *ptr) {} +void *calloc(size_t nmemb, size_t size) { return NULL; } +void *realloc(void *ptr, size_t size) { return NULL; } +#endif + +/* Copied from + * https://github.com/bminor/musl/blob/46d1c7801bb509e1097e8fadbaf359367fa4ef0b/src/setjmp/riscv64/setjmp.S + */ +/* We need to use inline asm for easier compilation, + * https://stackoverflow.com/a/42358235. */ +/* We need __attribute__((naked)) to remove prologue and epilogue, + * https://stackoverflow.com/a/42637729 */ +__attribute__((naked)) int setjmp(jmp_buf b) { + asm volatile("sd s0, 0(a0)\n" + "sd s1, 8(a0)\n" + "sd s2, 16(a0)\n" + "sd s3, 24(a0)\n" + "sd s4, 32(a0)\n" + "sd s5, 40(a0)\n" + "sd s6, 48(a0)\n" + "sd s7, 56(a0)\n" + "sd s8, 64(a0)\n" + "sd s9, 72(a0)\n" + "sd s10, 80(a0)\n" + "sd s11, 88(a0)\n" + "sd sp, 96(a0)\n" + "sd ra, 104(a0)\n" + "li a0, 0\n" + "ret\n"); +} + +__attribute__((naked)) void longjmp(jmp_buf b, int n) { + asm volatile("ld s0, 0(a0)\n" + "ld s1, 8(a0)\n" + "ld s2, 16(a0)\n" + "ld s3, 24(a0)\n" + "ld s4, 32(a0)\n" + "ld s5, 40(a0)\n" + "ld s6, 48(a0)\n" + "ld s7, 56(a0)\n" + "ld s8, 64(a0)\n" + "ld s9, 72(a0)\n" + "ld s10, 80(a0)\n" + "ld s11, 88(a0)\n" + "ld sp, 96(a0)\n" + "ld ra, 104(a0)\n" + "seqz a0, a1\n" + "add a0, a0, a1\n" + "ret\n"); +} + +__attribute__((naked)) void _longjmp(jmp_buf b, int n) { + asm volatile("ld s0, 0(a0)\n" + "ld s1, 8(a0)\n" + "ld s2, 16(a0)\n" + "ld s3, 24(a0)\n" + "ld s4, 32(a0)\n" + "ld s5, 40(a0)\n" + "ld s6, 48(a0)\n" + "ld s7, 56(a0)\n" + "ld s8, 64(a0)\n" + "ld s9, 72(a0)\n" + "ld s10, 80(a0)\n" + "ld s11, 88(a0)\n" + "ld sp, 96(a0)\n" + "ld ra, 104(a0)\n" + "seqz a0, a1\n" + "add a0, a0, a1\n" + "ret\n"); +} + +int abs(int a) { return a > 0 ? a : -a; } + +double frexp(double x, int *e) { + union { + double d; + uint64_t i; + } y = {x}; + int ee = y.i >> 52 & 0x7ff; + + if (!ee) { + if (x) { + x = frexp(x * 0x1p64, e); + *e -= 64; + } else + *e = 0; + return x; + } else if (ee == 0x7ff) { + return x; + } + + *e = ee - 0x3fe; + y.i &= 0x800fffffffffffffull; + y.i |= 0x3fe0000000000000ull; + return y.d; +} + +double fmod(double x, double y) { + union { + double f; + uint64_t i; + } ux = {x}, uy = {y}; + int ex = ux.i >> 52 & 0x7ff; + int ey = uy.i >> 52 & 0x7ff; + int sx = ux.i >> 63; + uint64_t i; + + /* in the followings uxi should be ux.i, but then gcc wrongly adds */ + /* float load/store to inner loops ruining performance and code size */ + uint64_t uxi = ux.i; + + if (uy.i << 1 == 0 || __builtin_isnan(y) || ex == 0x7ff) + return (x * y) / (x * y); + if (uxi << 1 <= uy.i << 1) { + if (uxi << 1 == uy.i << 1) + return 0 * x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = uxi << 12; i >> 63 == 0; ex--, i <<= 1) + ; + uxi <<= -ex + 1; + } else { + uxi &= -1ULL >> 12; + uxi |= 1ULL << 52; + } + if (!ey) { + for (i = uy.i << 12; i >> 63 == 0; ey--, i <<= 1) + ; + uy.i <<= -ey + 1; + } else { + uy.i &= -1ULL >> 12; + uy.i |= 1ULL << 52; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0 * x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0 * x; + uxi = i; + } + for (; uxi >> 52 == 0; uxi <<= 1, ex--) + ; + + /* scale result */ + if (ex > 0) { + uxi -= 1ULL << 52; + uxi |= (uint64_t)ex << 52; + } else { + uxi >>= -ex + 1; + } + uxi |= (uint64_t)sx << 63; + ux.i = uxi; + return ux.f; +} + +int strcoll(const char *l, const char *r) { return strcmp(l, r); } + +int *__errno_location(void) { + static int error = -1; + return &error; +} + +char *strerror(int e) { + static char *errorstr = "There is an error"; + return errorstr; +} + +int islower(int c) { return (unsigned)c - 'a' < 26; } + +int isupper(int c) { return (unsigned)c - 'A' < 26; } + +int tolower(int c) { + if (isupper(c)) + return c | 32; + return c; +} + +int toupper(int c) { + if (islower(c)) + return c & 0x5f; + return c; +} + +#define X(x) (((x) / 256 | (x)*256) % 65536) + +const unsigned short **__ctype_b_loc(void) { + static const unsigned short table[] = { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), + X(0x200), X(0x200), X(0x200), X(0x200), X(0x320), X(0x220), X(0x220), + X(0x220), X(0x220), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), + X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), + X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x200), X(0x160), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), + X(0x8d8), X(0x8d8), X(0x8d8), X(0x8d8), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x8d5), X(0x8d5), X(0x8d5), + X(0x8d5), X(0x8d5), X(0x8d5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), + X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), + X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), X(0x8c5), + X(0x8c5), X(0x8c5), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), X(0x4c0), + X(0x4c0), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), X(0x8d6), + X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), + X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), + X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x8c6), X(0x4c0), + X(0x4c0), X(0x4c0), X(0x4c0), X(0x200), 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + }; + + static const unsigned short *const ptable = table + 128; + return (void *)&ptable; +} + +const int32_t **__ctype_toupper_loc(void) { + static const int32_t table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 91, 92, 93, 94, 95, 96, + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 123, 124, 125, 126, + 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + static const int32_t *const ptable = table + 128; + + return (void *)&ptable; +} + +const int32_t **__ctype_tolower_loc(void) { + static const int32_t table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 91, 92, 93, 94, 95, 96, + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 123, 124, 125, 126, + 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + static const int32_t *const ptable = table + 128; + + return (void *)&ptable; +} + +char *getenv(const char *name) { return 0; } + +int isspace(int c) { return c == ' ' || (unsigned)c - '\t' < 5; } + +// Copied from dietlibc +float strtof(const char *s, char **endptr) { + register const char *p = s; + register float value = 0.; + int sign = +1; + float factor; + unsigned int expo; + + while (isspace(*p)) + p++; + + switch (*p) { + case '-': + sign = -1; /* fall through */ + case '+': + p++; + default: + break; + } + + while ((unsigned int)(*p - '0') < 10u) + value = value * 10 + (*p++ - '0'); + + if (*p == '.') { + factor = 1.; + + p++; + while ((unsigned int)(*p - '0') < 10u) { + factor *= 0.1; + value += (*p++ - '0') * factor; + } + } + + if ((*p | 32) == 'e') { + expo = 0; + factor = 10.L; + + switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' + // folgenden MUSS. + case '-': + factor = 0.1; /* fall through */ + case '+': + p++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + default: + value = 0.L; + p = s; + goto done; + } + + while ((unsigned int)(*p - '0') < 10u) + expo = 10 * expo + (*p++ - '0'); + + while (1) { + if (expo & 1) + value *= factor; + if ((expo >>= 1) == 0) + break; + factor *= factor; + } + } + +done: + if (endptr != NULL) + *endptr = (char *)p; + + return value * sign; +} + +// Convert char to an int in base `base`, +// `base` must be 10 or 16, return -1 on error. +int char2int(char ch, unsigned int base) { + if (ch >= '0' && ch <= '9') + return ch - '0'; + if (base == 16) { + if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + } + return -1; +} + +#define ldbltype long double +double strtod(const char *s, char **endptr) { + register const char *p = s; + register ldbltype value = 0.; + int sign = +1; + unsigned int base = 10; + ldbltype base_inverse = (ldbltype)1 / (ldbltype)base; + ldbltype factor; + unsigned int expo; + unsigned int has_digits = 0; + + while (isspace(*p)) + p++; + + switch (*p) { + case '-': + sign = -1; /* fall through */ + case '+': + p++; + case '0': + p++; + if ((*p | 32) == 'x') { + base = 16; + base_inverse = (ldbltype)1 / (ldbltype)base; + p++; + } else { + p--; + } + default: + break; + } + + unsigned int current_value; + while ((current_value = char2int(*p, base)) != -1) { + p++; + value = value * base + current_value; + has_digits = 1; + } + + if (*p == '.') { + factor = 1.; + + p++; + while ((current_value = char2int(*p, base)) != -1) { + p++; + factor *= base_inverse; + value += current_value * factor; + has_digits = 1; + } + } + + if ((*p | 32) == 'e' && base == 10) { + expo = 0; + factor = 10.; + + switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' + // folgenden MUSS. + case '-': + factor = 0.1; /* fall through */ + case '+': + p++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + default: + value = 0.; + p = s; + goto done; + } + + while ((unsigned int)(*p - '0') < 10u) + expo = 10 * expo + (*p++ - '0'); + + while (1) { + if (expo & 1) + value *= factor; + if ((expo >>= 1) == 0) + break; + factor *= factor; + } + } + + if ((*p | 32) == 'p' && base == 16) { + // TODO: add specifier p support + // https://cplusplus.com/reference/cstdlib/strtod/ + // - A 0x or 0X prefix, then a sequence of hexadecimal digits (as in + // isxdigit) optionally containing a period which separates the whole and + // fractional number parts. Optionally followed by a power of 2 exponent (a + // p or P character followed by an optional sign and a sequence of + // hexadecimal digits). + } +done: + if (endptr != NULL) { + if (has_digits) { + *endptr = (char *)p; + } else { + *endptr = (char *)s; + } + } + + return value * sign; +} + +long double strtold(const char *s, char **endptr) { + register const char *p = s; + register long double value = 0.L; + int sign = +1; + long double factor; + unsigned int expo; + + while (isspace(*p)) + p++; + + switch (*p) { + case '-': + sign = -1; /* fall through */ + case '+': + p++; + default: + break; + } + + while ((unsigned int)(*p - '0') < 10u) + value = value * 10 + (*p++ - '0'); + + if (*p == '.') { + factor = 1.; + + p++; + while ((unsigned int)(*p - '0') < 10u) { + factor *= 0.1; + value += (*p++ - '0') * factor; + } + } + + if ((*p | 32) == 'e') { + expo = 0; + factor = 10.L; + + switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' + // folgenden MUSS. + case '-': + factor = 0.1; /* fall through */ + case '+': + p++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + default: + value = 0.L; + p = s; + goto done; + } + + while ((unsigned int)(*p - '0') < 10u) + expo = 10 * expo + (*p++ - '0'); + + while (1) { + if (expo & 1) + value *= factor; + if ((expo >>= 1) == 0) + break; + factor *= factor; + } + } + +done: + if (endptr != NULL) + *endptr = (char *)p; + + return value * sign; +} diff --git a/lualib/c-stdlib/src/malloc_impl.h b/lualib/c-stdlib/src/malloc_impl.h new file mode 100644 index 0000000..59f15f6 --- /dev/null +++ b/lualib/c-stdlib/src/malloc_impl.h @@ -0,0 +1,421 @@ +#ifndef LUA_C_STDLIB_MALLOC_H_ +#define LUA_C_STDLIB_MALLOC_H_ + +#include "ckb_syscalls.h" + + +#if defined(malloc) +#undef malloc +#endif + +#if defined(realloc) +#undef realloc +#endif + +#if defined(free) +#undef free +#endif + +#ifndef CKB_BRK_MIN +extern char _end[]; /* _end is set in the linker */ +#define CKB_BRK_MIN ((uintptr_t)&_end) +#endif +#ifndef CKB_BRK_MAX +#define CKB_BRK_MAX 0x00300000 +#endif + +struct chunk { + size_t psize, csize; + struct chunk *next, *prev; +}; + +struct bin { + volatile int lock[2]; + struct chunk *head; + struct chunk *tail; +}; + +#define CKB_SIZE_ALIGN (4 * sizeof(size_t)) +#define CKB_SIZE_MASK (-CKB_SIZE_ALIGN) +#define CKB_OVERHEAD (2 * sizeof(size_t)) +#define CKB_DONTCARE 16 +#define CKB_RECLAIM 163840 +#define CKB_MMAP_THRESHOLD (0x1c00*CKB_SIZE_ALIGN) + +#define CKB_CHUNK_SIZE(c) ((c)->csize & -2) +#define CKB_CHUNK_PSIZE(c) ((c)->psize & -2) +#define CKB_PREV_CHUNK(c) ((struct chunk *)((char *)(c)-CKB_CHUNK_PSIZE(c))) +#define CKB_NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CKB_CHUNK_SIZE(c))) +#define CKB_MEM_TO_CHUNK(p) (struct chunk *)((char *)(p)-CKB_OVERHEAD) +#define CKB_CHUNK_TO_MEM(c) (void *)((char *)(c) + CKB_OVERHEAD) +#define CKB_BIN_TO_CHUNK(i) (CKB_MEM_TO_CHUNK(&mal.bins[i].head)) +#define CKB_C_INUSE ((size_t)1) +#define CKB_IS_MMAPPED(c) !((c)->csize & (CKB_C_INUSE)) +#define CKB_PAGE_SIZE 4096 +void __bin_chunk(struct chunk *); +int ckb_exit(int8_t code); +static inline void a_crash() { ckb_exit(-1); } +void free(void *p); + +static inline void a_and_64(volatile uint64_t *p, uint64_t v) { *p &= v; } + +static inline void a_or_64(volatile uint64_t *p, uint64_t v) { *p |= v; } + +static uintptr_t s_program_break = 0; +static uintptr_t s_brk_min = CKB_BRK_MIN; +static uintptr_t s_brk_max = CKB_BRK_MAX; + +void malloc_config(uintptr_t min, uintptr_t max) { + s_brk_min = min; + s_brk_max = max; + s_program_break = 0; +} + +void *_sbrk(uintptr_t incr) { + if (!s_program_break) { + s_program_break = s_brk_min; + s_program_break += -s_program_break & (CKB_PAGE_SIZE - 1); + } + if ((s_program_break + incr) > s_brk_max) { + return (void *)-1; + } + + uintptr_t start = s_program_break; + s_program_break += incr; + return (void *)start; +} + +static struct { + volatile uint64_t binmap; + struct bin bins[64]; + volatile int split_merge_lock[2]; +} mal; + +static inline void lock_bin(int i) { + if (!mal.bins[i].head) + mal.bins[i].head = mal.bins[i].tail = CKB_BIN_TO_CHUNK(i); +} + +static inline void unlock_bin(int i) {} + +#if 0 +static int first_set(uint64_t x) { + // TODO: use RISC-V asm + static const char debruijn64[64] = { + 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, + 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, + 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, + 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12}; + static const char debruijn32[32] = { + 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13, + 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14}; + if (sizeof(long) < 8) { + uint32_t y = x; + if (!y) { + y = x >> 32; + return 32 + debruijn32[(y & -y) * 0x076be629 >> 27]; + } + return debruijn32[(y & -y) * 0x076be629 >> 27]; + } + return debruijn64[(x & -x) * 0x022fdd63cc95386dull >> 58]; +} + +#else + +static int __attribute__((naked)) first_set(uint64_t x) { + __asm__(".byte 0x13, 0x15, 0x15, 0x60"); + __asm__("ret"); +} + +#endif + +static const unsigned char bin_tab[60] = { + 32, 33, 34, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, + 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, + 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 46, + 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, +}; + +static int bin_index(size_t x) { + x = x / CKB_SIZE_ALIGN - 1; + if (x <= 32) + return x; + if (x < 512) + return bin_tab[x / 8 - 4]; + if (x > 0x1c00) + return 63; + return bin_tab[x / 128 - 4] + 16; +} + +static int bin_index_up(size_t x) { + x = x / CKB_SIZE_ALIGN - 1; + if (x <= 32) + return x; + x--; + if (x < 512) + return bin_tab[x / 8 - 4] + 1; + return bin_tab[x / 128 - 4] + 17; +} + +static void *__expand_heap(size_t *pn) { + size_t n = *pn; + n += -n & (CKB_PAGE_SIZE - 1); + + void *p = _sbrk(n); + if (p == (void *)-1) { + return 0; + } + *pn = n; + return p; +} + +static struct chunk *expand_heap(size_t n) { + static void *end; + void *p; + struct chunk *w; + + /* The argument n already accounts for the caller's chunk + * CKB_OVERHEAD needs, but if the heap can't be extended in-place, + * we need room for an extra zero-sized sentinel chunk. */ + n += CKB_SIZE_ALIGN; + + p = __expand_heap(&n); + if (!p) + return 0; + /* If not just expanding existing space, we need to make a + * new sentinel chunk below the allocated space. */ + if (p != end) { + /* Valid/safe because of the prologue increment. */ + n -= CKB_SIZE_ALIGN; + p = (char *)p + CKB_SIZE_ALIGN; + w = CKB_MEM_TO_CHUNK(p); + w->psize = 0 | CKB_C_INUSE; + } + + /* Record new heap end and fill in footer. */ + end = (char *)p + n; + w = CKB_MEM_TO_CHUNK(end); + w->psize = n | CKB_C_INUSE; + w->csize = 0 | CKB_C_INUSE; + + /* Fill in header, which may be new or may be replacing a + * zero-size sentinel header at the old end-of-heap. */ + w = CKB_MEM_TO_CHUNK(p); + w->csize = n | CKB_C_INUSE; + + return w; +} + +static int adjust_size(size_t *n) { + /* Result of pointer difference must fit in ptrdiff_t. */ + if (*n - 1 > INT64_MAX - CKB_SIZE_ALIGN - CKB_PAGE_SIZE) { + if (*n) { + return -1; + } else { + *n = CKB_SIZE_ALIGN; + return 0; + } + } + *n = (*n + CKB_OVERHEAD + CKB_SIZE_ALIGN - 1) & CKB_SIZE_MASK; + return 0; +} + +static void unbin(struct chunk *c, int i) { + if (c->prev == c->next) + a_and_64(&mal.binmap, ~(1ULL << i)); + c->prev->next = c->next; + c->next->prev = c->prev; + c->csize |= CKB_C_INUSE; + CKB_NEXT_CHUNK(c)->psize |= CKB_C_INUSE; +} + +static void bin_chunk(struct chunk *self, int i) { + self->next = CKB_BIN_TO_CHUNK(i); + self->prev = mal.bins[i].tail; + self->next->prev = self; + self->prev->next = self; + if (self->prev == CKB_BIN_TO_CHUNK(i)) + a_or_64(&mal.binmap, 1ULL << i); +} + +static void trim(struct chunk *self, size_t n) { + size_t n1 = CKB_CHUNK_SIZE(self); + struct chunk *next, *split; + + if (n >= n1 - CKB_DONTCARE) + return; + + next = CKB_NEXT_CHUNK(self); + split = (void *)((char *)self + n); + + split->psize = n | CKB_C_INUSE; + split->csize = n1 - n; + next->psize = n1 - n; + self->csize = n | CKB_C_INUSE; + + int i = bin_index(n1 - n); + lock_bin(i); + + bin_chunk(split, i); + + unlock_bin(i); +} + +void *malloc(size_t n) { + struct chunk *c; + int i, j; + uint64_t mask; + + if (adjust_size(&n) < 0) + return 0; + + if (n >= CKB_MMAP_THRESHOLD) { + // TODO: don't support too large memory + return 0; + } + + i = bin_index_up(n); + if (i < 63 && (mal.binmap & (1ULL << i))) { + lock_bin(i); + c = mal.bins[i].head; + if (c != CKB_BIN_TO_CHUNK(i) && CKB_CHUNK_SIZE(c) - n <= CKB_DONTCARE) { + unbin(c, i); + unlock_bin(i); + return CKB_CHUNK_TO_MEM(c); + } + unlock_bin(i); + } + for (mask = mal.binmap & -(1ULL << i); mask; mask -= (mask & -mask)) { + j = first_set(mask); + lock_bin(j); + c = mal.bins[j].head; + if (c != CKB_BIN_TO_CHUNK(j)) { + unbin(c, j); + unlock_bin(j); + break; + } + unlock_bin(j); + } + if (!mask) { + c = expand_heap(n); + if (!c) { + return 0; + } + } + trim(c, n); + return CKB_CHUNK_TO_MEM(c); +} + +void *realloc(void *p, size_t n) { + struct chunk *self, *next; + size_t n0; + void *new; + + if (!p) + return malloc(n); + + if (adjust_size(&n) < 0) + return 0; + + self = CKB_MEM_TO_CHUNK(p); + n0 = CKB_CHUNK_SIZE(self); + + if (n <= n0 && n0 - n <= CKB_DONTCARE) + return p; + + next = CKB_NEXT_CHUNK(self); + + /* Crash on corrupted footer (likely from buffer overflow) */ + if (next->psize != self->csize) + a_crash(); + + if (n < n0) { + int i = bin_index_up(n); + int j = bin_index(n0); + if (i < j && (mal.binmap & (1ULL << i))) + goto copy_realloc; + struct chunk *split = (void *)((char *)self + n); + self->csize = split->psize = n | CKB_C_INUSE; + split->csize = next->psize = (n0 - n) | CKB_C_INUSE; + __bin_chunk(split); + return CKB_CHUNK_TO_MEM(self); + } + + size_t nsize = next->csize & CKB_C_INUSE ? 0 : CKB_CHUNK_SIZE(next); + if (n0 + nsize >= n) { + int i = bin_index(nsize); + lock_bin(i); + if (!(next->csize & CKB_C_INUSE)) { + unbin(next, i); + unlock_bin(i); + next = CKB_NEXT_CHUNK(next); + self->csize = next->psize = (n0 + nsize) | CKB_C_INUSE; + trim(self, n); + return CKB_CHUNK_TO_MEM(self); + } + unlock_bin(i); + } +copy_realloc: + /* As a last resort, allocate a new chunk and copy to it. */ + new = malloc(n - CKB_OVERHEAD); + if (!new) + return 0; + memcpy(new, p, (n < n0 ? n : n0) - CKB_OVERHEAD); + free(CKB_CHUNK_TO_MEM(self)); + return new; +} + +void __bin_chunk(struct chunk *self) { + struct chunk *next = CKB_NEXT_CHUNK(self); + + /* Crash on corrupted footer (likely from buffer overflow) */ + if (next->psize != self->csize) + a_crash(); + + size_t osize = CKB_CHUNK_SIZE(self), size = osize; + + /* Since we hold split_merge_lock, only transition from free to + * in-use can race; in-use to free is impossible */ + size_t psize = self->psize & CKB_C_INUSE ? 0 : CKB_CHUNK_PSIZE(self); + size_t nsize = next->csize & CKB_C_INUSE ? 0 : CKB_CHUNK_SIZE(next); + + if (psize) { + int i = bin_index(psize); + lock_bin(i); + if (!(self->psize & CKB_C_INUSE)) { + struct chunk *prev = CKB_PREV_CHUNK(self); + unbin(prev, i); + self = prev; + size += psize; + } + unlock_bin(i); + } + if (nsize) { + int i = bin_index(nsize); + lock_bin(i); + if (!(next->csize & CKB_C_INUSE)) { + unbin(next, i); + next = CKB_NEXT_CHUNK(next); + size += nsize; + } + unlock_bin(i); + } + + int i = bin_index(size); + lock_bin(i); + + self->csize = size; + next->psize = size; + bin_chunk(self, i); + + unlock_bin(i); +} + +void free(void *p) { + if (!p) + return; + struct chunk *self = CKB_MEM_TO_CHUNK(p); + __bin_chunk(self); +} + +#endif diff --git a/lualib/luaconf.h b/lualib/luaconf.h index 07bf77f..0f3e7f4 100644 --- a/lualib/luaconf.h +++ b/lualib/luaconf.h @@ -9,6 +9,7 @@ #include #include +#include "my_stddef.h" /* ** =================================================================== From 0f69aeb4bdf60274d6b0dadabf7ceeb4f9029e20 Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 12:31:28 +0800 Subject: [PATCH 09/18] fix not using the correct malloc implementation --- lualib/Makefile | 4 ++-- lualib/c-stdlib/src/impl.c | 11 ++--------- lualib/c-stdlib/src/malloc_impl.h | 2 ++ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/lualib/Makefile b/lualib/Makefile index e4fe75e..88ea838 100644 --- a/lualib/Makefile +++ b/lualib/Makefile @@ -10,7 +10,7 @@ CC=riscv64-unknown-linux-gnu-gcc # -ULUA_USE_LINUX -ULUA_USE_POSIX to make lua dependencies minimal, # otherwise, we may unable to find various platform dependent symbols, e.g. # setsignal. -CFLAGS= -Ic-stdlib -DCKB_MALLOC_DECLARATION_ONLY=1 -D__ISO_C_VISIBLE=1999 -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) +CFLAGS= -Ic-stdlib -D__ISO_C_VISIBLE=1999 -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) LIBS= -lm $(SYSLIBS) $(MYLIBS) @@ -157,7 +157,7 @@ lcode.o: $(CC) $(CFLAGS) $(CMCFLAGS) -c lcode.c stdlib.o: - $(CC) $(CFLAGS) $(CMCFLAGS) -o $@ -c c-stdlib/src/impl.c + $(CC) -I../include/ckb-c-stdlib -DCKB_DECLARATION_ONLY=1 $(CFLAGS) $(CMCFLAGS) -o $@ -c c-stdlib/src/impl.c # DO NOT DELETE diff --git a/lualib/c-stdlib/src/impl.c b/lualib/c-stdlib/src/impl.c index 122dfcc..12a1e0d 100644 --- a/lualib/c-stdlib/src/impl.c +++ b/lualib/c-stdlib/src/impl.c @@ -8,6 +8,8 @@ #include #include +#include "malloc_impl.h" + #define CKB_SS (sizeof(size_t)) #define CKB_ALIGN (sizeof(size_t) - 1) #define CKB_ONES ((size_t)-1 / UCHAR_MAX) @@ -308,15 +310,6 @@ struct lconv *localeconv(void) { return (void *)&posix_lconv; } -#ifdef CKB_C_STDLIB_MALLOC -#include "malloc_impl.h" -#else -void *malloc(size_t size) { return NULL; } -void free(void *ptr) {} -void *calloc(size_t nmemb, size_t size) { return NULL; } -void *realloc(void *ptr, size_t size) { return NULL; } -#endif - /* Copied from * https://github.com/bminor/musl/blob/46d1c7801bb509e1097e8fadbaf359367fa4ef0b/src/setjmp/riscv64/setjmp.S */ diff --git a/lualib/c-stdlib/src/malloc_impl.h b/lualib/c-stdlib/src/malloc_impl.h index 59f15f6..7b9e54c 100644 --- a/lualib/c-stdlib/src/malloc_impl.h +++ b/lualib/c-stdlib/src/malloc_impl.h @@ -1,6 +1,8 @@ #ifndef LUA_C_STDLIB_MALLOC_H_ #define LUA_C_STDLIB_MALLOC_H_ +#define CKB_MALLOC_DECLARATION_ONLY 1 + #include "ckb_syscalls.h" From a8bb211427c37cffd1c4daa83a8cd101bffc67e6 Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 12:35:10 +0800 Subject: [PATCH 10/18] fix multiple definitions --- lualib/c-stdlib/src/malloc_impl.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/lualib/c-stdlib/src/malloc_impl.h b/lualib/c-stdlib/src/malloc_impl.h index 7b9e54c..9231ca2 100644 --- a/lualib/c-stdlib/src/malloc_impl.h +++ b/lualib/c-stdlib/src/malloc_impl.h @@ -3,9 +3,6 @@ #define CKB_MALLOC_DECLARATION_ONLY 1 -#include "ckb_syscalls.h" - - #if defined(malloc) #undef malloc #endif From b52cb0235478c450a8f32f98a65bdf65eb6b412b Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 12:45:20 +0800 Subject: [PATCH 11/18] add correct printf with float support --- lua-loader/lua-loader.c | 1 - lualib/c-stdlib/src/impl.c | 1 + lualib/c-stdlib/src/printf_impl.h | 1034 +++++++++++++++++++++++++++++ 3 files changed, 1035 insertions(+), 1 deletion(-) create mode 100644 lualib/c-stdlib/src/printf_impl.h diff --git a/lua-loader/lua-loader.c b/lua-loader/lua-loader.c index 9aa2d68..84b2232 100644 --- a/lua-loader/lua-loader.c +++ b/lua-loader/lua-loader.c @@ -1,4 +1,3 @@ -#define CKB_C_STDLIB_PRINTF 1 #define CKB_MALLOC_DECLARATION_ONLY 1 #define lua_c diff --git a/lualib/c-stdlib/src/impl.c b/lualib/c-stdlib/src/impl.c index 12a1e0d..72b3e7f 100644 --- a/lualib/c-stdlib/src/impl.c +++ b/lualib/c-stdlib/src/impl.c @@ -8,6 +8,7 @@ #include #include +#include "printf_impl.h" #include "malloc_impl.h" #define CKB_SS (sizeof(size_t)) diff --git a/lualib/c-stdlib/src/printf_impl.h b/lualib/c-stdlib/src/printf_impl.h new file mode 100644 index 0000000..382e94f --- /dev/null +++ b/lualib/c-stdlib/src/printf_impl.h @@ -0,0 +1,1034 @@ +#ifndef LUA_C_STDLIB_PRINTF_H_ +#define LUA_C_STDLIB_PRINTF_H_ + +#undef CKB_C_STDLIB_PRINTF + +// Code copied from +// https://github.com/mpaland/printf/tree/d3b984684bb8a8bdc48cc7a1abecb93ce59bbe3e + +#include +#include +#include +#include + +/** + * Output a character to a custom device like UART, used by the printf() + * function This function is declared here only. You have to write your custom + * implementation somewhere \param character Character to output + */ +void _putchar(char character); + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro + * defines and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not + * counting the terminating null character + */ +#define printf printf_ +int printf_(const char *format, ...); + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING + * (V)SNPRINTF INSTEAD! \param buffer A pointer to the buffer where to store the + * formatted string. MUST be big enough to store the output! \param format A + * string that specifies the format of the output \return The number of + * characters that are WRITTEN into the buffer, not counting the terminating + * null character + */ +#define sprintf sprintf_ +int sprintf_(char *buffer, const char *format, ...); + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, + * including a terminating null character \param format A string that specifies + * the format of the output \param va A value identifying a variable arguments + * list \return The number of characters that COULD have been written into the + * buffer, not counting the terminating null character. A value equal or larger + * than count indicates truncation. Only when the returned value is non-negative + * and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char *buffer, size_t count, const char *format, ...); +int vsnprintf_(char *buffer, size_t count, const char *format, va_list va); + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not + * counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char *format, va_list va); + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() + * output \param out An output function which takes one character and an + * argument pointer \param arg An argument pointer for user data passed to + * output function \param format A string that specifies the format of the + * output \return The number of characters that are sent to the output function, + * not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void *arg), void *arg, + const char *format, ...); + +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for +// speed on +// embedded systems with a very limited resources. These routines are +// thread safe and reentrant! Use this instead of the bloated +// standard/newlib printf cause these use malloc for printf (and may not +// be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +// output function type +typedef void (*out_fct_type)(char character, void *buffer, size_t idx, + size_t maxlen); + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void *arg); + void *arg; +} out_fct_wrap_type; + +// internal buffer output +static inline void _out_buffer(char character, void *buffer, size_t idx, + size_t maxlen) { + if (idx < maxlen) { + ((char *)buffer)[idx] = character; + } +} + +// internal null output +static inline void _out_null(char character, void *buffer, size_t idx, + size_t maxlen) { + (void)character; + (void)buffer; + (void)idx; + (void)maxlen; +} + +// internal _putchar wrapper +static inline void _out_char(char character, void *buffer, size_t idx, + size_t maxlen) { + (void)buffer; + (void)idx; + (void)maxlen; + if (character) { + _putchar(character); + } +} + +// internal output function wrapper +static inline void _out_fct(char character, void *buffer, size_t idx, + size_t maxlen) { + (void)idx; + (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type *)buffer) + ->fct(character, ((out_fct_wrap_type *)buffer)->arg); + } +} + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by +// 'maxsize' +static inline unsigned int _strnlen_s(const char *str, size_t maxsize) { + const char *s; + for (s = str; *s && maxsize--; ++s) + ; + return (unsigned int)(s - str); +} + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) { return (ch >= '0') && (ch <= '9'); } + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char **str) { + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char *buffer, size_t idx, + size_t maxlen, const char *buf, size_t len, + unsigned int width, unsigned int flags) { + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx, + size_t maxlen, char *buf, size_t len, bool negative, + unsigned int base, unsigned int prec, + unsigned int width, unsigned int flags) { + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && + (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && + (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && + ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && + (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && + (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, + size_t maxlen, unsigned long value, bool negative, + unsigned long base, unsigned int prec, + unsigned int width, unsigned int flags) { + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 + ? '0' + digit + : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, + (unsigned int)base, prec, width, flags); +} + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, + size_t maxlen, unsigned long long value, + bool negative, unsigned long long base, + unsigned int prec, unsigned int width, + unsigned int flags) { + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 + ? '0' + digit + : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, + (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > +// PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, + double value, unsigned int prec, unsigned int width, + unsigned int flags); +#endif + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, + double value, unsigned int prec, unsigned int width, + unsigned int flags) { + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = {1, 10, 100, 1000, + 10000, 100000, 1000000, 10000000, + 100000000, 1000000000}; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, + (flags & FLAGS_PLUS) ? "fni+" : "fni", + (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which + // could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } else if (diff < 0.5) { + } else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by +// Martijn Jasperse +static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, + double value, unsigned int prec, unsigned int width, + unsigned int flags) { + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | + (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln + // around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see + // https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 + // characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of *significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, + flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = + _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, + expval < 0, 10, 0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) + out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, + const char *format, va_list va) { + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': + flags |= FLAGS_ZEROPAD; + format++; + n = 1U; + break; + case '-': + flags |= FLAGS_LEFT; + format++; + n = 1U; + break; + case '+': + flags |= FLAGS_PLUS; + format++; + n = 1U; + break; + case ' ': + flags |= FLAGS_SPACE; + format++; + n = 1U; + break; + case '#': + flags |= FLAGS_HASH; + format++; + n = 1U; + break; + default: + n = 0U; + break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l': + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h': + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't': + flags |= + (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j': + flags |= + (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z': + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default: + break; + } + + // evaluate specifier + switch (*format) { + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': + case 'o': + case 'b': { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } else if (*format == 'o') { + base = 8U; + } else if (*format == 'b') { + base = 2U; + } else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long( + out, buffer, idx, maxlen, + (unsigned long long)(value > 0 ? value : 0 - value), value < 0, + base, precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, + (unsigned long)(value > 0 ? value : 0 - value), + value < 0, base, precision, width, flags); + } else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) + : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) + : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, + (unsigned int)(value > 0 ? value : 0 - value), + value < 0, base, precision, width, flags); + } + } else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, + va_arg(va, unsigned long long), false, base, + precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), + false, base, precision, width, flags); + } else { + const unsigned int value = + (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) + : (flags & FLAGS_SHORT) + ? (unsigned short int)va_arg(va, unsigned int) + : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, + precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f': + case 'F': + if (*format == 'F') + flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, + width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g') || (*format == 'G')) + flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E') || (*format == 'G')) + flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, + width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c': { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's': { + const char *p = va_arg(va, char *); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p': { + width = sizeof(void *) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, + (uintptr_t)va_arg(va, void *), false, 16U, + precision, width, flags); + } else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, + (unsigned long)((uintptr_t)va_arg(va, void *)), false, + 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%': + out('%', buffer, idx++, maxlen); + format++; + break; + + default: + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char *format, ...) { + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + +int sprintf_(char *buffer, const char *format, ...) { + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + +int snprintf_(char *buffer, size_t count, const char *format, ...) { + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + +int vprintf_(const char *format, va_list va) { + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + +int vsnprintf_(char *buffer, size_t count, const char *format, va_list va) { + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + +int fctprintf(void (*out)(char character, void *arg), void *arg, + const char *format, ...) { + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = {out, arg}; + const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, + (size_t)-1, format, va); + va_end(va); + return ret; +} + +#endif From 21e0121d358360386c6edeb5f32b015ba3facb39 Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 13:23:17 +0800 Subject: [PATCH 12/18] correctly implement printf --- Makefile | 6 +++--- include/ckb-c-stdlib | 2 +- lua-loader/lua-loader.c | 1 + lualib/c-stdlib/src/printf_impl.h | 29 ++++++++++++++++++++++++++++- tests/test_cases/dylibtest.c | 4 +++- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index b6ce695..57866ab 100644 --- a/Makefile +++ b/Makefile @@ -27,13 +27,13 @@ lualib/liblua.a: make -C lualib liblua.a build/dylibtest: tests/test_cases/dylibtest.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(shell $(CC) --print-search-dirs | sed -n '/install:/p' | sed 's/install:\s*//g')libgcc.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< lualib/liblua.a $(shell $(CC) --print-search-dirs | sed -n '/install:/p' | sed 's/install:\s*//g')libgcc.a build/dylibexample: examples/dylib.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(shell $(CC) --print-search-dirs | sed -n '/install:/p' | sed 's/install:\s*//g')libgcc.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< lualib/liblua.a $(shell $(CC) --print-search-dirs | sed -n '/install:/p' | sed 's/install:\s*//g')libgcc.a build/spawnexample: examples/spawn.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(shell $(CC) --print-search-dirs | sed -n '/install:/p' | sed 's/install:\s*//g')libgcc.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< lualib/liblua.a $(shell $(CC) --print-search-dirs | sed -n '/install:/p' | sed 's/install:\s*//g')libgcc.a build/lua-loader.o: lua-loader/lua-loader.c $(CC) -c $(CFLAGS) -o $@ $< diff --git a/include/ckb-c-stdlib b/include/ckb-c-stdlib index aba7f2b..dffd9e6 160000 --- a/include/ckb-c-stdlib +++ b/include/ckb-c-stdlib @@ -1 +1 @@ -Subproject commit aba7f2bf1b2ff1b4a60a5cd0988215bd4eca3431 +Subproject commit dffd9e66dbba4de8213e8b8f83112cd62469269b diff --git a/lua-loader/lua-loader.c b/lua-loader/lua-loader.c index 84b2232..a8805ce 100644 --- a/lua-loader/lua-loader.c +++ b/lua-loader/lua-loader.c @@ -1,4 +1,5 @@ #define CKB_MALLOC_DECLARATION_ONLY 1 +#define CKB_PRINTF_DECLARATION_ONLY 1 #define lua_c diff --git a/lualib/c-stdlib/src/printf_impl.h b/lualib/c-stdlib/src/printf_impl.h index 382e94f..9843313 100644 --- a/lualib/c-stdlib/src/printf_impl.h +++ b/lualib/c-stdlib/src/printf_impl.h @@ -2,6 +2,7 @@ #define LUA_C_STDLIB_PRINTF_H_ #undef CKB_C_STDLIB_PRINTF +#define CKB_MALLOC_DECLARATION_ONLY 1 // Code copied from // https://github.com/mpaland/printf/tree/d3b984684bb8a8bdc48cc7a1abecb93ce59bbe3e @@ -27,7 +28,6 @@ void _putchar(char character); * \return The number of characters that are written into the array, not * counting the terminating null character */ -#define printf printf_ int printf_(const char *format, ...); /** @@ -1031,4 +1031,31 @@ int fctprintf(void (*out)(char character, void *arg), void *arg, return ret; } +// Default PRINTF_BUFFER_SIZE +#ifndef CKB_C_STDLIB_PRINTF_BUFFER_SIZE +#define CKB_C_STDLIB_PRINTF_BUFFER_SIZE 256 +#endif +// syscall +int ckb_debug(const char *s); + +int printf(const char *format, ...) { + static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; + va_list va; + va_start(va, format); + int ret = vsnprintf_(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); + va_end(va); + ckb_debug(buf); + return ret; +} + +int ckb_printf(const char *format, ...) { + static char buf[CKB_C_STDLIB_PRINTF_BUFFER_SIZE]; + va_list va; + va_start(va, format); + int ret = vsnprintf_(buf, CKB_C_STDLIB_PRINTF_BUFFER_SIZE, format, va); + va_end(va); + ckb_debug(buf); + return ret; +} + #endif diff --git a/tests/test_cases/dylibtest.c b/tests/test_cases/dylibtest.c index a9e9afa..aba2f5d 100644 --- a/tests/test_cases/dylibtest.c +++ b/tests/test_cases/dylibtest.c @@ -1,4 +1,6 @@ -#define CKB_C_STDLIB_PRINTF +#define CKB_MALLOC_DECLARATION_ONLY 1 +#define CKB_PRINTF_DECLARATION_ONLY 1 + #include #include "blake2b.h" From 711bebe7463398b252a558e58b9aa1aa10bdfe42 Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 13:36:25 +0800 Subject: [PATCH 13/18] fix implicit declaration of function 'malloc_config' --- tests/ckb-c-stdlib-tests/test_malloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ckb-c-stdlib-tests/test_malloc.c b/tests/ckb-c-stdlib-tests/test_malloc.c index 227df55..15ff9f3 100644 --- a/tests/ckb-c-stdlib-tests/test_malloc.c +++ b/tests/ckb-c-stdlib-tests/test_malloc.c @@ -10,6 +10,7 @@ #include "ckb_syscalls.h" #include "helper.h" +extern void malloc_config(uintptr_t min, uintptr_t max); #define COUNT_OF(a) (sizeof(a) / sizeof(a[0])) void check_heap(void) { From 48069fd1e66e2b433d151850b4a7eb44ab1fe05f Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 14:56:08 +0800 Subject: [PATCH 14/18] fix malloc test --- tests/ckb-c-stdlib-tests/Makefile | 2 +- tests/ckb-c-stdlib-tests/test_malloc.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/ckb-c-stdlib-tests/Makefile b/tests/ckb-c-stdlib-tests/Makefile index e7adf2e..4464442 100644 --- a/tests/ckb-c-stdlib-tests/Makefile +++ b/tests/ckb-c-stdlib-tests/Makefile @@ -2,7 +2,7 @@ TARGET := riscv64-unknown-linux-gnu CC := $(TARGET)-gcc LD := $(TARGET)-gcc OBJCOPY := $(TARGET)-objcopy -CFLAGS := -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I ../../include/ckb-c-stdlib -I ../../include/ckb-c-stdlib/libc -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g +CFLAGS := -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I ../../lualib/c-stdlib -I ../../lualib/c-stdlib/src -I ../../include/ckb-c-stdlib -I ../../include/ckb-c-stdlib/libc -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g LDFLAGS := -nostartfiles -Wl,-static -Wl,--gc-sections # docker pull nervos/ckb-riscv-gnu-toolchain:gnu-bionic-20191012 diff --git a/tests/ckb-c-stdlib-tests/test_malloc.c b/tests/ckb-c-stdlib-tests/test_malloc.c index 15ff9f3..40ba3d2 100644 --- a/tests/ckb-c-stdlib-tests/test_malloc.c +++ b/tests/ckb-c-stdlib-tests/test_malloc.c @@ -1,16 +1,15 @@ -#define CKB_C_STDLIB_PRINTF -#define CKB_C_STDLIB_MALLOC -#define PRINTF_DISABLE_SUPPORT_FLOAT +#define CKB_MALLOC_DECLARATION_ONLY 1 +#define CKB_C_STDLIB_PRINTF 1 #include #include #include #include +#include "malloc_impl.h" #include "ckb_syscalls.h" #include "helper.h" -extern void malloc_config(uintptr_t min, uintptr_t max); #define COUNT_OF(a) (sizeof(a) / sizeof(a[0])) void check_heap(void) { From c41aec1c41dd848e30e7515caa94514a2d17644b Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 15:26:27 +0800 Subject: [PATCH 15/18] move all c stdlib files to c-stdlib directory --- lualib/Makefile | 2 +- lualib/{ => c-stdlib}/mocked_math.h | 0 lualib/{ => c-stdlib}/mocked_stdio.h | 6 +----- lualib/{ => c-stdlib}/mocked_string.h | 0 lualib/c-stdlib/src/impl.c | 2 ++ lualib/{ => c-stdlib/src}/math_log.c | 0 lualib/{ => c-stdlib/src}/math_pow.c | 0 lualib/{ => c-stdlib/src}/math_private.h | 0 lualib/{ => c-stdlib/src}/mocked_math.c | 2 +- lualib/{ => c-stdlib/src}/mocked_stdio.c | 12 +----------- 10 files changed, 6 insertions(+), 18 deletions(-) rename lualib/{ => c-stdlib}/mocked_math.h (100%) rename lualib/{ => c-stdlib}/mocked_stdio.h (94%) rename lualib/{ => c-stdlib}/mocked_string.h (100%) rename lualib/{ => c-stdlib/src}/math_log.c (100%) rename lualib/{ => c-stdlib/src}/math_pow.c (100%) rename lualib/{ => c-stdlib/src}/math_private.h (100%) rename lualib/{ => c-stdlib/src}/mocked_math.c (98%) rename lualib/{ => c-stdlib/src}/mocked_stdio.c (97%) diff --git a/lualib/Makefile b/lualib/Makefile index 88ea838..267ee17 100644 --- a/lualib/Makefile +++ b/lualib/Makefile @@ -37,7 +37,7 @@ PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix LUA_A= liblua.a CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o -LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o lstrlib.o ltablib.o lutf8lib.o linit.o mocked_stdio.o mocked_math.o stdlib.o +LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o lstrlib.o ltablib.o lutf8lib.o linit.o stdlib.o BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) LUA_T= lua diff --git a/lualib/mocked_math.h b/lualib/c-stdlib/mocked_math.h similarity index 100% rename from lualib/mocked_math.h rename to lualib/c-stdlib/mocked_math.h diff --git a/lualib/mocked_stdio.h b/lualib/c-stdlib/mocked_stdio.h similarity index 94% rename from lualib/mocked_stdio.h rename to lualib/c-stdlib/mocked_stdio.h index e77a974..7133fb0 100644 --- a/lualib/mocked_stdio.h +++ b/lualib/c-stdlib/mocked_stdio.h @@ -5,7 +5,7 @@ #include #include -#include "../include/ckb_cell_fs.h" +#include "../../include/ckb_cell_fs.h" #define BUFSIZ 512 #define EOF (-1) @@ -53,15 +53,11 @@ int sprintf(char *__s, const char *__format, ...); int vfprintf(FILE *__s, const char *__format, ...); -int vprintf(const char *__format, ...); - int vsprintf(char *__s, const char *__format, ...); int snprintf(char *__s, size_t __maxlen, const char *__format, ...); int snprintf_(char *__s, size_t __maxlen, const char *__format, ...); -int vsnprintf(char *__s, size_t __maxlen, const char *__format, ...); - int fscanf(FILE *__stream, const char *__format, ...); int scanf(const char *__format, ...); diff --git a/lualib/mocked_string.h b/lualib/c-stdlib/mocked_string.h similarity index 100% rename from lualib/mocked_string.h rename to lualib/c-stdlib/mocked_string.h diff --git a/lualib/c-stdlib/src/impl.c b/lualib/c-stdlib/src/impl.c index 72b3e7f..e37f1e2 100644 --- a/lualib/c-stdlib/src/impl.c +++ b/lualib/c-stdlib/src/impl.c @@ -10,6 +10,8 @@ #include "printf_impl.h" #include "malloc_impl.h" +#include "mocked_stdio.c" +#include "mocked_math.c" #define CKB_SS (sizeof(size_t)) #define CKB_ALIGN (sizeof(size_t) - 1) diff --git a/lualib/math_log.c b/lualib/c-stdlib/src/math_log.c similarity index 100% rename from lualib/math_log.c rename to lualib/c-stdlib/src/math_log.c diff --git a/lualib/math_pow.c b/lualib/c-stdlib/src/math_pow.c similarity index 100% rename from lualib/math_pow.c rename to lualib/c-stdlib/src/math_pow.c diff --git a/lualib/math_private.h b/lualib/c-stdlib/src/math_private.h similarity index 100% rename from lualib/math_private.h rename to lualib/c-stdlib/src/math_private.h diff --git a/lualib/mocked_math.c b/lualib/c-stdlib/src/mocked_math.c similarity index 98% rename from lualib/mocked_math.c rename to lualib/c-stdlib/src/mocked_math.c index d3f6302..55d4af5 100644 --- a/lualib/mocked_math.c +++ b/lualib/c-stdlib/src/mocked_math.c @@ -1,4 +1,4 @@ -#include "mocked_math.h" +#include "../mocked_math.h" #include #include "math_pow.c" diff --git a/lualib/mocked_stdio.c b/lualib/c-stdlib/src/mocked_stdio.c similarity index 97% rename from lualib/mocked_stdio.c rename to lualib/c-stdlib/src/mocked_stdio.c index d06d4c2..f37d4b7 100644 --- a/lualib/mocked_stdio.c +++ b/lualib/c-stdlib/src/mocked_stdio.c @@ -1,5 +1,4 @@ - -#include "mocked_stdio.h" +#include "../mocked_stdio.h" #include #include @@ -151,19 +150,10 @@ int fprintf(FILE *__stream, const char *__format, ...) { return 0; } -int sprintf(char *__s, const char *__format, ...) { - NOT_IMPL(sprintf); - return 0; -} - int vfprintf(FILE *__s, const char *__format, ...) { NOT_IMPL(vfprintf); return 0; } -int vprintf(const char *__format, ...) { - NOT_IMPL(vprintf); - return 0; -} int vsprintf(char *__s, const char *__format, ...) { NOT_IMPL(vsprintf); return 0; From 42d65d8629fe6d8df21cd0058363d48e4c48daee Mon Sep 17 00:00:00 2001 From: YI Date: Thu, 7 Sep 2023 15:40:47 +0800 Subject: [PATCH 16/18] make c-stdlib file names more consistent --- lualib/c-stdlib/mocked_math.h | 87 ------------------ lualib/c-stdlib/mocked_string.h | 0 lualib/c-stdlib/my_math.h | 90 ++++++++++++------- .../c-stdlib/{mocked_stdio.h => my_stdio.h} | 0 lualib/c-stdlib/src/impl.c | 4 +- .../src/{mocked_math.c => mocked_math_impl.h} | 2 +- .../{mocked_stdio.c => mocked_stdio_impl.h} | 2 +- lualib/lauxlib.c | 2 +- lualib/lauxlib.h | 2 +- lualib/lgc.c | 2 +- lualib/liolib.c | 2 +- lualib/lmathlib.c | 2 +- lualib/loadlib.c | 2 +- lualib/lobject.c | 2 +- lualib/lstrlib.c | 2 +- lualib/lua.c | 2 +- lualib/luac.c | 2 +- lualib/lvm.c | 2 +- 18 files changed, 72 insertions(+), 135 deletions(-) delete mode 100644 lualib/c-stdlib/mocked_math.h delete mode 100644 lualib/c-stdlib/mocked_string.h rename lualib/c-stdlib/{mocked_stdio.h => my_stdio.h} (100%) rename lualib/c-stdlib/src/{mocked_math.c => mocked_math_impl.h} (98%) rename lualib/c-stdlib/src/{mocked_stdio.c => mocked_stdio_impl.h} (99%) diff --git a/lualib/c-stdlib/mocked_math.h b/lualib/c-stdlib/mocked_math.h deleted file mode 100644 index 43b25d3..0000000 --- a/lualib/c-stdlib/mocked_math.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifdef __cplusplus -extern "C" { -#endif - -/* fp_force_eval ensures that the input value is computed when that's - otherwise unused. To prevent the constant folding of the input - expression, an additional fp_barrier may be needed or a compilation - mode that does so (e.g. -frounding-math in gcc). Then it can be - used to evaluate an expression for its fenv side-effects only. */ - -#ifndef fp_force_evalf -#define fp_force_evalf fp_force_evalf -static inline void fp_force_evalf(float x) { - volatile float y; - y = x; - (void)y; -} -#endif - -#ifndef fp_force_eval -#define fp_force_eval fp_force_eval -static inline void fp_force_eval(double x) { - volatile double y; - y = x; - (void)y; -} -#endif - -#ifndef fp_force_evall -#define fp_force_evall fp_force_evall -static inline void fp_force_evall(long double x) { - volatile long double y; - y = x; - (void)y; -} -#endif - -#define FORCE_EVAL(x) \ - do { \ - if (sizeof(x) == sizeof(float)) { \ - fp_force_evalf(x); \ - } else if (sizeof(x) == sizeof(double)) { \ - fp_force_eval(x); \ - } else { \ - fp_force_evall(x); \ - } \ - } while (0) - -double acos(double); - -double asin(double); - -double atan2(double, double); - -double cos(double); - -double cosh(double); - -double exp(double); - -double fabs(double); - -double log(double); - -double log2(double); - -double log10(double); - -double pow(double, double); - -double sin(double); - -double sinh(double); - -double sqrt(double); - -double tan(double); - -double tanh(double); - -double scalbn(double, int); - -double ldexp(double, int); - -#ifdef __cplusplus -} -#endif diff --git a/lualib/c-stdlib/mocked_string.h b/lualib/c-stdlib/mocked_string.h deleted file mode 100644 index e69de29..0000000 diff --git a/lualib/c-stdlib/my_math.h b/lualib/c-stdlib/my_math.h index 9bc8f7f..43b25d3 100644 --- a/lualib/c-stdlib/my_math.h +++ b/lualib/c-stdlib/my_math.h @@ -1,8 +1,3 @@ -#ifndef LUA_C_STDLIB_MATH_H_ -#define LUA_C_STDLIB_MATH_H_ - -#define DBL_MAX 1.79769313486231570815e+308 - #ifdef __cplusplus extern "C" { #endif @@ -15,49 +10,78 @@ extern "C" { #ifndef fp_force_evalf #define fp_force_evalf fp_force_evalf -static inline void fp_force_evalf(float x) -{ - volatile float y; - y = x; - (void)y; +static inline void fp_force_evalf(float x) { + volatile float y; + y = x; + (void)y; } #endif #ifndef fp_force_eval #define fp_force_eval fp_force_eval -static inline void fp_force_eval(double x) -{ - volatile double y; - y = x; - (void)y; +static inline void fp_force_eval(double x) { + volatile double y; + y = x; + (void)y; } #endif #ifndef fp_force_evall #define fp_force_evall fp_force_evall -static inline void fp_force_evall(long double x) -{ - volatile long double y; - y = x; - (void)y; +static inline void fp_force_evall(long double x) { + volatile long double y; + y = x; + (void)y; } #endif -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - fp_force_evalf(x); \ - } else if (sizeof(x) == sizeof(double)) { \ - fp_force_eval(x); \ - } else { \ - fp_force_evall(x); \ - } \ -} while(0) +#define FORCE_EVAL(x) \ + do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ + } while (0) + +double acos(double); + +double asin(double); + +double atan2(double, double); + +double cos(double); + +double cosh(double); + +double exp(double); + +double fabs(double); + +double log(double); + +double log2(double); -double fmod(double, double); -double frexp(double, int *); +double log10(double); + +double pow(double, double); + +double sin(double); + +double sinh(double); + +double sqrt(double); + +double tan(double); + +double tanh(double); + +double scalbn(double, int); + +double ldexp(double, int); #ifdef __cplusplus } #endif - -#endif diff --git a/lualib/c-stdlib/mocked_stdio.h b/lualib/c-stdlib/my_stdio.h similarity index 100% rename from lualib/c-stdlib/mocked_stdio.h rename to lualib/c-stdlib/my_stdio.h diff --git a/lualib/c-stdlib/src/impl.c b/lualib/c-stdlib/src/impl.c index e37f1e2..0ec96fc 100644 --- a/lualib/c-stdlib/src/impl.c +++ b/lualib/c-stdlib/src/impl.c @@ -10,8 +10,8 @@ #include "printf_impl.h" #include "malloc_impl.h" -#include "mocked_stdio.c" -#include "mocked_math.c" +#include "mocked_stdio_impl.h" +#include "mocked_math_impl.h" #define CKB_SS (sizeof(size_t)) #define CKB_ALIGN (sizeof(size_t) - 1) diff --git a/lualib/c-stdlib/src/mocked_math.c b/lualib/c-stdlib/src/mocked_math_impl.h similarity index 98% rename from lualib/c-stdlib/src/mocked_math.c rename to lualib/c-stdlib/src/mocked_math_impl.h index 55d4af5..f0c9f08 100644 --- a/lualib/c-stdlib/src/mocked_math.c +++ b/lualib/c-stdlib/src/mocked_math_impl.h @@ -1,4 +1,4 @@ -#include "../mocked_math.h" +#include "../my_math.h" #include #include "math_pow.c" diff --git a/lualib/c-stdlib/src/mocked_stdio.c b/lualib/c-stdlib/src/mocked_stdio_impl.h similarity index 99% rename from lualib/c-stdlib/src/mocked_stdio.c rename to lualib/c-stdlib/src/mocked_stdio_impl.h index f37d4b7..6c6d0ce 100644 --- a/lualib/c-stdlib/src/mocked_stdio.c +++ b/lualib/c-stdlib/src/mocked_stdio_impl.h @@ -1,4 +1,4 @@ -#include "../mocked_stdio.h" +#include "../my_stdio.h" #include #include diff --git a/lualib/lauxlib.c b/lualib/lauxlib.c index 804e70d..6aa1786 100644 --- a/lualib/lauxlib.c +++ b/lualib/lauxlib.c @@ -11,7 +11,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lprefix.h" diff --git a/lualib/lauxlib.h b/lualib/lauxlib.h index 02d1593..108b3f0 100644 --- a/lualib/lauxlib.h +++ b/lualib/lauxlib.h @@ -8,7 +8,7 @@ #define lauxlib_h #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lua.h" #include "luaconf.h" diff --git a/lualib/lgc.c b/lualib/lgc.c index 0dee526..7cb05b7 100644 --- a/lualib/lgc.c +++ b/lualib/lgc.c @@ -10,7 +10,7 @@ #include "lgc.h" #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "ldebug.h" #include "ldo.h" diff --git a/lualib/liolib.c b/lualib/liolib.c index 0a2337d..f321890 100644 --- a/lualib/liolib.c +++ b/lualib/liolib.c @@ -12,7 +12,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lauxlib.h" #include "lprefix.h" diff --git a/lualib/lmathlib.c b/lualib/lmathlib.c index d3197c5..3fc8498 100644 --- a/lualib/lmathlib.c +++ b/lualib/lmathlib.c @@ -12,7 +12,7 @@ #include -#include "mocked_math.h" +#include "my_math.h" #include diff --git a/lualib/loadlib.c b/lualib/loadlib.c index 39672d5..2a2835e 100644 --- a/lualib/loadlib.c +++ b/lualib/loadlib.c @@ -13,7 +13,7 @@ #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lauxlib.h" #include "lprefix.h" diff --git a/lualib/lobject.c b/lualib/lobject.c index 0a3a3b8..d95d916 100644 --- a/lualib/lobject.c +++ b/lualib/lobject.c @@ -14,7 +14,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lctype.h" #include "ldebug.h" diff --git a/lualib/lstrlib.c b/lualib/lstrlib.c index 9ab75f9..b8ab5e6 100644 --- a/lualib/lstrlib.c +++ b/lualib/lstrlib.c @@ -15,7 +15,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lauxlib.h" #include "lprefix.h" diff --git a/lualib/lua.c b/lualib/lua.c index ba0368f..1097d53 100644 --- a/lualib/lua.c +++ b/lualib/lua.c @@ -11,7 +11,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lauxlib.h" #include "lprefix.h" diff --git a/lualib/luac.c b/lualib/luac.c index 293e763..c308e45 100644 --- a/lualib/luac.c +++ b/lualib/luac.c @@ -11,7 +11,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "lauxlib.h" #include "ldebug.h" diff --git a/lualib/lvm.c b/lualib/lvm.c index af3697d..ce5defe 100644 --- a/lualib/lvm.c +++ b/lualib/lvm.c @@ -14,7 +14,7 @@ #include #include #include -#include "mocked_stdio.h" +#include "my_stdio.h" #include "ldebug.h" #include "ldo.h" From f8edde030d55572d836f8f8c359b980c3dea6646 Mon Sep 17 00:00:00 2001 From: YI Date: Mon, 11 Sep 2023 10:07:28 +0800 Subject: [PATCH 17/18] change ckb-c-stdlib submodule url --- .gitmodules | 2 +- include/ckb-c-stdlib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index f12c637..42e95e5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "include/ckb-c-stdlib"] path = include/ckb-c-stdlib - url = https://github.com/contrun/ckb-c-stdlib.git + url = https://github.com/nervosnetwork/ckb-c-stdlib.git diff --git a/include/ckb-c-stdlib b/include/ckb-c-stdlib index dffd9e6..bdc87e0 160000 --- a/include/ckb-c-stdlib +++ b/include/ckb-c-stdlib @@ -1 +1 @@ -Subproject commit dffd9e66dbba4de8213e8b8f83112cd62469269b +Subproject commit bdc87e064b98a40df7ccc0abc23cd3d60b7da475 From 95166069a5b02011e4c6c7f4dda8500415db4d0f Mon Sep 17 00:00:00 2001 From: YI Date: Mon, 11 Sep 2023 10:28:54 +0800 Subject: [PATCH 18/18] add comments of why __ISO_C_VISIBLE=1999 is needed --- Makefile | 1 + lualib/Makefile | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 57866ab..492b167 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ CC := $(TARGET)-gcc LD := $(TARGET)-gcc OBJCOPY := $(TARGET)-objcopy +# See comments in lualib/Makefile for why __ISO_C_VISIBLE=1999 is needed CFLAGS := -D__ISO_C_VISIBLE=1999 -fPIC -O3 -fno-builtin -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I lualib -I lualib/c-stdlib -I include/ckb-c-stdlib -I include/ckb-c-stdlib/libc -I include/ckb-c-stdlib/molecule -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -Wno-error=maybe-uninitialized -g LDFLAGS := -nostdlib -nostartfiles -fno-builtin -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections diff --git a/lualib/Makefile b/lualib/Makefile index 267ee17..e39edee 100644 --- a/lualib/Makefile +++ b/lualib/Makefile @@ -10,7 +10,11 @@ CC=riscv64-unknown-linux-gnu-gcc # -ULUA_USE_LINUX -ULUA_USE_POSIX to make lua dependencies minimal, # otherwise, we may unable to find various platform dependent symbols, e.g. # setsignal. -CFLAGS= -Ic-stdlib -D__ISO_C_VISIBLE=1999 -O3 -Wall -Wextra -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) +# __ISO_C_VISIBLE=1999 is needed because lua requires LLONG_MAX to be defined. +# And if __ISO_C_VISIBLE=1999 then LLONG_MAX is defined in ckb-c-stdlib +# See https://github.com/nervosnetwork/ckb-c-stdlib/blob/efe1fe6b3cdda12e248e25664f5c04cbf7876265/libc/limits.h#L94 +# and https://github.com/nervosnetwork/ckb-lua/blob/b71d44288e8fb085074d3af056b359b8c6c22afa/lualib/luaconf.h#L502 +CFLAGS= -Ic-stdlib -O3 -Wall -Wextra -D__ISO_C_VISIBLE=1999 -DLUA_COMPAT_5_3 -ULUA_USE_LINUX -ULUA_USE_POSIX $(SYSCFLAGS) $(MYCFLAGS) LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) LIBS= -lm $(SYSLIBS) $(MYLIBS)