Compare commits
10 Commits
5762484550
...
785070798c
| Author | SHA1 | Date | |
|---|---|---|---|
| 785070798c | |||
| ebb78a4802 | |||
| d0cd2c4697 | |||
| a99724e934 | |||
| 87b34d57be | |||
| 4c77ce8fe3 | |||
| 9642630dd1 | |||
| d8b9e97e07 | |||
| ecab74bb22 | |||
| bfa33b3778 |
@@ -10,6 +10,10 @@ include(CheckIPOSupported)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckSymbolExists)
|
||||
|
||||
# Project settings
|
||||
option(BH_PLATFORM_THREADS "Enable multithreading support" TRUE)
|
||||
option(BH_BIGINT_LONG "Use bigger internal units for big integer calculations" TRUE)
|
||||
|
||||
# Check for IPO/LTO
|
||||
check_ipo_supported(RESULT supported)
|
||||
|
||||
@@ -31,6 +35,7 @@ set(BH_SOURCE
|
||||
src/thread.c
|
||||
src/io.c
|
||||
src/deflate.c
|
||||
src/bigint.c
|
||||
)
|
||||
|
||||
set(BH_HEADER
|
||||
@@ -43,6 +48,7 @@ set(BH_HEADER
|
||||
include/bh/thread.h
|
||||
include/bh/io.h
|
||||
include/bh/deflate.h
|
||||
include/bh/bigint.h
|
||||
)
|
||||
|
||||
set(BH_INCLUDE_DIRS
|
||||
@@ -55,6 +61,7 @@ set(BH_INCLUDE_DIRS
|
||||
if(WIN32)
|
||||
message(STATUS "Platform - Win32")
|
||||
set(BH_PLATFORM_WIN TRUE)
|
||||
option(BH_THREADS_WINXP "Enable threading support for Windows XP" FALSE)
|
||||
|
||||
# Add platform dependent files
|
||||
list(APPEND BH_SOURCE
|
||||
@@ -62,8 +69,11 @@ if(WIN32)
|
||||
)
|
||||
|
||||
# Check multithreading support
|
||||
check_symbol_exists(_beginthread process.h BH_USE_WINTHREAD)
|
||||
if(BH_USE_WINTHREAD)
|
||||
if(BH_PLATFORM_THREADS)
|
||||
check_symbol_exists(_beginthread process.h BH_PLATFORM_THREADS)
|
||||
endif()
|
||||
|
||||
if(BH_PLATFORM_THREADS)
|
||||
message(STATUS "Multithreading enabled")
|
||||
list(APPEND BH_SOURCE
|
||||
src/thread_win.c
|
||||
@@ -75,7 +85,7 @@ if(WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BH_NO_WINXP)
|
||||
if(NOT BH_THREADS_WINXP)
|
||||
add_definitions(-D_WIN32_WINNT=_WIN32_WINNT_VISTA -DWINVER=_WIN32_WINNT_VISTA)
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
@@ -88,8 +98,11 @@ elseif(UNIX)
|
||||
)
|
||||
|
||||
# Check multithreading support
|
||||
check_include_file(pthread.h BH_USE_PTHREAD)
|
||||
if(BH_USE_PTHREAD)
|
||||
if(BH_PLATFORM_THREADS)
|
||||
check_include_file(pthread.h BH_PLATFORM_THREADS)
|
||||
endif()
|
||||
|
||||
if(BH_PLATFORM_THREADS)
|
||||
message(STATUS "Multithreading enabled")
|
||||
list(APPEND BH_SOURCE
|
||||
src/thread_posix.c
|
||||
@@ -111,11 +124,19 @@ endif()
|
||||
|
||||
# Configure library
|
||||
configure_file(include/bh/config.in include/bh/config.h)
|
||||
configure_file(include/bh/internal/config.in include/bh/internal/config.h)
|
||||
|
||||
# Library
|
||||
add_library(bhlib STATIC ${BH_SOURCE} ${BH_HEADER})
|
||||
target_include_directories(bhlib PUBLIC ${BH_INCLUDE_DIRS})
|
||||
|
||||
# Enable warnings and pedantics
|
||||
if(MSVC)
|
||||
target_compile_options(bhlib PRIVATE /W4)
|
||||
else()
|
||||
target_compile_options(bhlib PRIVATE -Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
# Runtime definition
|
||||
add_executable(main
|
||||
main.c
|
||||
|
||||
150
include/bh/bigint.h
Normal file
150
include/bh/bigint.h
Normal file
@@ -0,0 +1,150 @@
|
||||
#ifndef BH_BIGINT_H
|
||||
#define BH_BIGINT_H
|
||||
|
||||
#include "bh.h"
|
||||
|
||||
typedef struct bh_bigint_s bh_bigint_t;
|
||||
|
||||
bh_bigint_t *bh_bigint_new(void);
|
||||
void bh_bigint_free(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_block(void);
|
||||
|
||||
int bh_bigint_clear(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_set(bh_bigint_t *to,
|
||||
bh_bigint_t *from);
|
||||
|
||||
int bh_bigint_set_int(bh_bigint_t *to,
|
||||
int from);
|
||||
|
||||
int bh_bigint_set_uint(bh_bigint_t *to,
|
||||
unsigned int from);
|
||||
|
||||
int bh_bigint_get_int(bh_bigint_t *bigint);
|
||||
|
||||
unsigned int bh_bigint_get_uint(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_set_int8(bh_bigint_t *to,
|
||||
bh_int8_t from);
|
||||
|
||||
int bh_bigint_set_uint8(bh_bigint_t *to,
|
||||
bh_uint8_t from);
|
||||
|
||||
bh_int8_t bh_bigint_get_int8(bh_bigint_t *bigint);
|
||||
|
||||
bh_uint8_t bh_bigint_get_uint8(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_set_int16(bh_bigint_t *to,
|
||||
bh_int16_t from);
|
||||
|
||||
int bh_bigint_set_uint16(bh_bigint_t *to,
|
||||
bh_uint16_t from);
|
||||
|
||||
bh_int16_t bh_bigint_get_int16(bh_bigint_t *bigint);
|
||||
|
||||
bh_uint16_t bh_bigint_get_uint16(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_set_int32(bh_bigint_t *to,
|
||||
bh_int32_t from);
|
||||
|
||||
int bh_bigint_set_uint32(bh_bigint_t *to,
|
||||
bh_uint32_t from);
|
||||
|
||||
bh_int32_t bh_bigint_get_int32(bh_bigint_t *bigint);
|
||||
|
||||
bh_uint32_t bh_bigint_get_uint32(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_set_int64(bh_bigint_t *to,
|
||||
bh_int64_t from);
|
||||
|
||||
int bh_bigint_set_uint64(bh_bigint_t *to,
|
||||
bh_uint64_t from);
|
||||
|
||||
bh_int64_t bh_bigint_get_int64(bh_bigint_t *bigint);
|
||||
|
||||
bh_uint64_t bh_bigint_get_uint64(bh_bigint_t *bigint);
|
||||
|
||||
size_t bh_bigint_capacity(bh_bigint_t *bigint);
|
||||
|
||||
size_t bh_bigint_length(bh_bigint_t *bigint);
|
||||
|
||||
int bh_bigint_reserve(bh_bigint_t *bigint,
|
||||
size_t size);
|
||||
|
||||
int bh_bigint_add(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_sub(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_mul(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_mul_digit(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_int16_t right);
|
||||
|
||||
int bh_bigint_pow(bh_bigint_t *to,
|
||||
bh_bigint_t *from,
|
||||
bh_uint32_t power);
|
||||
|
||||
int bh_bigint_pow10(bh_bigint_t *to,
|
||||
bh_uint32_t power);
|
||||
|
||||
int bh_bigint_powm(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right,
|
||||
bh_bigint_t *mod);
|
||||
|
||||
int bh_bigint_divmod(bh_bigint_t *quotient,
|
||||
bh_bigint_t *remainder,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_div(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_mod(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_lsh(bh_bigint_t *to,
|
||||
bh_bigint_t *from,
|
||||
bh_uint32_t shift);
|
||||
|
||||
int bh_bigint_rsh(bh_bigint_t *to,
|
||||
bh_bigint_t *from,
|
||||
bh_uint32_t shift);
|
||||
|
||||
int bh_bigint_or(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_and(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_xor(bh_bigint_t *to,
|
||||
bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_negate(bh_bigint_t *to,
|
||||
bh_bigint_t *from);
|
||||
|
||||
int bh_bigint_equal(bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_equal_mod(bh_bigint_t *left,
|
||||
bh_bigint_t *right);
|
||||
|
||||
int bh_bigint_is_negative(bh_bigint_t *bigint);
|
||||
int bh_bigint_is_zero(bh_bigint_t *bigint);
|
||||
int bh_bigint_is_error(bh_bigint_t *bigint);
|
||||
size_t bh_bigint_log2(bh_bigint_t *bigint);
|
||||
|
||||
#endif /* BH_BIGINT_H */
|
||||
@@ -1,14 +1,13 @@
|
||||
#ifndef BH_BUFFER_H
|
||||
#define BH_BUFFER_H
|
||||
|
||||
#include "bh.h"
|
||||
#include "io.h"
|
||||
|
||||
typedef struct bh_buffer_s bh_buffer_t;
|
||||
|
||||
bh_buffer_t *bh_buffer_new(void);
|
||||
|
||||
void bh_buffer_free(bh_buffer_t *buffer);
|
||||
|
||||
const char *bh_buffer_data(bh_buffer_t *buffer);
|
||||
|
||||
void bh_buffer_set_data(bh_buffer_t *buffer,
|
||||
@@ -20,34 +19,8 @@ size_t bh_buffer_capacity(bh_buffer_t *buffer);
|
||||
int bh_buffer_reserve(bh_buffer_t *buffer,
|
||||
size_t size);
|
||||
|
||||
int bh_buffer_open_base(bh_buffer_t *buffer,
|
||||
int mode);
|
||||
|
||||
void bh_buffer_close_base(bh_buffer_t *buffer);
|
||||
|
||||
int bh_buffer_is_open_base(bh_buffer_t *buffer);
|
||||
|
||||
size_t bh_buffer_read_base(bh_buffer_t *buffer,
|
||||
char *data,
|
||||
size_t size);
|
||||
|
||||
size_t bh_buffer_write_base(bh_buffer_t *buffer,
|
||||
const char *data,
|
||||
size_t size);
|
||||
|
||||
void bh_buffer_flush_base(bh_buffer_t *buffer);
|
||||
|
||||
int bh_buffer_seek_base(bh_buffer_t *buffer,
|
||||
bh_off_t pos,
|
||||
int dir);
|
||||
|
||||
bh_off_t bh_buffer_size_base(bh_buffer_t *buffer);
|
||||
|
||||
bh_off_t bh_buffer_tell_base(bh_buffer_t *buffer);
|
||||
|
||||
bh_off_t bh_buffer_available_base(bh_buffer_t *buffer);
|
||||
|
||||
void bh_buffer_clear_base(bh_buffer_t *buffer);
|
||||
#define bh_buffer_free(buffer) \
|
||||
bh_io_free((bh_io_t *)(buffer))
|
||||
|
||||
#define bh_buffer_open(buffer, mode) \
|
||||
bh_io_open((bh_io_t *)(buffer), (mode))
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#ifndef BH_CONFIG_H
|
||||
#define BH_CONFIG_H
|
||||
|
||||
#cmakedefine BH_USE_WINTHREAD
|
||||
#cmakedefine BH_USE_PTHREAD
|
||||
#cmakedefine BH_NO_WINXP
|
||||
#cmakedefine BH_PLATFORM_POSIX
|
||||
#cmakedefine BH_PLATFORM_WIN
|
||||
#cmakedefine BH_PLATFORM_THREADS
|
||||
|
||||
#endif /* BH_CONFIG_H */
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#ifndef BH_DEFLATE_H
|
||||
#define BH_DEFLATE_H
|
||||
|
||||
#include "bh.h"
|
||||
|
||||
#endif /* BH_DEFLATE_H */
|
||||
|
||||
@@ -1,42 +1,15 @@
|
||||
#ifndef BH_FILE_H
|
||||
#define BH_FILE_H
|
||||
|
||||
#include "bh.h"
|
||||
#include "io.h"
|
||||
|
||||
typedef struct bh_file_s bh_file_t;
|
||||
|
||||
bh_file_t *bh_file_new(const char *path);
|
||||
|
||||
void bh_file_free(bh_file_t *file);
|
||||
|
||||
int bh_file_open_base(bh_file_t *file,
|
||||
int mode);
|
||||
|
||||
void bh_file_close_base(bh_file_t *file);
|
||||
|
||||
int bh_file_is_open_base(bh_file_t *file);
|
||||
|
||||
size_t bh_file_read_base(bh_file_t *file,
|
||||
char *data,
|
||||
size_t size);
|
||||
|
||||
size_t bh_file_write_base(bh_file_t *file,
|
||||
const char *data,
|
||||
size_t size);
|
||||
|
||||
void bh_file_flush_base(bh_file_t *file);
|
||||
|
||||
int bh_file_seek_base(bh_file_t *file,
|
||||
bh_off_t pos,
|
||||
int dir);
|
||||
|
||||
bh_off_t bh_file_size_base(bh_file_t *file);
|
||||
|
||||
bh_off_t bh_file_tell_base(bh_file_t *file);
|
||||
|
||||
bh_off_t bh_file_available_base(bh_file_t *file);
|
||||
|
||||
void bh_file_clear_base(bh_file_t *file);
|
||||
#define bh_file_free(file) \
|
||||
bh_io_free((bh_io_t *)(file))
|
||||
|
||||
#define bh_file_open(file, mode) \
|
||||
bh_io_open((bh_io_t *)(file), (mode))
|
||||
@@ -50,6 +23,9 @@ void bh_file_clear_base(bh_file_t *file);
|
||||
#define bh_file_read(file, data, size) \
|
||||
bh_io_read((bh_io_t *)(file), (data), (size))
|
||||
|
||||
#define bh_file_peek(file, data, size) \
|
||||
bh_io_peek((bh_io_t *)(file), (data), (size))
|
||||
|
||||
#define bh_file_write(file, data, size) \
|
||||
bh_io_write((bh_io_t *)(file), (data), (size))
|
||||
|
||||
|
||||
8
include/bh/internal/bh.h
Normal file
8
include/bh/internal/bh.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef BH_INTERNAL_H
|
||||
#define BH_INTERNAL_H
|
||||
|
||||
#include <bh/bh.h>
|
||||
#include <bh/internal/config.h>
|
||||
|
||||
#endif /* BH_INTERNAL_H */
|
||||
|
||||
31
include/bh/internal/bigint.h
Normal file
31
include/bh/internal/bigint.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef BH_INTERNAL_BIGINT_H
|
||||
#define BH_INTERNAL_BIGINT_H
|
||||
|
||||
#include "bh.h"
|
||||
#include <bh/bigint.h>
|
||||
|
||||
#if defined(BH_BIGINT_LONG)
|
||||
#define BH_BIGINT_BITS 31
|
||||
#define BH_BIGINT_MASK 0x7FFFFFFF
|
||||
#define BH_BIGINT_TYPE bh_uint32_t
|
||||
#define BH_BIGINT_TMP bh_uint64_t
|
||||
#else
|
||||
#define BH_BIGINT_BITS 15
|
||||
#define BH_BIGINT_MASK 0x7FFF
|
||||
#define BH_BIGINT_TYPE bh_uint16_t
|
||||
#define BH_BIGINT_TMP bh_uint32_t
|
||||
#endif
|
||||
|
||||
struct bh_bigint_s
|
||||
{
|
||||
BH_BIGINT_TYPE *data;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
int type;
|
||||
int error;
|
||||
};
|
||||
|
||||
void bh_bigint_init(bh_bigint_t *bigint);
|
||||
void bh_bigint_destroy(bh_bigint_t *bigint);
|
||||
|
||||
#endif /* BH_INTERNAL_BIGINT_H */
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef BH_INTERNAL_BUFFER_H
|
||||
#define BH_INTERNAL_BUFFER_H
|
||||
|
||||
#include "bh.h"
|
||||
#include <bh/buffer.h>
|
||||
|
||||
struct bh_buffer_s
|
||||
@@ -15,6 +16,38 @@ struct bh_buffer_s
|
||||
|
||||
int bh_buffer_init(bh_buffer_t *buffer);
|
||||
|
||||
void bh_buffer_destroy(bh_buffer_t *buffer);
|
||||
#define bh_buffer_destroy(buffer) \
|
||||
bh_io_destroy((bh_io_t *)(buffer))
|
||||
|
||||
void bh_buffer_destroy_base(bh_buffer_t *buffer);
|
||||
|
||||
int bh_buffer_open_base(bh_buffer_t *buffer,
|
||||
int mode);
|
||||
|
||||
void bh_buffer_close_base(bh_buffer_t *buffer);
|
||||
|
||||
int bh_buffer_is_open_base(bh_buffer_t *buffer);
|
||||
|
||||
size_t bh_buffer_read_base(bh_buffer_t *buffer,
|
||||
char *data,
|
||||
size_t size);
|
||||
|
||||
size_t bh_buffer_write_base(bh_buffer_t *buffer,
|
||||
const char *data,
|
||||
size_t size);
|
||||
|
||||
void bh_buffer_flush_base(bh_buffer_t *buffer);
|
||||
|
||||
int bh_buffer_seek_base(bh_buffer_t *buffer,
|
||||
bh_off_t pos,
|
||||
int dir);
|
||||
|
||||
bh_off_t bh_buffer_size_base(bh_buffer_t *buffer);
|
||||
|
||||
bh_off_t bh_buffer_tell_base(bh_buffer_t *buffer);
|
||||
|
||||
bh_off_t bh_buffer_available_base(bh_buffer_t *buffer);
|
||||
|
||||
void bh_buffer_clear_base(bh_buffer_t *buffer);
|
||||
|
||||
#endif /* BH_INTERNAL_BUFFER_H */
|
||||
|
||||
7
include/bh/internal/config.in
Normal file
7
include/bh/internal/config.in
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef BH_INTERNAL_CONFIG_H
|
||||
#define BH_INTERNAL_CONFIG_H
|
||||
|
||||
#cmakedefine BH_BIGINT_LONG
|
||||
#cmakedefine BH_THREADS_WINXP
|
||||
|
||||
#endif /* BH_INTERNAL_CONFIG_H */
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef BH_INTERNAL_FILE_H
|
||||
#define BH_INTERNAL_FILE_H
|
||||
|
||||
#include "bh.h"
|
||||
#include "io.h"
|
||||
#include <bh/file.h>
|
||||
|
||||
@@ -15,6 +16,38 @@
|
||||
int bh_file_init(bh_file_t *file,
|
||||
const char *path);
|
||||
|
||||
void bh_file_destroy(bh_file_t *file);
|
||||
#define bh_file_destroy(file) \
|
||||
bh_io_destroy((bh_io_t *)(file))
|
||||
|
||||
void bh_file_destroy_base(bh_file_t *file);
|
||||
|
||||
int bh_file_open_base(bh_file_t *file,
|
||||
int mode);
|
||||
|
||||
void bh_file_close_base(bh_file_t *file);
|
||||
|
||||
int bh_file_is_open_base(bh_file_t *file);
|
||||
|
||||
size_t bh_file_read_base(bh_file_t *file,
|
||||
char *data,
|
||||
size_t size);
|
||||
|
||||
size_t bh_file_write_base(bh_file_t *file,
|
||||
const char *data,
|
||||
size_t size);
|
||||
|
||||
void bh_file_flush_base(bh_file_t *file);
|
||||
|
||||
int bh_file_seek_base(bh_file_t *file,
|
||||
bh_off_t pos,
|
||||
int dir);
|
||||
|
||||
bh_off_t bh_file_size_base(bh_file_t *file);
|
||||
|
||||
bh_off_t bh_file_tell_base(bh_file_t *file);
|
||||
|
||||
bh_off_t bh_file_available_base(bh_file_t *file);
|
||||
|
||||
void bh_file_clear_base(bh_file_t *file);
|
||||
|
||||
#endif /* BH_INTERNAL_FILE_H */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef BH_INTERNAL_HASHMAP_H
|
||||
#define BH_INTERNAL_HASHMAP_H
|
||||
|
||||
#include "bh.h"
|
||||
#include <bh/hashmap.h>
|
||||
|
||||
typedef struct bh_hashmap_node_s
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
#ifndef BH_INTERNAL_IO_H
|
||||
#define BH_INTERNAL_IO_H
|
||||
|
||||
#include "bh.h"
|
||||
#include <bh/io.h>
|
||||
|
||||
void bh_io_init(bh_io_t *io,
|
||||
const bh_io_table_t *table);
|
||||
|
||||
void bh_io_destroy(bh_io_t *io);
|
||||
|
||||
#endif /* BH_INTERNAL_IO_H */
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef BH_INTERNAL_QUEUE_H
|
||||
#define BH_INTERNAL_QUEUE_H
|
||||
|
||||
#include "bh.h"
|
||||
#include <bh/queue.h>
|
||||
|
||||
struct bh_queue_s
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef BH_INTERNAL_THREAD_H
|
||||
#define BH_INTERNAL_THREAD_H
|
||||
|
||||
#include "bh.h"
|
||||
#include <bh/thread.h>
|
||||
#include "queue.h"
|
||||
|
||||
@@ -8,9 +9,9 @@
|
||||
|
||||
#define BH_MAX_TLS 32
|
||||
|
||||
#if defined(BH_USE_PTHREAD)
|
||||
#if defined(BH_PLATFORM_POSIX) && defined(BH_PLATFORM_THREADS)
|
||||
#include "thread_posix.h"
|
||||
#elif defined(BH_USE_WINTHREAD)
|
||||
#elif defined(BH_PLATFORM_WIN) && defined(BH_PLATFORM_THREADS)
|
||||
#include "thread_win.h"
|
||||
#else
|
||||
#include "thread_null.h"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#define BH_IO_ERROR 0x0001
|
||||
#define BH_IO_EOF 0x0002
|
||||
#define BH_IO_UNIFIED 0x0004
|
||||
|
||||
#define BH_IO_NONE 0x0000
|
||||
#define BH_IO_READ 0x0001
|
||||
@@ -63,13 +64,30 @@ typedef struct bh_io_s
|
||||
{
|
||||
const bh_io_table_t *table;
|
||||
int flags;
|
||||
struct
|
||||
{
|
||||
char *data;
|
||||
size_t head;
|
||||
size_t tail;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} buffer;
|
||||
} bh_io_t;
|
||||
|
||||
bh_io_t *bh_io_new(bh_io_table_t *table,
|
||||
size_t size);
|
||||
void bh_io_destroy_base(bh_io_t *io);
|
||||
|
||||
bh_io_t *bh_io_new(const bh_io_table_t *table,
|
||||
size_t size,
|
||||
int unified);
|
||||
|
||||
void bh_io_free(bh_io_t *io);
|
||||
|
||||
void bh_io_init(bh_io_t *io,
|
||||
const bh_io_table_t *table,
|
||||
int unified);
|
||||
|
||||
void bh_io_destroy(bh_io_t *io);
|
||||
|
||||
int bh_io_open(bh_io_t *io,
|
||||
int mode);
|
||||
|
||||
@@ -81,6 +99,9 @@ size_t bh_io_read(bh_io_t *io,
|
||||
char *data,
|
||||
size_t size);
|
||||
|
||||
size_t bh_io_peek(bh_io_t *io,
|
||||
char *data,
|
||||
size_t size);
|
||||
|
||||
size_t bh_io_write(bh_io_t *io,
|
||||
const char* data,
|
||||
@@ -97,7 +118,6 @@ bh_off_t bh_io_size(bh_io_t *io);
|
||||
|
||||
bh_off_t bh_io_tell(bh_io_t *io);
|
||||
|
||||
|
||||
bh_off_t bh_io_available(bh_io_t *io);
|
||||
|
||||
int bh_io_error(bh_io_t *io);
|
||||
|
||||
@@ -14,12 +14,7 @@ typedef struct bh_task_s bh_task_t;
|
||||
typedef struct bh_thread_pool_s bh_thread_pool_t;
|
||||
typedef struct bh_spinlock_s bh_spinlock_t;
|
||||
|
||||
#if defined(BH_USE_PTHREAD)
|
||||
bh_thread_t *bh_thread_new(bh_task_t *task);
|
||||
|
||||
bh_thread_pool_t *bh_thread_pool_new(size_t size);
|
||||
|
||||
#elif defined(BH_USE_WINTHREAD)
|
||||
#if defined(BH_PLATFORM_WIN) && defined(BH_PLATFORM_THREADS)
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
@@ -46,6 +41,10 @@ bh_thread_pool_t *bh_thread_pool_new_base(size_t size,
|
||||
#define bh_thread_pool_new(size) \
|
||||
bh_thread_pool_new_base((size), _beginthreadex, _endthreadex);
|
||||
|
||||
#elif defined(BH_PLATFORM_THREADS)
|
||||
bh_thread_t *bh_thread_new(bh_task_t *task);
|
||||
|
||||
bh_thread_pool_t *bh_thread_pool_new(size_t size);
|
||||
#endif
|
||||
|
||||
bh_task_t *bh_task_new(void (*func)(void *),
|
||||
|
||||
2
scripts/dos2unix.sh
Normal file
2
scripts/dos2unix.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
find . \( -iname "*.h" -o -iname "*.c" \) -exec dos2unix {} \;
|
||||
2
scripts/unix2dos.sh
Normal file
2
scripts/unix2dos.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
find . \( -iname "*.h" -o -iname "*.c" \) -exec unix2dos {} \;
|
||||
1786
src/bigint.c
Normal file
1786
src/bigint.c
Normal file
File diff suppressed because it is too large
Load Diff
14
src/buffer.c
14
src/buffer.c
@@ -15,7 +15,7 @@ static const bh_io_table_t bh_buffer_table = {
|
||||
(bh_off_t (*)(struct bh_io_s *)) bh_buffer_tell_base,
|
||||
(bh_off_t (*)(struct bh_io_s *)) bh_buffer_available_base,
|
||||
(void (*)(struct bh_io_s *)) bh_buffer_clear_base,
|
||||
(void (*)(struct bh_io_s *)) bh_buffer_destroy
|
||||
(void (*)(struct bh_io_s *)) bh_buffer_destroy_base
|
||||
};
|
||||
|
||||
bh_buffer_t *bh_buffer_new(void)
|
||||
@@ -34,17 +34,10 @@ bh_buffer_t *bh_buffer_new(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
void bh_buffer_free(bh_buffer_t *buffer)
|
||||
{
|
||||
/* Destroy buffer and free the memory */
|
||||
bh_buffer_destroy(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
int bh_buffer_init(bh_buffer_t *buffer)
|
||||
{
|
||||
/* Initialize underlying io object */
|
||||
bh_io_init(&buffer->base, &bh_buffer_table);
|
||||
bh_io_init(&buffer->base, &bh_buffer_table, 1);
|
||||
|
||||
/* Setup internal information */
|
||||
buffer->data = NULL;
|
||||
@@ -56,12 +49,13 @@ int bh_buffer_init(bh_buffer_t *buffer)
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
void bh_buffer_destroy(bh_buffer_t *buffer)
|
||||
void bh_buffer_destroy_base(bh_buffer_t *buffer)
|
||||
{
|
||||
/* Close the buffer and free allocated memory */
|
||||
bh_buffer_close(buffer);
|
||||
if (buffer->data)
|
||||
free(buffer->data);
|
||||
bh_io_destroy_base(&buffer->base);
|
||||
}
|
||||
|
||||
const char *bh_buffer_data(bh_buffer_t *buffer)
|
||||
|
||||
@@ -21,19 +21,6 @@ bh_file_t *bh_file_new(const char *path)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the \a file object.
|
||||
*
|
||||
* Before freeing the file object, this function ensures that underlying file
|
||||
* was closed.
|
||||
*
|
||||
* \param file Pointer to the file object
|
||||
*/
|
||||
void bh_file_free(bh_file_t *file)
|
||||
{
|
||||
(void)file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the \a file object with specified \a path to file.
|
||||
*
|
||||
@@ -59,7 +46,7 @@ int bh_file_init(bh_file_t *file,
|
||||
*
|
||||
* \param file Pointer to the file object
|
||||
*/
|
||||
void bh_file_destroy(bh_file_t *file)
|
||||
void bh_file_destroy_base(bh_file_t *file)
|
||||
{
|
||||
(void)file;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ static const bh_io_table_t bh_file_table = {
|
||||
(bh_off_t (*)(struct bh_io_s *)) bh_file_tell_base,
|
||||
(bh_off_t (*)(struct bh_io_s *)) bh_file_available_base,
|
||||
(void (*)(struct bh_io_s *)) bh_file_clear_base,
|
||||
(void (*)(struct bh_io_s *)) bh_file_destroy
|
||||
(void (*)(struct bh_io_s *)) bh_file_destroy_base
|
||||
};
|
||||
|
||||
bh_file_t *bh_file_new(const char *path)
|
||||
@@ -38,12 +38,6 @@ bh_file_t *bh_file_new(const char *path)
|
||||
return result;
|
||||
}
|
||||
|
||||
void bh_file_free(bh_file_t *file)
|
||||
{
|
||||
bh_file_destroy(file);
|
||||
free(file);
|
||||
}
|
||||
|
||||
int bh_file_init(bh_file_t *file,
|
||||
const char *path)
|
||||
{
|
||||
@@ -51,8 +45,8 @@ int bh_file_init(bh_file_t *file,
|
||||
if (!path)
|
||||
return BH_INVALID;
|
||||
|
||||
/* Initialize base io object */
|
||||
bh_io_init(&file->base, &bh_file_table);
|
||||
/* Initialize underlying io object */
|
||||
bh_io_init(&file->base, &bh_file_table, 1);
|
||||
|
||||
/* Initialize file io object */
|
||||
file->handle = -1;
|
||||
@@ -62,11 +56,12 @@ int bh_file_init(bh_file_t *file,
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
void bh_file_destroy(bh_file_t *file)
|
||||
void bh_file_destroy_base(bh_file_t *file)
|
||||
{
|
||||
/* Close the file */
|
||||
bh_file_close(file);
|
||||
free(file->path);
|
||||
bh_io_destroy_base(&file->base);
|
||||
}
|
||||
|
||||
int bh_file_open_base(bh_file_t *file,
|
||||
|
||||
@@ -12,7 +12,7 @@ static const bh_io_table_t bh_file_table = {
|
||||
(bh_off_t (*)(struct bh_io_s *)) bh_file_tell_base,
|
||||
(bh_off_t (*)(struct bh_io_s *)) bh_file_available_base,
|
||||
(void (*)(struct bh_io_s *)) bh_file_clear_base,
|
||||
(void (*)(struct bh_io_s *)) bh_file_destroy
|
||||
(void (*)(struct bh_io_s *)) bh_file_destroy_base
|
||||
};
|
||||
|
||||
bh_file_t *bh_file_new(const char *path)
|
||||
@@ -31,13 +31,6 @@ bh_file_t *bh_file_new(const char *path)
|
||||
return result;
|
||||
}
|
||||
|
||||
void bh_file_free(bh_file_t *file)
|
||||
{
|
||||
/* Destroy file object and free allocated memory */
|
||||
bh_file_destroy(file);
|
||||
free(file);
|
||||
}
|
||||
|
||||
int bh_file_init(bh_file_t *file,
|
||||
const char *path)
|
||||
{
|
||||
@@ -45,20 +38,23 @@ int bh_file_init(bh_file_t *file,
|
||||
if (!path)
|
||||
return BH_INVALID;
|
||||
|
||||
/* Initialize underlying io object */
|
||||
bh_io_init(&file->base, &bh_file_table, 1);
|
||||
|
||||
/* Fill file structure information */
|
||||
file->handle = INVALID_HANDLE_VALUE;
|
||||
file->mode = BH_IO_NONE;
|
||||
file->path = strdup(path);
|
||||
file->base.table = &bh_file_table;
|
||||
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
void bh_file_destroy(bh_file_t *file)
|
||||
void bh_file_destroy_base(bh_file_t *file)
|
||||
{
|
||||
/* Close the file and free allocated memory */
|
||||
bh_file_close(file);
|
||||
free(file->path);
|
||||
bh_io_destroy_base(&file->base);
|
||||
}
|
||||
|
||||
int bh_file_open_base(bh_file_t *file,
|
||||
|
||||
425
src/io.c
425
src/io.c
@@ -1,5 +1,8 @@
|
||||
#include <bh/internal/io.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BH_IO_BUFFER_STEP 256
|
||||
|
||||
/**
|
||||
* \defgroup io Input/Output
|
||||
@@ -8,11 +11,339 @@
|
||||
* \{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Returns pointer to the \a io peek buffer.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
*
|
||||
* \return Pointer to the peek buffer.
|
||||
*
|
||||
* \warning Always use this function to get data of the buffer!
|
||||
*/
|
||||
static char *bh_io_buffer_data(bh_io_t *io)
|
||||
{
|
||||
if (io->buffer.capacity)
|
||||
return io->buffer.data;
|
||||
|
||||
return (char *)&io->buffer.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Returns peek buffer capacity of the /a io object.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
*
|
||||
* \return Peek buffer capacity.
|
||||
*
|
||||
* \warning Always use this function to get capacity of the buffer!
|
||||
*/
|
||||
static size_t bh_io_buffer_capacity(bh_io_t *io)
|
||||
{
|
||||
if (io->buffer.capacity)
|
||||
return io->buffer.capacity;
|
||||
return sizeof(char *);
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Reduces the capacity of the \a io object peek buffer.
|
||||
*
|
||||
* \param io Pointer to the io object.
|
||||
*
|
||||
* \note This function does not guarantee that the capacity of the buffer will
|
||||
* actually be reduced.
|
||||
*/
|
||||
static void bh_io_buffer_shrink(bh_io_t *io)
|
||||
{
|
||||
size_t capacity;
|
||||
char *data;
|
||||
|
||||
/* Check if buffer is allocated */
|
||||
if (!io->buffer.capacity)
|
||||
return;
|
||||
|
||||
/* Calculate new capacity and check against old capacity */
|
||||
capacity = (io->buffer.size + BH_IO_BUFFER_STEP - 1) / BH_IO_BUFFER_STEP;
|
||||
capacity *= BH_IO_BUFFER_STEP;
|
||||
if (io->buffer.capacity >= capacity)
|
||||
return;
|
||||
|
||||
/* Allocate new buffer space */
|
||||
data = malloc(capacity);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
/* Copy data */
|
||||
if (io->buffer.size)
|
||||
{
|
||||
size_t block;
|
||||
|
||||
/* Depending on the tail-head positions copy data in two or one go */
|
||||
if (io->buffer.tail <= io->buffer.head)
|
||||
{
|
||||
block = io->buffer.capacity - io->buffer.head;
|
||||
memmove(data, io->buffer.data + io->buffer.head, block);
|
||||
memmove(data + block, io->buffer.data, io->buffer.size - block);
|
||||
}
|
||||
else
|
||||
{
|
||||
block = io->buffer.size;
|
||||
memmove(data, io->buffer.data + io->buffer.head, block);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update fields */
|
||||
free(io->buffer.data);
|
||||
io->buffer.data = data;
|
||||
io->buffer.head = 0;
|
||||
io->buffer.tail = io->buffer.size;
|
||||
io->buffer.capacity = capacity;
|
||||
if (io->buffer.tail >= capacity)
|
||||
io->buffer.tail = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Reserves the capacity of the \a io object peek buffer.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
* \param size New peek buffer capacity
|
||||
*
|
||||
* \return On success, returns zero value.
|
||||
* \return On failure, returns error code.
|
||||
*/
|
||||
static int bh_io_buffer_reserve(bh_io_t *io,
|
||||
size_t size)
|
||||
{
|
||||
size_t capacity;
|
||||
char *data;
|
||||
|
||||
/* Check if entire buffer can fit into a pointer */
|
||||
if (size <= sizeof(char *))
|
||||
return BH_OK;
|
||||
|
||||
/* Check that size can fit into a buffer */
|
||||
if (io->buffer.capacity >= size)
|
||||
return BH_OK;
|
||||
|
||||
/* Calculate new buffer capacity */
|
||||
capacity = (size + BH_IO_BUFFER_STEP - 1) / BH_IO_BUFFER_STEP;
|
||||
capacity *= BH_IO_BUFFER_STEP;
|
||||
|
||||
/* Allocate new buffer space */
|
||||
data = malloc(capacity);
|
||||
if (!data)
|
||||
return BH_OOM;
|
||||
|
||||
/* Copy data */
|
||||
if (io->buffer.size)
|
||||
{
|
||||
size_t block;
|
||||
|
||||
/* Depending on the tail-head positions copy data in two or one go */
|
||||
if (io->buffer.tail <= io->buffer.head)
|
||||
{
|
||||
block = io->buffer.capacity - io->buffer.head;
|
||||
memmove(data, bh_io_buffer_data(io) + io->buffer.head, block);
|
||||
memmove(data + block, bh_io_buffer_data(io), io->buffer.size - block);
|
||||
}
|
||||
else
|
||||
{
|
||||
block = io->buffer.size;
|
||||
memmove(data, bh_io_buffer_data(io) + io->buffer.head, block);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update fields */
|
||||
if (io->buffer.capacity)
|
||||
free(io->buffer.data);
|
||||
io->buffer.data = data;
|
||||
io->buffer.head = 0;
|
||||
io->buffer.tail = io->buffer.size;
|
||||
io->buffer.capacity = capacity;
|
||||
if (io->buffer.tail >= capacity)
|
||||
io->buffer.tail = 0;
|
||||
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Reads data from the \a io peek buffer.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
* \param data Pointer to the memory buffer
|
||||
* \param size Maximum number of bytes to be read
|
||||
* \param peek Reading or peeking flag
|
||||
*
|
||||
* \return On success, returns number of bytes successfuly read.
|
||||
* \return On failure, returns zero.
|
||||
*/
|
||||
static size_t bh_io_buffer_read(bh_io_t *io,
|
||||
char *data,
|
||||
size_t size,
|
||||
int peek)
|
||||
{
|
||||
size_t block;
|
||||
|
||||
/* Check if buffer is empty */
|
||||
if (!io->buffer.size)
|
||||
return 0;
|
||||
|
||||
/* Reading size can't be bigger then buffer size */
|
||||
if (size > io->buffer.size)
|
||||
size = io->buffer.size;
|
||||
|
||||
/* Copy data */
|
||||
if (data)
|
||||
{
|
||||
/* Depending on the tail-head positions copy data in two or one go */
|
||||
if (io->buffer.tail <= io->buffer.head)
|
||||
{
|
||||
block = bh_io_buffer_capacity(io) - io->buffer.head;
|
||||
if (block > size)
|
||||
block = size;
|
||||
memmove(data, bh_io_buffer_data(io) + io->buffer.head, block);
|
||||
memmove(data + block, bh_io_buffer_data(io), size - block);
|
||||
}
|
||||
else
|
||||
{
|
||||
block = size;
|
||||
memmove(data, bh_io_buffer_data(io) + io->buffer.head, block);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust head position and size if we are not peeking */
|
||||
if (!peek)
|
||||
{
|
||||
io->buffer.head += size;
|
||||
io->buffer.size -= size;
|
||||
|
||||
if (io->buffer.head >= bh_io_buffer_capacity(io))
|
||||
io->buffer.head -= bh_io_buffer_capacity(io);
|
||||
|
||||
/* Shrink buffer if neccesary*/
|
||||
bh_io_buffer_shrink(io);
|
||||
}
|
||||
|
||||
/* Return readed size */
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Writes data to the \a io peek buffer.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
* \param data Pointer to the memory buffer
|
||||
* \param size Maximum number of bytes to be read
|
||||
*
|
||||
* \return On success, returns number of bytes successfuly written.
|
||||
* \return On failure, returns zero.
|
||||
*/
|
||||
static size_t bh_io_buffer_write(bh_io_t *io,
|
||||
const char *data,
|
||||
size_t size)
|
||||
{
|
||||
size_t block;
|
||||
|
||||
/* Reserve capacity in the buffer */
|
||||
if (bh_io_buffer_reserve(io, io->buffer.size + size))
|
||||
return 0;
|
||||
|
||||
/* Depending on the tail-head positions copy data in two or one go */
|
||||
if (io->buffer.tail + size > bh_io_buffer_capacity(io))
|
||||
{
|
||||
block = io->buffer.capacity - io->buffer.tail;
|
||||
memmove(bh_io_buffer_data(io) + io->buffer.tail, data, block);
|
||||
memmove(bh_io_buffer_data(io), data + block, size - block);
|
||||
}
|
||||
else
|
||||
{
|
||||
block = size;
|
||||
memmove(bh_io_buffer_data(io) + io->buffer.tail, data, block);
|
||||
}
|
||||
|
||||
/* Adjust tail and size */
|
||||
io->buffer.tail += size;
|
||||
io->buffer.size += size;
|
||||
|
||||
if (io->buffer.tail >= bh_io_buffer_capacity(io))
|
||||
io->buffer.tail -= bh_io_buffer_capacity(io);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* Adjusts \a io object peek buffer according to the specified seek direction
|
||||
* \a dir and \a offset.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
* \param offset Number of bytes to seek in specified direciton
|
||||
* \param dir Seeking direction
|
||||
*
|
||||
* \return Returns new offset for the io seek function.
|
||||
*/
|
||||
static bh_off_t bh_io_buffer_seek(bh_io_t *io,
|
||||
bh_off_t offset,
|
||||
int dir)
|
||||
{
|
||||
/* Check if seek is relative to current position */
|
||||
if (dir != BH_IO_CURRENT)
|
||||
{
|
||||
/* It's not - reset peek buffer and return offset as is */
|
||||
io->buffer.size = 0;
|
||||
io->buffer.head = 0;
|
||||
io->buffer.tail = 0;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* If offset is negative or past peek buffer size */
|
||||
if (offset < 0 || offset >= (bh_off_t)io->buffer.size)
|
||||
{
|
||||
/* It's not - reset peek buffer and adjust offset position */
|
||||
offset -= io->buffer.size;
|
||||
io->buffer.size = 0;
|
||||
io->buffer.head = 0;
|
||||
io->buffer.tail = 0;
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Skip offset amount of bytes */
|
||||
bh_io_buffer_read(io, NULL, offset, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys base io object.
|
||||
*
|
||||
* \param io Pointer to the base io object
|
||||
*
|
||||
* \warning This function should be used in context of implementing child
|
||||
* io objects (files, sockets, streaming compression, etc).
|
||||
*/
|
||||
void bh_io_destroy_base(bh_io_t *io)
|
||||
{
|
||||
if (io->buffer.capacity)
|
||||
free(io->buffer.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the new io object with specified \a table and \a size.
|
||||
*
|
||||
* \param table Pointer to the io table
|
||||
* \param size Size of the io object
|
||||
* The \a unified flag specifies the behaivor of the internal peek buffer.
|
||||
* If the \a unified flag is set - the io object will assume that read and
|
||||
* write operations are dependant on each other (ex. writing to the file
|
||||
* affects next read operation).
|
||||
* If the \a unified flag is not set - the io object will asusme that read and
|
||||
* write operations are independant.
|
||||
*
|
||||
* \param table Pointer to the io table
|
||||
* \param size Size of the io object
|
||||
* \param unified Unified read/write stream flag
|
||||
*
|
||||
* \return On success, returns new semi-initialized io object.
|
||||
* \return On failure, returns null pointer.
|
||||
@@ -20,14 +351,15 @@
|
||||
* \warning This function should be used in context of implementing child
|
||||
* io objects (files, sockets, streaming compression, etc).
|
||||
*/
|
||||
bh_io_t *bh_io_new(bh_io_table_t *table,
|
||||
size_t size)
|
||||
bh_io_t *bh_io_new(const bh_io_table_t *table,
|
||||
size_t size,
|
||||
int unified)
|
||||
{
|
||||
bh_io_t *result;
|
||||
|
||||
result = malloc(size);
|
||||
if (result)
|
||||
bh_io_init(result, table);
|
||||
bh_io_init(result, table, unified);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -46,14 +378,27 @@ void bh_io_free(bh_io_t *io)
|
||||
/**
|
||||
* Initializes the \a io object with specified \a table.
|
||||
*
|
||||
* \param io Pointer to the io object to be initialized
|
||||
* \param table Pointer to the io table
|
||||
* The \a unified flag specifies the behaivor of the internal peek buffer.
|
||||
* If the \a unified flag is set - the io object will assume that read and
|
||||
* write operations are dependant on each other (ex. writing to the file
|
||||
* affects next read operation).
|
||||
* If the \a unified flag is not set - the io object will asusme that read and
|
||||
* write operations are independant.
|
||||
*
|
||||
* \param io Pointer to the io object to be initialized
|
||||
* \param table Pointer to the io table
|
||||
* \param unified Unified read/write stream flag
|
||||
*/
|
||||
void bh_io_init(bh_io_t *io,
|
||||
const bh_io_table_t *table)
|
||||
const bh_io_table_t *table,
|
||||
int unified)
|
||||
{
|
||||
io->table = table;
|
||||
io->flags = 0;
|
||||
io->flags = (unified) ? (BH_IO_UNIFIED) : (0);
|
||||
io->buffer.capacity = 0;
|
||||
io->buffer.head = 0;
|
||||
io->buffer.tail = 0;
|
||||
io->buffer.size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +466,50 @@ size_t bh_io_read(bh_io_t *io,
|
||||
char *data,
|
||||
size_t size)
|
||||
{
|
||||
return io->table->read(io, data, size);
|
||||
|
||||
size_t result;
|
||||
|
||||
/* Read as much data from peek buffer as possible */
|
||||
result = bh_io_buffer_read(io, data, size, 0);
|
||||
|
||||
/* If that wasn't enough read from the device */
|
||||
if (result != size)
|
||||
result += io->table->read(io, data + result, size - result);
|
||||
|
||||
/* Return amount of bytes read */
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks up to \a size amount of bytes from the \a io object into memory buffer
|
||||
* pointed by \a data pointer.
|
||||
*
|
||||
* \param io Pointer to the io object
|
||||
* \param data Pointer to the memory buffer
|
||||
* \param size Maximum number of bytes to be read
|
||||
*
|
||||
* \return On success, returns number of bytes successfuly read.
|
||||
* \return On failure, returns zero.
|
||||
*/
|
||||
size_t bh_io_peek(bh_io_t *io,
|
||||
char *data,
|
||||
size_t size)
|
||||
{
|
||||
/* Fill peek buffer if it's size is less then requested */
|
||||
if (io->buffer.size < size)
|
||||
{
|
||||
size_t read;
|
||||
|
||||
read = io->table->read(io, data, size - io->buffer.size);
|
||||
bh_io_buffer_write(io, data, read);
|
||||
}
|
||||
|
||||
/* Clear EOF flag if peek buffer is not empty */
|
||||
if (io->buffer.size > 0)
|
||||
io->flags &= ~BH_IO_EOF;
|
||||
|
||||
/* Read data from the peek buffer */
|
||||
return bh_io_buffer_read(io, data, size, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,9 +526,19 @@ size_t bh_io_read(bh_io_t *io,
|
||||
* \note To check for error see bh_io_error.
|
||||
*/
|
||||
size_t bh_io_write(bh_io_t *io,
|
||||
const char* data,
|
||||
const char *data,
|
||||
size_t size)
|
||||
{
|
||||
/* Clear peek buffer and adjust the position if IO is unified */
|
||||
if (io->buffer.size && (io->flags & BH_IO_UNIFIED))
|
||||
{
|
||||
io->table->seek(io, -(bh_off_t)io->buffer.size, BH_IO_CURRENT);
|
||||
io->buffer.head = 0;
|
||||
io->buffer.tail = 0;
|
||||
io->buffer.size = 0;
|
||||
}
|
||||
|
||||
/* Write data */
|
||||
return io->table->write(io, data, size);
|
||||
}
|
||||
|
||||
@@ -172,6 +570,7 @@ int bh_io_seek(bh_io_t *io,
|
||||
bh_off_t offset,
|
||||
int dir)
|
||||
{
|
||||
offset = bh_io_buffer_seek(io, offset, dir);
|
||||
return io->table->seek(io, offset, dir);
|
||||
}
|
||||
|
||||
@@ -198,7 +597,7 @@ bh_off_t bh_io_size(bh_io_t *io)
|
||||
*/
|
||||
bh_off_t bh_io_tell(bh_io_t *io)
|
||||
{
|
||||
return io->table->tell(io);
|
||||
return io->table->tell(io) - io->buffer.size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +610,7 @@ bh_off_t bh_io_tell(bh_io_t *io)
|
||||
*/
|
||||
bh_off_t bh_io_available(bh_io_t *io)
|
||||
{
|
||||
return io->table->available(io);
|
||||
return io->table->available(io) + io->buffer.size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
|
||||
static void *bh_thread_run(void *arg)
|
||||
{
|
||||
bh_tls_t *tls;
|
||||
bh_task_t *task;
|
||||
|
||||
/* Fetch thread data */
|
||||
task = (bh_task_t *)arg;
|
||||
|
||||
/* Setup TLS */
|
||||
tls = bh_tls_fetch();
|
||||
bh_tls_fetch();
|
||||
|
||||
/* Do the task, mark as done, and if required free it */
|
||||
task->func(task->data);
|
||||
|
||||
@@ -46,7 +46,7 @@ int bh_thread_init_base(bh_thread_t *thread,
|
||||
|
||||
/* Create and setup thread (relative to the callers libc) */
|
||||
thread->allocated = 0;
|
||||
thread->handle = (HANDLE)_beginthreadex(NULL, 0, bh_thread_run, data, 0, NULL);
|
||||
thread->handle = (HANDLE)begin(NULL, 0, bh_thread_run, data, 0, NULL);
|
||||
|
||||
/* Check for errors */
|
||||
if (!thread->handle)
|
||||
@@ -187,7 +187,7 @@ int bh_semaphore_try_wait(bh_semaphore_t *semaphore)
|
||||
return BH_OK;
|
||||
}
|
||||
|
||||
#if WINVER >= _WIN32_WINNT_VISTA
|
||||
#if WINVER >= _WIN32_WINNT_VISTA && !defined(BH_THREADS_WINXP)
|
||||
int bh_cond_init(bh_cond_t *cond)
|
||||
{
|
||||
InitializeConditionVariable(&cond->handle);
|
||||
|
||||
@@ -2,9 +2,6 @@ set(CMAKE_C_STANDARD 90)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
# Enable warnings and pedantics
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic")
|
||||
|
||||
# Enable testing
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
@@ -17,4 +14,11 @@ foreach(TEST_FILENAME ${TEST_FILES})
|
||||
add_executable("${TEST_NAME}" ${TEST_FILENAME})
|
||||
target_link_libraries("${TEST_NAME}" bhlib bhunit)
|
||||
add_test(NAME "${TEST_NAME}" COMMAND "${TEST_NAME}")
|
||||
|
||||
# Enable warnings and pedantics
|
||||
if(MSVC)
|
||||
target_compile_options("${TEST_NAME}" PRIVATE /W4)
|
||||
else()
|
||||
target_compile_options("${TEST_NAME}" PRIVATE -Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
924
tests/src/bigint.c
Normal file
924
tests/src/bigint.c
Normal file
@@ -0,0 +1,924 @@
|
||||
#include <bh/internal/bigint.h>
|
||||
#include <bh/unit.h>
|
||||
#include <string.h>
|
||||
|
||||
static int fields(void)
|
||||
{
|
||||
bh_bigint_t bint;
|
||||
|
||||
bh_bigint_init(&bint);
|
||||
|
||||
/* Ensure that methods reflect big integer fields */
|
||||
bint.error = 0;
|
||||
bint.type = 0;
|
||||
bh_unit_assert(bint.error == bh_bigint_is_error(&bint));
|
||||
bh_unit_assert((bint.type < 0) == bh_bigint_is_negative(&bint));
|
||||
bh_unit_assert((bint.type == 0) == bh_bigint_is_zero(&bint));
|
||||
|
||||
bint.error = 0;
|
||||
bint.type = 1;
|
||||
bh_unit_assert(bint.error == bh_bigint_is_error(&bint));
|
||||
bh_unit_assert((bint.type < 0) == bh_bigint_is_negative(&bint));
|
||||
bh_unit_assert((bint.type == 0) == bh_bigint_is_zero(&bint));
|
||||
|
||||
bint.type = -1;
|
||||
bh_unit_assert(bint.error == bh_bigint_is_error(&bint));
|
||||
bh_unit_assert((bint.type < 0) == bh_bigint_is_negative(&bint));
|
||||
bh_unit_assert((bint.type == 0) == bh_bigint_is_zero(&bint));
|
||||
|
||||
bint.error = 1;
|
||||
bh_unit_assert(bint.error == bh_bigint_is_error(&bint));
|
||||
|
||||
bh_bigint_destroy(&bint);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int round_trip(void)
|
||||
{
|
||||
bh_bigint_t *data[10];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
data[i] = bh_bigint_new();
|
||||
bh_unit_assert(data[i] != NULL);
|
||||
}
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(data[0], -12345) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(data[0]) == -12345);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int8(data[1], -120) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int8(data[1]) == -120);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int16(data[2], -12345) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int16(data[2]) == -12345);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int32(data[3], -12345678l) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int32(data[3]) == -12345678l);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int64(data[4], -123456789012345ll) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int64(data[4]) == -123456789012345ll);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_uint(data[5], 12345) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint(data[5]) == 12345);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_uint8(data[6], 230) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint8(data[6]) == 230);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_uint16(data[7], 40000) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint16(data[7]) == 40000);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_uint32(data[8], 12345678ul) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint32(data[8]) == 12345678ul);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_uint64(data[9], 123456789012345ull) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(data[9]) == 123456789012345ull);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
bh_bigint_free(data[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_sub(void)
|
||||
{
|
||||
const bh_uint64_t ta = 0xA3B1DBC158176B96ull, tb = 0x2748D1622F3E90A2ull;
|
||||
bh_bigint_t *a, *b, *c;
|
||||
|
||||
/* Allocate new big integers */
|
||||
a = bh_bigint_new();
|
||||
b = bh_bigint_new();
|
||||
c = bh_bigint_new();
|
||||
|
||||
bh_unit_assert(a != NULL);
|
||||
bh_unit_assert(b != NULL);
|
||||
bh_unit_assert(c != NULL);
|
||||
|
||||
/* Test correct result sign */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 5) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 8);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -2);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 5) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 2);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -8);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -5) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -2);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 8);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -5) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -8);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 2);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
/* Edge cases for correct sign */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 6);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -6);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 6);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -6);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
/* Set 'multi-digit' integers */
|
||||
bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK);
|
||||
|
||||
/* Test addition and subtraction */
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb));
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb));
|
||||
|
||||
/* Overwrites */
|
||||
bh_unit_assert(bh_bigint_set(c, a) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb));
|
||||
bh_unit_assert(bh_bigint_set(c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, a, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta + tb));
|
||||
|
||||
bh_unit_assert(bh_bigint_set(c, a) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_sub(c, c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb));
|
||||
bh_unit_assert(bh_bigint_set(c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_sub(c, a, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta - tb));
|
||||
|
||||
/* Check for error handling */
|
||||
a->error = 0;
|
||||
b->error = 0;
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 0;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_add(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_sub(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
/* Free big integers */
|
||||
bh_bigint_free(a);
|
||||
bh_bigint_free(b);
|
||||
bh_bigint_free(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int multiplication(void)
|
||||
{
|
||||
bh_bigint_t *a, *b, *c, *d;
|
||||
int i;
|
||||
|
||||
/* Allocate new big integers */
|
||||
a = bh_bigint_new();
|
||||
b = bh_bigint_new();
|
||||
c = bh_bigint_new();
|
||||
d = bh_bigint_new();
|
||||
|
||||
bh_unit_assert(a != NULL);
|
||||
bh_unit_assert(b != NULL);
|
||||
bh_unit_assert(c != NULL);
|
||||
bh_unit_assert(d != NULL);
|
||||
|
||||
/* Set big integers to arbitrary number */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1234567) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 1234567) == BH_OK);
|
||||
|
||||
/* Reference multiplication by addition */
|
||||
bh_unit_assert(bh_bigint_reserve(c, a->size + b->size + 1) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set(c, a) == BH_OK);
|
||||
for (i = 1; i < 1234567; i++)
|
||||
bh_unit_assert(bh_bigint_add(c, c, a) == BH_OK);
|
||||
|
||||
/* Multiplication and compare for equality */
|
||||
bh_unit_assert(bh_bigint_mul(d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(c, d) == 0);
|
||||
|
||||
/* Check signs */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Check multiplication by zero */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
/* Overwrites */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1234) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 4321) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(a, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(a) == 1234 * 4321);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1234) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 4321) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(b, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(b) == 1234 * 4321);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1234) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 4321) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(a, a, a) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(a) == 1234 * 1234);
|
||||
|
||||
/* Check digit multiplication */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1234567) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 12345) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == 15240729615ull);
|
||||
|
||||
/* Check digit multiplication by zero */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
/* Check digit multiplication signs */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, -2) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 4);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Check for error handling */
|
||||
a->error = 0;
|
||||
b->error = 0;
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 0;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_mul(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
/* Check for digit multiplication error handling */
|
||||
a->error = 0;
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 10) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
a->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_mul_digit(c, a, 10) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
bh_bigint_free(a);
|
||||
bh_bigint_free(b);
|
||||
bh_bigint_free(c);
|
||||
bh_bigint_free(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int logic(void)
|
||||
{
|
||||
const bh_uint64_t ta = 0xA3B1DBC158176B96ull, tb = 0x2748D1622F3E90A2ull;
|
||||
bh_bigint_t *a, *b, *c;
|
||||
|
||||
/* Allocate big integers */
|
||||
a = bh_bigint_new();
|
||||
b = bh_bigint_new();
|
||||
c = bh_bigint_new();
|
||||
|
||||
bh_unit_assert(a != NULL);
|
||||
bh_unit_assert(b != NULL);
|
||||
bh_unit_assert(c != NULL);
|
||||
|
||||
/* Copy from reference integers */
|
||||
bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK);
|
||||
|
||||
/* Logic OR */
|
||||
bh_unit_assert(bh_bigint_or(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta | tb));
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
|
||||
/* Logic AND */
|
||||
bh_unit_assert(bh_bigint_and(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta & tb));
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
|
||||
/* Logic XOR */
|
||||
bh_unit_assert(bh_bigint_xor(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (ta ^ tb));
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
|
||||
/* Operations with zero */
|
||||
bh_unit_assert(bh_bigint_clear(b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_and(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_or(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == ta);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_xor(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == ta);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Copy from reference integers */
|
||||
bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK);
|
||||
|
||||
/* Logic shift left */
|
||||
bh_unit_assert(bh_bigint_lsh(c, b, 1) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (tb << 1));
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Logic shift right */
|
||||
bh_unit_assert(bh_bigint_rsh(c, b, 1) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == (tb >> 1));
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Zero bit shifts */
|
||||
bh_unit_assert(bh_bigint_lsh(c, b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == tb);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_rsh(c, b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == tb);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Full width shift */
|
||||
bh_unit_assert(bh_bigint_rsh(c, b, 64) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) != 0);
|
||||
|
||||
/* Large shifts */
|
||||
bh_unit_assert(bh_bigint_rsh(c, a, 60) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == 0xA);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_lsh(c, a, 100) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_rsh(c, c, 100) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == ta);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_zero(c) == 0);
|
||||
|
||||
/* Check for error handling */
|
||||
a->error = 0;
|
||||
b->error = 0;
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_or(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_and(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_xor(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_lsh(c, a, 1) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
c->error = 1;
|
||||
bh_unit_assert(bh_bigint_rsh(c, a, 1) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 0;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_or(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_and(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_xor(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_lsh(c, a, 1) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_rsh(c, a, 1) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_or(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_and(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_xor(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_or(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_and(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
c->error = 0;
|
||||
bh_unit_assert(bh_bigint_xor(c, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
|
||||
/* Free big integers */
|
||||
bh_bigint_free(a);
|
||||
bh_bigint_free(b);
|
||||
bh_bigint_free(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int division(void)
|
||||
{
|
||||
const bh_uint64_t ta = 0x41F915031348A134ull, tb = 0x434115F6ull, tc = 0x153F14ABull;
|
||||
const bh_uint64_t td = 0xD0D561E41F7EA081ull, te = 0x0459E1CDull;
|
||||
bh_bigint_t *a, *b, *c, *d;
|
||||
|
||||
/* Allocate big integers */
|
||||
a = bh_bigint_new();
|
||||
b = bh_bigint_new();
|
||||
c = bh_bigint_new();
|
||||
d = bh_bigint_new();
|
||||
|
||||
bh_unit_assert(a != NULL);
|
||||
bh_unit_assert(b != NULL);
|
||||
bh_unit_assert(c != NULL);
|
||||
bh_unit_assert(d != NULL);
|
||||
|
||||
/* Set integers to test values */
|
||||
bh_unit_assert(bh_bigint_set_uint64(a, ta) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_uint64(b, tb) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mul(a, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_uint64(b, tc) == BH_OK);
|
||||
|
||||
/* Divide and check result for div&mod operation */
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == td);
|
||||
bh_unit_assert(bh_bigint_get_uint64(d) == te);
|
||||
|
||||
/* Check for division */
|
||||
bh_unit_assert(bh_bigint_div(c, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(c) == td);
|
||||
|
||||
/* Check for modulos */
|
||||
bh_unit_assert(bh_bigint_mod(d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_uint64(d) == te);
|
||||
|
||||
/* Check division with zero */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int(d) == 0);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(d) != 0);
|
||||
|
||||
/* Check signs */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1773) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 35);
|
||||
bh_unit_assert(bh_bigint_get_int(d) == 23);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(d) == 0);
|
||||
bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 1773);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, 1773) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -35);
|
||||
bh_unit_assert(bh_bigint_get_int(d) == 23);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(d) == 0);
|
||||
bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 1773);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -1773) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -35);
|
||||
bh_unit_assert(bh_bigint_get_int(d) == -23);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(d) != 0);
|
||||
bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -1773);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -1773) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, -50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == 35);
|
||||
bh_unit_assert(bh_bigint_get_int(d) == -23);
|
||||
bh_unit_assert(bh_bigint_is_negative(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_negative(d) != 0);
|
||||
bh_unit_assert(bh_bigint_mul(c, c, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_add(c, c, d) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_get_int(c) == -1773);
|
||||
|
||||
/* Check for error handling */
|
||||
a->error = 0;
|
||||
b->error = 0;
|
||||
c->error = 1;
|
||||
d->error = 1;
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(d) == 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 0;
|
||||
c->error = 0;
|
||||
d->error = 0;
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(d) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
d->error = 0;
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(d) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
d->error = 0;
|
||||
bh_unit_assert(bh_bigint_divmod(c, d, a, b) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(c) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(d) != 0);
|
||||
|
||||
/* Deallocate big integers */
|
||||
bh_bigint_free(a);
|
||||
bh_bigint_free(b);
|
||||
bh_bigint_free(c);
|
||||
bh_bigint_free(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int power(void)
|
||||
{
|
||||
bh_bigint_t *a, *b, *c, *d, *e;
|
||||
|
||||
/* Allocate big integers */
|
||||
a = bh_bigint_new();
|
||||
b = bh_bigint_new();
|
||||
c = bh_bigint_new();
|
||||
d = bh_bigint_new();
|
||||
e = bh_bigint_new();
|
||||
|
||||
bh_unit_assert(a != NULL);
|
||||
bh_unit_assert(b != NULL);
|
||||
bh_unit_assert(c != NULL);
|
||||
bh_unit_assert(d != NULL);
|
||||
bh_unit_assert(e != NULL);
|
||||
|
||||
/* Check sign */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 137) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK);
|
||||
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(d, e) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int64(e) == 2571353ll);
|
||||
|
||||
bh_unit_assert(bh_bigint_set_int(a, -137) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(d, e) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int64(e) == -2571353ll);
|
||||
|
||||
/* Power of zero */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 137) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(d, e) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int64(e) == 1);
|
||||
|
||||
/* Zero in some power */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 50) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(d, e) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int64(e) == 0);
|
||||
|
||||
/* Zero in power of zero */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int64(c, 10000000ll) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 0) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(d, e) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int64(e) == 1);
|
||||
|
||||
/* Error handling */
|
||||
a->error = 0;
|
||||
b->error = 0;
|
||||
c->error = 0;
|
||||
d->error = 1;
|
||||
e->error = 1;
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 3) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(d) == 0);
|
||||
bh_unit_assert(bh_bigint_is_error(e) == 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 0;
|
||||
c->error = 0;
|
||||
d->error = 0;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 3) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(d) != 0);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 1;
|
||||
c->error = 0;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 0;
|
||||
c->error = 1;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 0;
|
||||
c->error = 1;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
a->error = 0;
|
||||
b->error = 1;
|
||||
c->error = 1;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
a->error = 1;
|
||||
b->error = 1;
|
||||
c->error = 1;
|
||||
e->error = 0;
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) != BH_OK);
|
||||
bh_unit_assert(bh_bigint_is_error(e) != 0);
|
||||
|
||||
/* Large powers */
|
||||
/* TODO: Replace this with some better test */
|
||||
bh_unit_assert(bh_bigint_set_int(a, 137) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(b, 2048) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_set_int(c, 100) == BH_OK);
|
||||
|
||||
bh_unit_assert(bh_bigint_pow(d, a, 2048) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_mod(d, d, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_powm(e, a, b, c) == BH_OK);
|
||||
bh_unit_assert(bh_bigint_equal(d, e) == 0);
|
||||
bh_unit_assert(bh_bigint_get_int(d) == 21);
|
||||
|
||||
/* Deallocate big integers */
|
||||
bh_bigint_free(a);
|
||||
bh_bigint_free(b);
|
||||
bh_bigint_free(c);
|
||||
bh_bigint_free(d);
|
||||
bh_bigint_free(e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
/* Add unit tests */
|
||||
bh_unit_add("fields", fields);
|
||||
bh_unit_add("round_trip", round_trip);
|
||||
bh_unit_add("add_sub", add_sub);
|
||||
bh_unit_add("multiplication", multiplication);
|
||||
bh_unit_add("logic", logic);
|
||||
bh_unit_add("division", division);
|
||||
bh_unit_add("power", power);
|
||||
|
||||
return bh_unit_run();
|
||||
}
|
||||
@@ -20,3 +20,10 @@ set(BHUNIT_HEADER
|
||||
# Library
|
||||
add_library(bhunit STATIC ${BHUNIT_SOURCE} ${BHUNIT_HEADER})
|
||||
target_include_directories(bhunit PUBLIC include)
|
||||
|
||||
# Enable warnings and pedantics
|
||||
if(MSVC)
|
||||
target_compile_options(bhunit PRIVATE /W4)
|
||||
else()
|
||||
target_compile_options(bhunit PRIVATE -Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
@@ -9,10 +9,11 @@ typedef struct bh_unit_s
|
||||
} bh_unit_t;
|
||||
|
||||
static bh_unit_t *root = NULL;
|
||||
static bh_unit_t *last = NULL;
|
||||
|
||||
void bh_unit_add(const char *name, bh_unit_cb_t func)
|
||||
{
|
||||
bh_unit_t *unit, *current;
|
||||
bh_unit_t *unit;
|
||||
|
||||
unit = malloc(sizeof(*unit));
|
||||
if (!unit)
|
||||
@@ -22,14 +23,11 @@ void bh_unit_add(const char *name, bh_unit_cb_t func)
|
||||
unit->func = func;
|
||||
unit->next = NULL;
|
||||
|
||||
current = root;
|
||||
while (current && current->next)
|
||||
current = current->next;
|
||||
|
||||
if (current)
|
||||
current->next = unit;
|
||||
if (last)
|
||||
last->next = unit;
|
||||
else
|
||||
root = unit;
|
||||
last = unit;
|
||||
}
|
||||
|
||||
int bh_unit_run(void)
|
||||
|
||||
Reference in New Issue
Block a user